From fc0fb1e540b1776727f49054727ba68ab4230eb8 Mon Sep 17 00:00:00 2001 From: mrBovo Date: Thu, 26 Jun 2025 12:19:39 +0200 Subject: [PATCH] BalancerV3: SwapAdapter and Substreams (#126) * feat: add balancer swapAdapter and Substreams * fix: undo tycho-substreams logs, ignore abi on rustmft * ci: prevent warnings from failing CI * ci: skip size check on CI * chore: forge fmt * feat: vault balance from storage Vault contract tokenBalance message are set according to the vault storage changes in the `_reserveOf` storage variable VaultStorage.sol contract This was the culprit that caused the failure in simulation since balancer enforces the invariant that `token.balanceOf(vault_addr) == _reservesOf[token]` * ci: warnings * fix: avoid duplicated balance changes * fix: order by ordinal * chore: format * feat: extract new contracts before extracting balance changes * feat: skip unnecessary steps if no balance change is found * refactor: filter out account balances for tokens that aren't part of any protocol components. On the indexer side, when we receive an account balance, we need to know about the token. This commit ensure that the token was introduced before we emit any account balance with it. * refactor: don't index liquidity buffers. Liquidity buffers rely on rate providers. Therefore we need DCI (feature to be able to index previously created contract) to deal with them. * refactor: cleanup tests and add docstrings * chore: lock tycho-substreams version * ci: set Foundry workflow to use stable foundry * feat(DCI): Add DCI Entrypoints to BalancerV3 components (#218) * refactor: fix typo in weighted_pool_factory_contract name * feat: add rate_providers static attributes * feat: add DCI entrypoints to BalancerV3 components * fix: set default trade price to Fraction(0, 1) * feat: remove buffers as components Buffers are to be used internally by Boosted pools (stable/weighted pools that use ERC4626 tokens). They are not to be treated as a separate swap component. * test: update test blocks Extend tests some tests block range to ensure liquidity was added to the pool and can be simulated on * feat: remove buffers as components Remove balance updates for buffer components * feat: listen for pool pause/unpause events * chore: formating * fix: encoding call data * test: update Balancer V3 tests to use DCI * test: set indexer log level to info * docs: add comment on support of boosted pools * feat: update balancer v3 package version --------- Co-authored-by: Thales Co-authored-by: zizou <111426680+flopell@users.noreply.github.com> Co-authored-by: Louise Poole Co-authored-by: Louise Poole --- .github/workflows/evm.yml | 6 +- evm/foundry.toml | 9 +- evm/src/balancer-v3/BalancerV3SwapAdapter.sol | 160 + .../lib/BalancerCustomWrapHelpers.sol | 511 ++ .../balancer-v3/lib/BalancerERC20Helpers.sol | 314 + .../lib/BalancerERC4626Helpers.sol | 393 ++ .../balancer-v3/lib/BalancerInterfaces.sol | 206 + evm/src/balancer-v3/lib/BalancerStorage.sol | 42 + .../balancer-v3/lib/BalancerSwapHelpers.sol | 247 + evm/src/balancer-v3/lib/BalancerV3Errors.sol | 661 +++ evm/src/balancer-v3/manifest.yaml | 36 + evm/src/libraries/CustomBytesAppend.sol | 108 + evm/test/BalancerV3SwapAdapter.t.sol | 1310 ++++ evm/test/interfaces/IBufferRouter.sol | 14 + evm/test/mocks/MockSETHx.sol | 37 + evm/test/mocks/MockSGOETH.sol | 40 + evm/test/mocks/MockSUSDC.sol | 37 + substreams/Cargo.lock | 67 +- substreams/Cargo.toml | 1 + .../crates/tycho-substreams/src/contract.rs | 6 +- substreams/ethereum-balancer-v3/Cargo.lock | 1330 +++++ substreams/ethereum-balancer-v3/Cargo.toml | 34 + substreams/ethereum-balancer-v3/Readme.md | 38 + .../abi/stable_pool_contract.abi.json | 1 + .../abi/stable_pool_factory_contract.abi.json | 1 + .../abi/vault_contract.abi.json | 1 + .../abi/weighted_pool_contract.abi.json | 1 + .../weighted_pool_factory_contract.abi.json | 1 + substreams/ethereum-balancer-v3/buf.gen.yaml | 11 + substreams/ethereum-balancer-v3/build.rs | 50 + .../integration_test.tycho.yaml | 110 + .../ethereum-balancer-v3/src/abi/mod.rs | 7 + .../src/abi/stable_pool_contract.rs | 5241 +++++++++++++++++ .../src/abi/stable_pool_factory_contract.rs | 2008 +++++++ .../src/abi/vault_contract.rs | 4856 +++++++++++++++ .../src/abi/weighted_pool_contract.rs | 4488 ++++++++++++++ .../src/abi/weighted_pool_factory_contract.rs | 2022 +++++++ substreams/ethereum-balancer-v3/src/lib.rs | 3 + .../ethereum-balancer-v3/src/modules.rs | 541 ++ .../src/pool_factories.rs | 119 + .../ethereum-balancer-v3/substreams.yaml | 78 + substreams/rustfmt.toml | 3 +- testing/src/runner/tycho.py | 2 + 43 files changed, 25137 insertions(+), 14 deletions(-) create mode 100644 evm/src/balancer-v3/BalancerV3SwapAdapter.sol create mode 100644 evm/src/balancer-v3/lib/BalancerCustomWrapHelpers.sol create mode 100644 evm/src/balancer-v3/lib/BalancerERC20Helpers.sol create mode 100644 evm/src/balancer-v3/lib/BalancerERC4626Helpers.sol create mode 100644 evm/src/balancer-v3/lib/BalancerInterfaces.sol create mode 100644 evm/src/balancer-v3/lib/BalancerStorage.sol create mode 100644 evm/src/balancer-v3/lib/BalancerSwapHelpers.sol create mode 100644 evm/src/balancer-v3/lib/BalancerV3Errors.sol create mode 100644 evm/src/balancer-v3/manifest.yaml create mode 100644 evm/src/libraries/CustomBytesAppend.sol create mode 100644 evm/test/BalancerV3SwapAdapter.t.sol create mode 100644 evm/test/interfaces/IBufferRouter.sol create mode 100644 evm/test/mocks/MockSETHx.sol create mode 100644 evm/test/mocks/MockSGOETH.sol create mode 100644 evm/test/mocks/MockSUSDC.sol create mode 100644 substreams/ethereum-balancer-v3/Cargo.lock create mode 100644 substreams/ethereum-balancer-v3/Cargo.toml create mode 100644 substreams/ethereum-balancer-v3/Readme.md create mode 100644 substreams/ethereum-balancer-v3/abi/stable_pool_contract.abi.json create mode 100644 substreams/ethereum-balancer-v3/abi/stable_pool_factory_contract.abi.json create mode 100644 substreams/ethereum-balancer-v3/abi/vault_contract.abi.json create mode 100644 substreams/ethereum-balancer-v3/abi/weighted_pool_contract.abi.json create mode 100644 substreams/ethereum-balancer-v3/abi/weighted_pool_factory_contract.abi.json create mode 100644 substreams/ethereum-balancer-v3/buf.gen.yaml create mode 100644 substreams/ethereum-balancer-v3/build.rs create mode 100644 substreams/ethereum-balancer-v3/integration_test.tycho.yaml create mode 100644 substreams/ethereum-balancer-v3/src/abi/mod.rs create mode 100644 substreams/ethereum-balancer-v3/src/abi/stable_pool_contract.rs create mode 100644 substreams/ethereum-balancer-v3/src/abi/stable_pool_factory_contract.rs create mode 100644 substreams/ethereum-balancer-v3/src/abi/vault_contract.rs create mode 100644 substreams/ethereum-balancer-v3/src/abi/weighted_pool_contract.rs create mode 100644 substreams/ethereum-balancer-v3/src/abi/weighted_pool_factory_contract.rs create mode 100644 substreams/ethereum-balancer-v3/src/lib.rs create mode 100644 substreams/ethereum-balancer-v3/src/modules.rs create mode 100644 substreams/ethereum-balancer-v3/src/pool_factories.rs create mode 100644 substreams/ethereum-balancer-v3/substreams.yaml diff --git a/.github/workflows/evm.yml b/.github/workflows/evm.yml index a2429d3..aeefc9c 100644 --- a/.github/workflows/evm.yml +++ b/.github/workflows/evm.yml @@ -1,4 +1,4 @@ -name: test & check evm +name: Foundry CI on: pull_request: @@ -13,7 +13,7 @@ jobs: strategy: fail-fast: true - name: Foundry project + name: Foundry Lint & Test runs-on: ubuntu-latest defaults: run: @@ -26,7 +26,7 @@ jobs: - name: Install Foundry uses: foundry-rs/foundry-toolchain@v1 with: - version: nightly + version: stable - name: Run Forge build run: | diff --git a/evm/foundry.toml b/evm/foundry.toml index 23cb8a0..fb0dfb5 100644 --- a/evm/foundry.toml +++ b/evm/foundry.toml @@ -3,11 +3,17 @@ src = "src" out = "out" libs = ["lib"] via_ir = true +optimizer = true +optimizer_runs = 200 solc_version = "0.8.27" # 0.8.25 and 0.8.26 are broken with via-ir (see https://github.com/ethereum/solidity/issues/15004) +evm_version = 'cancun' + +[profile.ci] +size_check = false [rpc_endpoints] mainnet = "${ETH_RPC_URL}" - +sepolia = "${SEPOLIA_RPC_URL}" [fmt] line_length = 80 @@ -20,3 +26,4 @@ mainnet = { key = "${ETHERSCAN_MAINNET_KEY}" } [[profile.default.fs_permissions]] access = "read-write" path = "out" + diff --git a/evm/src/balancer-v3/BalancerV3SwapAdapter.sol b/evm/src/balancer-v3/BalancerV3SwapAdapter.sol new file mode 100644 index 0000000..3dd3a03 --- /dev/null +++ b/evm/src/balancer-v3/BalancerV3SwapAdapter.sol @@ -0,0 +1,160 @@ +// SPDX-License-Identifier: AGPL-3.0-or-later +pragma solidity ^0.8.26; + +import "./lib/BalancerSwapHelpers.sol"; + +/** + * @title Balancer V3 Swap Adapter + * @dev Supports: + * Direct Swaps: + * - ETH<->ERC20 + * - ERC20<->ERC20 + * - ERC4626<->ERC4626 + * - ERC4626<->ERC20 + * + * 2 steps: + * - (ERC20->ERC20)->ERC4626: swap, wrap_0 + * - (ERC4626->ERC20)->ERC4626: swap, wrap_1 + * + * - (ERC4626->ERC4626)->ERC20: swap, unwrap_0 + * - (ERC20->ERC4626)->ERC20; swap, unwrap_1 + * + * - ERC20->(ERC4626->ERC4626): wrap, swap_0 + * - ERC20->(ERC4626->ERC20); wrap, swap_1 + * + * - ERC4626->(ERC20->ERC20): unwrap, swap_0 + * - ERC4626->(ERC20->ERC4626): unwrap, swap_1 + * + * 3 steps: + * - ERC20->(ERC4626->ERC4626)->ERC20 + * - ERC4626->(ERC20->ERC20)->ERC4626 + */ +contract BalancerV3SwapAdapter is BalancerSwapHelpers { + constructor( + address payable vault_, + address _router, + address _permit2, + address _WETH_ADDRESS + ) { + vault = IVault(vault_); + router = IBatchRouter(_router); + permit2 = _permit2; + WETH_ADDRESS = _WETH_ADDRESS; + } + + /// @dev Enable ETH receiving + receive() external payable {} + + /// @inheritdoc ISwapAdapter + function price( + bytes32 _poolId, + address _sellToken, + address _buyToken, + uint256[] memory _specifiedAmounts + ) external override returns (Fraction[] memory _prices) { + _prices = new Fraction[](_specifiedAmounts.length); + + for (uint256 i = 0; i < _specifiedAmounts.length; i++) { + _prices[i] = + getPriceAt(_poolId, _sellToken, _buyToken, _specifiedAmounts[i]); + } + } + + /// @inheritdoc ISwapAdapter + function swap( + bytes32 poolId, + address sellToken, + address buyToken, + OrderSide side, + uint256 specifiedAmount + ) external override returns (Trade memory trade) { + if (specifiedAmount == 0) { + // Price defaults to Fraction(0, 0) which breaks simulation. We need + // to explicitly set it. + trade.price = Fraction(0, 1); + return trade; + } + + uint256 gasBefore = gasleft(); + + // perform swap (forward to middleware) + trade.calculatedAmount = + swapMiddleware(poolId, sellToken, buyToken, side, specifiedAmount); + + trade.gasUsed = gasBefore - gasleft(); + + // as post-trade price cannot be calculated in an external call, we + // return the trade price here + trade.price = Fraction(trade.calculatedAmount, specifiedAmount); + } + + /// @inheritdoc ISwapAdapter + function getLimits(bytes32 poolId, address sellToken, address buyToken) + external + view + override + returns (uint256[] memory limits) + { + limits = getLimitsMiddleware(poolId, sellToken, buyToken); + } + + /// @inheritdoc ISwapAdapter + function getCapabilities(bytes32, address, address) + external + pure + override + returns (Capability[] memory capabilities) + { + capabilities = new Capability[](3); + capabilities[0] = Capability.SellOrder; + capabilities[1] = Capability.BuyOrder; + capabilities[2] = Capability.HardLimits; + } + + /// @inheritdoc ISwapAdapter + function getTokens(bytes32 poolId) + external + view + override + returns (address[] memory tokens) + { + address poolAddress = address(bytes20(poolId)); + // Is accessing to vault to get the tokens of a pool / Here could be + // where it was reverting the test + IERC20[] memory tokens_ = vault.getPoolTokens(poolAddress); + tokens = new address[](tokens_.length); + + for (uint256 i = 0; i < tokens_.length; i++) { + tokens[i] = address(tokens_[i]); + } + } + + function getPoolIds(uint256, uint256) + external + pure + override + returns (bytes32[] memory) + { + revert NotImplemented("BalancerV3SwapAdapter.getPoolIds"); + } + + /** + * @dev Returns the price of the swap + * @dev The price is not scaled by the token decimals + * @param pool The ID of the trading pool. + * @param sellToken The token being sold. + * @param buyToken The token being bought. + * @param specifiedAmount The amount to be traded. + */ + function getPriceAt( + bytes32 pool, + address sellToken, + address buyToken, + uint256 specifiedAmount + ) internal returns (Fraction memory calculatedPrice) { + calculatedPrice = Fraction( + getAmountOutMiddleware(pool, sellToken, buyToken, specifiedAmount), + specifiedAmount + ); + } +} diff --git a/evm/src/balancer-v3/lib/BalancerCustomWrapHelpers.sol b/evm/src/balancer-v3/lib/BalancerCustomWrapHelpers.sol new file mode 100644 index 0000000..add59f6 --- /dev/null +++ b/evm/src/balancer-v3/lib/BalancerCustomWrapHelpers.sol @@ -0,0 +1,511 @@ +//SPDX-License-Identifier: AGPL-3.0-or-later +pragma solidity ^0.8.26; + +import "./BalancerERC20Helpers.sol"; + +abstract contract BalancerCustomWrapHelpers is BalancerERC20Helpers { + using SafeERC20 for IERC20; + + function isERC4626(address token) internal view returns (bool) { + if (token == WETH_ADDRESS) { + return false; + } + try IERC4626(token).asset() { + try IERC4626(token).maxRedeem(msg.sender) { + return true; + } catch { + // Proceed to the next try-catch + } + } catch { + // return false; + } + + return false; + } + + function getCustomWrap(address sellToken, address buyToken, address pool) + internal + view + returns ( + CUSTOM_WRAP_KIND kind, + address sellTokenOutput, + address buyTokenOutput + ) + { + IERC20[] memory tokens = vault.getPoolTokens(pool); + + if (isERC4626(sellToken) && isERC4626(buyToken)) { + // 4626-(20-20)-4626 + address sellTokenAsset = IERC4626(sellToken).asset(); + address buyTokenAsset = IERC4626(buyToken).asset(); + + for (uint256 i = 0; i < tokens.length; i++) { + address token = address(tokens[i]); + if ( + sellTokenOutput != address(0) + && buyTokenOutput != address(0) + ) { + // prevent other findings, use the firsts as default + break; + } + + if (token == sellTokenAsset) { + sellTokenOutput = token; // asset + } + if (token == buyTokenAsset) { + buyTokenOutput = token; // asset + } + } + + require( + sellTokenOutput != address(0) && buyTokenOutput != address(0), + "CUSTOM_WRAP(4626-4626): Invalid Pool" + ); + kind = CUSTOM_WRAP_KIND.ERC4626_TO_ERC4626; + } else if (!isERC4626(sellToken) && !isERC4626(buyToken)) { + for (uint256 i = 0; i < tokens.length; i++) { + address token = address(tokens[i]); + if (isERC4626(token)) { + if ( + sellTokenOutput != address(0) + && buyTokenOutput != address(0) + ) { + // prevent other findings, use the firsts as default + break; + } + + if (IERC4626(token).asset() == sellToken) { + sellTokenOutput = token; // share + } + if (IERC4626(token).asset() == buyToken) { + buyTokenOutput = token; // share + } + } + } + + require( + sellTokenOutput != address(0) && buyTokenOutput != address(0), + "CUSTOM_WRAP(4626-4626): Invalid Pool" + ); + kind = CUSTOM_WRAP_KIND.ERC20_TO_ERC20; + } else { + revert("CUSTOM_WRAP: Invalid tokens"); + } + } + + function prepareSellCustomWrap( + address pool, + address _sellToken, + address buyToken, + uint256 specifiedAmount, + CUSTOM_WRAP_KIND kind, + address sellTokenOutput, + address buyTokenOutput + ) + internal + view + returns (IBatchRouter.SwapPathExactAmountIn[] memory paths) + { + IBatchRouter.SwapPathStep[] memory steps = + new IBatchRouter.SwapPathStep[](3); + + if (kind == CUSTOM_WRAP_KIND.ERC20_TO_ERC20) { + // Step 1: sellToken.asset() -> sellToken.shares() + (,, IBatchRouter.SwapPathStep memory step0) = createWrapOrUnwrapPath( + sellTokenOutput, + specifiedAmount, + IVault.WrappingDirection.WRAP, + false + ); + steps[0] = step0; + + // Step 2: sellToken.shares() -> buyToken.shares() + (,, IBatchRouter.SwapPathStep memory step1) = createERC20Path( + pool, + IERC20(sellTokenOutput), + IERC20(buyTokenOutput), + specifiedAmount, + false, + false + ); + steps[1] = step1; + + // Step 3: buyToken.shares() -> buyToken.asset() + (,, IBatchRouter.SwapPathStep memory step2) = createWrapOrUnwrapPath( + buyTokenOutput, + specifiedAmount, + IVault.WrappingDirection.UNWRAP, + false + ); + steps[2] = step2; + + paths = new IBatchRouter.SwapPathExactAmountIn[](1); + paths[0] = IBatchRouter.SwapPathExactAmountIn({ + tokenIn: IERC20(_sellToken), + steps: steps, + exactAmountIn: specifiedAmount, + minAmountOut: 1 + }); + } else { + // ERC4626_TO_ERC4626 + // Step 1: sellToken.shares() -> sellToken.asset() + (,, IBatchRouter.SwapPathStep memory step0) = createWrapOrUnwrapPath( + _sellToken, + specifiedAmount, + IVault.WrappingDirection.UNWRAP, + false + ); + steps[0] = step0; + + // Step 2: sellToken.asset() -> buyToken.asset() + (,, IBatchRouter.SwapPathStep memory step1) = createERC20Path( + pool, + IERC20(sellTokenOutput), + IERC20(buyTokenOutput), + specifiedAmount, + false, + false + ); + steps[1] = step1; + + // Step 3: buyToken.asset() -> buyToken.shares() + (,, IBatchRouter.SwapPathStep memory step2) = createWrapOrUnwrapPath( + buyToken, specifiedAmount, IVault.WrappingDirection.WRAP, false + ); + steps[2] = step2; + + paths = new IBatchRouter.SwapPathExactAmountIn[](1); + paths[0] = IBatchRouter.SwapPathExactAmountIn({ + tokenIn: IERC20(_sellToken), + steps: steps, + exactAmountIn: specifiedAmount, + minAmountOut: 1 + }); + } + } + + /** + * @notice Get amount out for custom wrap + */ + function getAmountOutCustomWrap( + address pool, + address _sellToken, + address buyToken, + uint256 specifiedAmount, + CUSTOM_WRAP_KIND kind, + address sellTokenOutput, + address buyTokenOutput + ) internal returns (uint256 calculatedAmount) { + IBatchRouter.SwapPathExactAmountIn[] memory paths = + prepareSellCustomWrap( + pool, + _sellToken, + buyToken, + specifiedAmount, + kind, + sellTokenOutput, + buyTokenOutput + ); + + (,, uint256[] memory amountsOut) = + router.querySwapExactIn(paths, address(0), bytes("")); + + calculatedAmount = amountsOut[0]; + } + + /** + * @notice Perform a custom sell with wrap/unwrap + * @dev + * - Does not support ETH(gas), use wrapped ETH instead + * @param pool the ERC4626 pool containing sellToken.share() and + * buyToken.share(), or the ERC20 pool containing sellToken.asset() and + * buyToken.asset(), depending on the kind + * @param _sellToken ERC20 token being sold if kind == ERC20_TO_ERC20, + * ERC4626 else + * @param _buyToken ERC20 token being bought if kind == ERC20_TO_ERC20, + * ERC4626 else + * @param kind The Custom wrap kind + * @param sellTokenOutput sellToken.share() if sellToken is kind == + * ERC20_TO_ERC20, sellToken.asset() else + * @param buyTokenOutput buyToken.share() if sellToken is kind == + * ERC20_TO_ERC20, buyToken.asset() else + * @param specifiedAmount The amount of _buyToken bought + */ + function sellCustomWrap( + address pool, + address _sellToken, + address _buyToken, + uint256 specifiedAmount, + CUSTOM_WRAP_KIND kind, + address sellTokenOutput, + address buyTokenOutput + ) internal returns (uint256 calculatedAmount) { + IERC20 sellToken = IERC20(_sellToken); + + // approve and transfer + IERC20(sellToken).safeTransferFrom( + msg.sender, address(this), specifiedAmount + ); + sellToken.safeIncreaseAllowance(permit2, specifiedAmount); + IPermit2(permit2).approve( + address(sellToken), + address(router), + type(uint160).max, + type(uint48).max + ); + + IBatchRouter.SwapPathExactAmountIn[] memory paths = + prepareSellCustomWrap( + pool, + _sellToken, + _buyToken, + specifiedAmount, + kind, + sellTokenOutput, + buyTokenOutput + ); + + (,, uint256[] memory amountsOut) = + router.swapExactIn(paths, type(uint256).max, false, bytes("")); + + calculatedAmount = amountsOut[0]; + + IERC20(_buyToken).safeTransfer(msg.sender, calculatedAmount); + } + + /** + * @notice Perform a custom sell with wrap/unwrap + * @param specifiedAmount The amount of buyToken to buy + * @return calculatedAmount The amount of sellToken spent + */ + function buyCustomWrap( + address pool, + address _sellToken, + address _buyToken, + uint256 specifiedAmount, + CUSTOM_WRAP_KIND kind, + address sellTokenOutput, + address buyTokenOutput + ) internal returns (uint256 calculatedAmount) { + IBatchRouter.SwapPathStep[] memory steps = + new IBatchRouter.SwapPathStep[](3); + IERC20 sellToken = IERC20(_sellToken); + + // get balance of sender + uint256 initialSenderBalance = IERC20(sellToken).balanceOf(msg.sender); + + // approve and transfer + IERC20(sellToken).safeTransferFrom( + msg.sender, address(this), initialSenderBalance + ); + sellToken.safeIncreaseAllowance(permit2, type(uint256).max); + IPermit2(permit2).approve( + address(sellToken), + address(router), + type(uint160).max, + type(uint48).max + ); + + if (kind == CUSTOM_WRAP_KIND.ERC20_TO_ERC20) { + // Step 1: sellToken.asset() -> sellToken.shares() + (,, IBatchRouter.SwapPathStep memory step0) = createWrapOrUnwrapPath( + sellTokenOutput, + specifiedAmount, + IVault.WrappingDirection.WRAP, + false + ); + steps[0] = step0; + + // Step 2: sellToken.shares() -> buyToken.shares() + (,, IBatchRouter.SwapPathStep memory step1) = createERC20Path( + pool, + IERC4626(sellTokenOutput), + IERC4626(buyTokenOutput), + specifiedAmount, + true, + false + ); + steps[1] = step1; + + // Step 3: buyToken.shares() -> buyToken.asset() + (,, IBatchRouter.SwapPathStep memory step2) = createWrapOrUnwrapPath( + buyTokenOutput, + specifiedAmount, + IVault.WrappingDirection.UNWRAP, + true + ); + steps[2] = step2; + + IBatchRouter.SwapPathExactAmountOut[] memory paths = + new IBatchRouter.SwapPathExactAmountOut[](1); + paths[0] = IBatchRouter.SwapPathExactAmountOut({ + tokenIn: IERC20(_sellToken), + steps: steps, + maxAmountIn: initialSenderBalance, + exactAmountOut: specifiedAmount + }); + + (,, uint256[] memory amountsIn) = + router.swapExactOut(paths, type(uint256).max, false, bytes("")); + + calculatedAmount = amountsIn[0]; + + IERC20(_buyToken).safeTransfer(msg.sender, specifiedAmount); + } else { + // ERC4626_TO_ERC4626 + // Step 1: sellToken.shares() -> sellToken.asset() + (,, IBatchRouter.SwapPathStep memory step0) = createWrapOrUnwrapPath( + _sellToken, + specifiedAmount, + IVault.WrappingDirection.UNWRAP, + true + ); + steps[0] = step0; + + // Step 2: sellToken.asset() -> buyToken.asset() + (,, IBatchRouter.SwapPathStep memory step1) = createERC20Path( + pool, + IERC20(sellTokenOutput), + IERC20(buyTokenOutput), + specifiedAmount, + true, + false + ); + steps[1] = step1; + + // Step 3: buyToken.asset() -> buyToken.shares() + (,, IBatchRouter.SwapPathStep memory step2) = createWrapOrUnwrapPath( + _buyToken, specifiedAmount, IVault.WrappingDirection.WRAP, false + ); + steps[2] = step2; + + IBatchRouter.SwapPathExactAmountOut[] memory paths = + new IBatchRouter.SwapPathExactAmountOut[](1); + paths[0] = IBatchRouter.SwapPathExactAmountOut({ + tokenIn: IERC20(_sellToken), + steps: steps, + maxAmountIn: initialSenderBalance, + exactAmountOut: specifiedAmount + }); + + (,, uint256[] memory amountsIn) = + router.swapExactOut(paths, type(uint256).max, false, bytes("")); + + calculatedAmount = amountsIn[0]; + + IERC20(_buyToken).safeTransfer(msg.sender, specifiedAmount); + } + + // transfer back sellToken to sender + IERC20(sellToken).safeTransferFrom( + address(this), msg.sender, initialSenderBalance - calculatedAmount + ); + } + + /** + * @notice Create a wrap or unwrap path in BalancerV3 router using buffer + * pools + * @param token (ERC4626) token to Wrap or Unwrap + * @param amount Amount to buy if isBuy, amount to sell else + * @param direction Wrap or Unwrap + * @param isBuy True if buy, false if sell + */ + function createWrapOrUnwrapPath( + address token, + uint256 amount, + IVault.WrappingDirection direction, + bool isBuy + ) + internal + view + returns ( + IBatchRouter.SwapPathExactAmountIn memory sellPath, + IBatchRouter.SwapPathExactAmountOut memory buyPath, + IBatchRouter.SwapPathStep memory step + ) + { + step = IBatchRouter.SwapPathStep({ + pool: token, + tokenOut: direction == IVault.WrappingDirection.UNWRAP + ? IERC20(IERC4626(token).asset()) + : IERC20(token), + isBuffer: true + }); + IBatchRouter.SwapPathStep[] memory steps = + new IBatchRouter.SwapPathStep[](1); + steps[0] = step; + + if (isBuy) { + buyPath = IBatchRouter.SwapPathExactAmountOut({ + tokenIn: direction == IVault.WrappingDirection.UNWRAP + ? IERC20(token) + : IERC20(IERC4626(token).asset()), + steps: steps, + maxAmountIn: direction == IVault.WrappingDirection.UNWRAP + ? IERC20(token).balanceOf(address(this)) + : IERC20(IERC4626(token).asset()).balanceOf(address(this)), + exactAmountOut: amount + }); + } else { + sellPath = IBatchRouter.SwapPathExactAmountIn({ + tokenIn: direction == IVault.WrappingDirection.UNWRAP + ? IERC20(token) + : IERC20(IERC4626(token).asset()), + steps: steps, + exactAmountIn: amount, + minAmountOut: 1 + }); + } + } + + function getLimitsCustomWrap( + bytes32 poolId, + address sellToken, + address buyToken, + CUSTOM_WRAP_KIND kind, + address sellTokenOutput, + address buyTokenOutput + ) internal view returns (uint256[] memory limits) { + limits = new uint256[](2); + address pool = address(bytes20(poolId)); + + (IERC20[] memory tokens,, uint256[] memory balancesRaw,) = + vault.getPoolTokenInfo(pool); + + if (kind == CUSTOM_WRAP_KIND.ERC20_TO_ERC20) { + // pool contains sellToken.share() and buyToken.share() + for (uint256 i = 0; i < tokens.length; i++) { + address token = address(tokens[i]); + + if (token == sellTokenOutput) { + limits[0] = IERC4626(sellTokenOutput).previewRedeem( + (balancesRaw[i] * RESERVE_LIMIT_FACTOR) / 10 + ); + } else if (token == buyTokenOutput) { + limits[1] = IERC4626(buyTokenOutput).previewRedeem( + (balancesRaw[i] * RESERVE_LIMIT_FACTOR) / 10 + ); + } + } + + return limits; + } + + // pool contains sellToken.asset() and buyToken.asset() + IERC20 underlyingSellToken = IERC20(IERC4626(sellToken).asset()); + IERC20 underlyingBuyToken = IERC20(IERC4626(buyToken).asset()); + for (uint256 i = 0; i < tokens.length; i++) { + if (tokens[i] == underlyingSellToken) { + limits[0] = IERC4626(sellToken).previewDeposit( + (balancesRaw[i] * RESERVE_LIMIT_FACTOR) / 10 + ); + } + if (tokens[i] == underlyingBuyToken) { + limits[1] = IERC4626(buyToken).previewDeposit( + (balancesRaw[i] * RESERVE_LIMIT_FACTOR) / 10 + ); + } + } + return limits; + } +} diff --git a/evm/src/balancer-v3/lib/BalancerERC20Helpers.sol b/evm/src/balancer-v3/lib/BalancerERC20Helpers.sol new file mode 100644 index 0000000..bcfb1c3 --- /dev/null +++ b/evm/src/balancer-v3/lib/BalancerERC20Helpers.sol @@ -0,0 +1,314 @@ +//SPDX-License-Identifier: AGPL-3.0-or-later +pragma solidity ^0.8.26; + +import "./BalancerStorage.sol"; + +abstract contract BalancerERC20Helpers is BalancerStorage { + using SafeERC20 for IERC20; + + /** + * @dev Returns the amount of sellToken tokens to spend for a trade + * @param path The path to get amountIn for + * @return amountIn The amount of tokens to spend. + */ + function getAmountIn(IBatchRouter.SwapPathExactAmountOut memory path) + internal + returns (uint256 amountIn) + { + bytes memory userData; // empty bytes + + IBatchRouter.SwapPathExactAmountOut[] memory paths = + new IBatchRouter.SwapPathExactAmountOut[](1); + paths[0] = path; + + (,, uint256[] memory amountsIn) = + router.querySwapExactOut(paths, address(0), userData); + + // return + amountIn = amountsIn[0]; + } + + /** + * @dev Returns the amount of buyToken tokens received from a trade + * @param path The path of the trade. + * @return amountOut The amount of tokens to receive. + */ + function getAmountOut(IBatchRouter.SwapPathExactAmountIn memory path) + internal + returns (uint256 amountOut) + { + bytes memory userData; // empty bytes + + IBatchRouter.SwapPathExactAmountIn[] memory paths = + new IBatchRouter.SwapPathExactAmountIn[](1); + paths[0] = path; + + (,, uint256[] memory amountsOut) = + router.querySwapExactIn(paths, address(this), userData); + + amountOut = amountsOut[0]; + } + + /** + * @dev Perform a sell order for ERC20 tokens + * @param pool The address of the pool to trade in. + * @param sellToken The token being sold. + * @param buyToken The token being bought. + * @param specifiedAmount The amount to be traded. + * @param performTransfer Whether to perform a transfer to msg.sender or + * not(keeping tokens in the contract) + * @return calculatedAmount The amount of tokens received. + */ + function sellERC20ForERC20( + address pool, + IERC20 sellToken, + IERC20 buyToken, + uint256 specifiedAmount, + bool performTransfer + ) internal returns (uint256 calculatedAmount) { + // prepare constants + bytes memory userData; + bool isETHSell = address(sellToken) == address(0); + bool isETHBuy = address(buyToken) == address(0); + + // prepare path + (IBatchRouter.SwapPathExactAmountIn memory sellPath,,) = createERC20Path( + pool, + sellToken, + buyToken, + specifiedAmount, + false, + isETHSell || isETHBuy + ); + IBatchRouter.SwapPathExactAmountIn[] memory paths = + new IBatchRouter.SwapPathExactAmountIn[](1); + paths[0] = sellPath; + + // prepare swap + uint256[] memory amountsOut; + if (isETHSell) { + paths[0].tokenIn = IERC20(WETH_ADDRESS); + } else { + if (isETHBuy) { + // adjust parameters for ETH buy + paths[0].steps[0].tokenOut = IERC20(WETH_ADDRESS); + } + // Approve and Transfer ERC20 token + sellToken.safeTransferFrom( + msg.sender, address(this), specifiedAmount + ); + + sellToken.safeIncreaseAllowance(permit2, specifiedAmount); + IPermit2(permit2).approve( + address(sellToken), + address(router), + type(uint160).max, + type(uint48).max + ); + } + + // Swap (incl. WETH) + if (isETHSell) { + (,, amountsOut) = router.swapExactIn{value: specifiedAmount}( + paths, type(uint256).max, isETHSell || isETHBuy, userData + ); + } else { + (,, amountsOut) = router.swapExactIn( + paths, type(uint256).max, isETHSell || isETHBuy, userData + ); + } + + // transfer if required + if (performTransfer) { + if (isETHBuy) { + (bool sent,) = + payable(msg.sender).call{value: amountsOut[0]}(""); + require(sent, "Failed to transfer ETH"); + } else { + buyToken.safeTransfer(msg.sender, amountsOut[0]); + } + } + + // return amount + calculatedAmount = amountsOut[0]; + } + + /** + * @dev Perform a buy order for ERC20 tokens + * @param pool The address of the pool to trade in. + * @param sellToken The token being sold. + * @param buyToken The token being bought. + * @param specifiedAmount The amount to be traded. + * @param performTransfer Whether to perform a transfer to msg.sender or + * not(keeping tokens in the contract) + * @return calculatedAmount The amount of tokens received. + */ + function buyERC20WithERC20( + address pool, + IERC20 sellToken, + IERC20 buyToken, + uint256 specifiedAmount, + bool performTransfer + ) internal returns (uint256 calculatedAmount) { + // prepare constants + bytes memory userData; + bool isETHSell = address(sellToken) == address(0); + bool isETHBuy = address(buyToken) == address(0); + uint256 msgSenderBalance = + isETHSell ? address(this).balance : sellToken.balanceOf(msg.sender); + + // prepare path + (, IBatchRouter.SwapPathExactAmountOut memory buyPath,) = + createERC20Path( + pool, + sellToken, + buyToken, + specifiedAmount, + true, + isETHSell || isETHBuy + ); + IBatchRouter.SwapPathExactAmountOut[] memory paths = + new IBatchRouter.SwapPathExactAmountOut[](1); + paths[0] = buyPath; + + // prepare swap + uint256[] memory amountsIn; + if (isETHSell) { + // Set token in as WETH + paths[0].tokenIn = IERC20(WETH_ADDRESS); + } else { + if (isETHBuy) { + // adjust parameters for ETH buy + paths[0].steps[0].tokenOut = IERC20(WETH_ADDRESS); + } + + // Approve and Transfer ERC20 token + sellToken.safeTransferFrom( + msg.sender, address(this), msgSenderBalance + ); + sellToken.safeIncreaseAllowance(address(router), type(uint256).max); + sellToken.safeIncreaseAllowance(permit2, type(uint256).max); + IPermit2(permit2).approve( + address(sellToken), + address(router), + type(uint160).max, + type(uint48).max + ); + } + + // perform swap + if (isETHSell) { + (,, amountsIn) = router.swapExactOut{value: msgSenderBalance}( + paths, type(uint256).max, isETHSell || isETHBuy, userData + ); + } else { + (,, amountsIn) = router.swapExactOut( + paths, type(uint256).max, isETHSell || isETHBuy, userData + ); + } + + // transfer if required + if (performTransfer) { + if (isETHBuy) { + (bool sent,) = + payable(msg.sender).call{value: specifiedAmount}(""); + require(sent, "Failed to transfer ETH"); + } else { + buyToken.safeTransfer(msg.sender, specifiedAmount); + } + } + + // return amount + calculatedAmount = amountsIn[0]; + + // re-transfer back funds to msg.sender + if (isETHSell) { + (bool sent2,) = payable(msg.sender).call{ + value: msgSenderBalance - calculatedAmount + }(""); + require(sent2, "Failed to transfer ETH(2)"); + } else { + sellToken.safeTransfer( + msg.sender, msgSenderBalance - calculatedAmount + ); + } + } + + /** + * @notice Create a ERC20 swap path in BalancerV3 router + * @param sellToken (ERC20) token to Sell + * @param buyToken (ERC20) token to Buy + * @param specifiedAmount Amount to buy if isBuy, amount to sell else + * @param isBuy True if buy, false if sell + */ + function createERC20Path( + address pool, + IERC20 sellToken, + IERC20 buyToken, + uint256 specifiedAmount, + bool isBuy, + bool isETH + ) + internal + view + returns ( + IBatchRouter.SwapPathExactAmountIn memory sellPath, + IBatchRouter.SwapPathExactAmountOut memory buyPath, + IBatchRouter.SwapPathStep memory step + ) + { + uint256 maxAmountIn_ = address(this).balance; + if (!isETH) { + maxAmountIn_ = IERC20(sellToken).balanceOf(msg.sender); + } + + // prepare steps + step = IBatchRouter.SwapPathStep({ + pool: pool, + tokenOut: buyToken, + isBuffer: false + }); + IBatchRouter.SwapPathStep[] memory steps = + new IBatchRouter.SwapPathStep[](1); + steps[0] = step; + + if (isBuy) { + buyPath = IBatchRouter.SwapPathExactAmountOut({ + tokenIn: sellToken, + steps: steps, + maxAmountIn: maxAmountIn_, + exactAmountOut: specifiedAmount + }); + } else { + sellPath = IBatchRouter.SwapPathExactAmountIn({ + tokenIn: sellToken, + steps: steps, + exactAmountIn: specifiedAmount, + minAmountOut: 1 + }); + } + } + + function getLimitsERC20(bytes32 poolId, address sellToken, address buyToken) + internal + view + returns (uint256[] memory limits) + { + limits = new uint256[](2); + address pool = address(bytes20(poolId)); + + (IERC20[] memory tokens,, uint256[] memory balancesRaw,) = + vault.getPoolTokenInfo(pool); + (IERC20 sellTokenERC, IERC20 buyTokenERC) = + (IERC20(sellToken), IERC20(buyToken)); + // ERC4626-ERC4626, ERC20-ERC20 + for (uint256 i = 0; i < tokens.length; i++) { + if (tokens[i] == sellTokenERC) { + limits[0] = (balancesRaw[i] * RESERVE_LIMIT_FACTOR) / 10; + } + if (tokens[i] == buyTokenERC) { + limits[1] = (balancesRaw[i] * RESERVE_LIMIT_FACTOR) / 10; + } + } + } +} diff --git a/evm/src/balancer-v3/lib/BalancerERC4626Helpers.sol b/evm/src/balancer-v3/lib/BalancerERC4626Helpers.sol new file mode 100644 index 0000000..fa64fe9 --- /dev/null +++ b/evm/src/balancer-v3/lib/BalancerERC4626Helpers.sol @@ -0,0 +1,393 @@ +//SPDX-License-Identifier: AGPL-3.0-or-later +pragma solidity ^0.8.26; + +import "./BalancerCustomWrapHelpers.sol"; + +abstract contract BalancerERC4626Helpers is BalancerCustomWrapHelpers { + using SafeERC20 for IERC20; + + function getERC4626PathType( + address pool, + address sellToken, + address buyToken, + bool sellTokenFound + ) internal view returns (ERC4626_SWAP_TYPE kind, address outputAddress) { + IERC20[] memory tokens = vault.getPoolTokens(pool); + + if (sellTokenFound) { + // SWAP_WRAP and SWAP_UNWRAP + bool isERC4626BuyToken = isERC4626(buyToken); + + if (isERC4626BuyToken) { + kind = ERC4626_SWAP_TYPE.SWAP_WRAP; + } else { + for (uint256 i = 0; i < tokens.length; i++) { + address token = address(tokens[i]); + if (isERC4626(token) && IERC4626(token).asset() == buyToken) + { + outputAddress = token; // buyToken share + break; + } + } + require(outputAddress != address(0), "Token not found in pool"); + kind = ERC4626_SWAP_TYPE.SWAP_UNWRAP; + } + } else { + bool isERC4626SellToken = isERC4626(sellToken); + + if (isERC4626SellToken) { + kind = ERC4626_SWAP_TYPE.UNWRAP_SWAP; + } else { + for (uint256 i = 0; i < tokens.length; i++) { + address token = address(tokens[i]); + if ( + isERC4626(token) && IERC4626(token).asset() == sellToken + ) { + outputAddress = token; // sellToken share + break; + } + } + require(outputAddress != address(0), "Token not found in pool"); + kind = ERC4626_SWAP_TYPE.WRAP_SWAP; + } + } + } + + function prepareERC4626SellOrBuy( + address pool, + address _sellToken, + address _buyToken, + uint256 specifiedAmount, + ERC4626_SWAP_TYPE kind, + address outputAddress, + bool isBuy + ) + internal + view + returns ( + IBatchRouter.SwapPathExactAmountIn[] memory sellPath, + IBatchRouter.SwapPathExactAmountOut[] memory buyPath + ) + { + IBatchRouter.SwapPathStep[] memory steps; + + address sellToken = _sellToken == address(0) ? WETH_ADDRESS : _sellToken; + address buyToken = _buyToken == address(0) ? WETH_ADDRESS : _buyToken; + + if (kind == ERC4626_SWAP_TYPE.SWAP_WRAP) { + // !isERC4626(sellToken) && isERC4626(buyToken) and + // isERC4626(buyToken) && isERC4626(sellToken) + steps = new IBatchRouter.SwapPathStep[](2); + + // swap: sellToken -> buyToken.asset() + (,, steps[0]) = createERC20Path( + pool, + IERC20(sellToken), + IERC20(IERC4626(buyToken).asset()), + specifiedAmount, + false, + _sellToken == address(0) + ); + + // wrap: buyToken.asset() -> buyToken.shares() + (,, steps[1]) = createWrapOrUnwrapPath( + buyToken, specifiedAmount, IVault.WrappingDirection.WRAP, false + ); + } else if (kind == ERC4626_SWAP_TYPE.SWAP_UNWRAP) { + // isERC4626(sellToken) && !isERC4626(buyToken) and + // !isERC4626(buyToken) && !isERC4626(sellToken) + steps = new IBatchRouter.SwapPathStep[](2); + + // swap: sellToken -> buyToken.shares() + (,, steps[0]) = createERC20Path( + pool, + IERC20(sellToken), + IERC20(outputAddress), + specifiedAmount, + false, + _sellToken == address(0) + ); + + // unwrap: buyToken.shares() -> buyToken.asset() + (,, steps[1]) = createWrapOrUnwrapPath( + outputAddress, + specifiedAmount, + IVault.WrappingDirection.UNWRAP, + false + ); + } else if (kind == ERC4626_SWAP_TYPE.WRAP_SWAP) { + // input is ERC20, output is ERC4626 + steps = new IBatchRouter.SwapPathStep[](2); + + // wrap: sellToken.shares() -> sellToken.asset() + (,, steps[0]) = createWrapOrUnwrapPath( + outputAddress, + specifiedAmount, + IVault.WrappingDirection.WRAP, + false + ); + // swap: sellToken.asset() -> buyToken + (,, steps[1]) = createERC20Path( + pool, + IERC20(outputAddress), + IERC20(buyToken), + specifiedAmount, + false, + _buyToken == address(0) + ); + } else if (kind == ERC4626_SWAP_TYPE.UNWRAP_SWAP) { + steps = new IBatchRouter.SwapPathStep[](2); + + // unwrap: sellToken.shares() -> sellToken.asset() + (,, steps[0]) = createWrapOrUnwrapPath( + sellToken, + specifiedAmount, + IVault.WrappingDirection.UNWRAP, + false + ); + + // swap: sellToken.asset() -> buyToken + (,, steps[1]) = createERC20Path( + pool, + IERC20(sellToken), + IERC20(buyToken), + specifiedAmount, + false, + _buyToken == address(0) + ); + } + + if (isBuy) { + buyPath = new IBatchRouter.SwapPathExactAmountOut[](1); + buyPath[0] = IBatchRouter.SwapPathExactAmountOut({ + tokenIn: IERC20(sellToken), + steps: steps, + maxAmountIn: IERC20(sellToken).balanceOf(address(this)), + exactAmountOut: specifiedAmount + }); + } else { + sellPath = new IBatchRouter.SwapPathExactAmountIn[](1); + sellPath[0] = IBatchRouter.SwapPathExactAmountIn({ + tokenIn: IERC20(sellToken), + steps: steps, + exactAmountIn: specifiedAmount, + minAmountOut: 1 + }); + } + } + + function swapERC4626AndERC20( + address pool, + address _sellToken, + address _buyToken, + uint256 specifiedAmount, + ERC4626_SWAP_TYPE kind, + address outputAddress, + bool isBuy + ) internal returns (uint256 calculatedAmount) { + // approve + uint256 approvalAmount = specifiedAmount; + + address sellToken = _sellToken == address(0) ? WETH_ADDRESS : _sellToken; + address buyToken = _buyToken == address(0) ? WETH_ADDRESS : _buyToken; + + if (_sellToken != address(0)) { + if (isBuy) { + approvalAmount = IERC20(sellToken).balanceOf(msg.sender); + } + IERC20(sellToken).safeIncreaseAllowance(permit2, approvalAmount); + IPermit2(permit2).approve( + address(sellToken), + address(router), + type(uint160).max, + type(uint48).max + ); + } else { + if (isBuy) { + approvalAmount = address(this).balance; + } + } + + if (!isBuy) { + if (_sellToken != address(0)) { + IERC20(sellToken).safeTransferFrom( + msg.sender, address(this), approvalAmount + ); + } + + (IBatchRouter.SwapPathExactAmountIn[] memory sellPath,) = + prepareERC4626SellOrBuy( + pool, + sellToken, + buyToken, + specifiedAmount, + kind, + outputAddress, + isBuy + ); + + uint256[] memory amountsOut; + if (_sellToken == address(0)) { + (,, amountsOut) = router.swapExactIn{value: specifiedAmount}( + sellPath, type(uint256).max, true, bytes("") + ); + } else { + (,, amountsOut) = router.swapExactIn( + sellPath, type(uint256).max, false, bytes("") + ); + } + + calculatedAmount = amountsOut[0]; + + if (_buyToken != address(0)) { + IERC20(buyToken).safeTransfer(msg.sender, calculatedAmount); + } else { + (bool sent,) = + payable(msg.sender).call{value: calculatedAmount}(""); + require(sent, "Failed to transfer ETH"); + } + } else { + uint256 initialSenderBalance = address(this).balance; + if (_sellToken != address(0)) { + initialSenderBalance = IERC20(sellToken).balanceOf(msg.sender); + IERC20(sellToken).safeTransferFrom( + msg.sender, address(this), approvalAmount + ); + } + + (, IBatchRouter.SwapPathExactAmountOut[] memory buyPath) = + prepareERC4626SellOrBuy( + pool, + sellToken, + buyToken, + specifiedAmount, + kind, + outputAddress, + true + ); + + uint256[] memory amountsIn; + if (_sellToken == address(0)) { + (,, amountsIn) = router.swapExactOut{value: approvalAmount}( + buyPath, type(uint256).max, false, bytes("") + ); + } else { + (,, amountsIn) = router.swapExactOut( + buyPath, type(uint256).max, false, bytes("") + ); + } + + calculatedAmount = amountsIn[0]; + + if (_buyToken != address(0)) { + IERC20(buyToken).safeTransfer(msg.sender, specifiedAmount); + } else { + (bool sent,) = + payable(msg.sender).call{value: specifiedAmount}(""); + require(sent, "Failed to transfer ETH"); + } + + // transfer back sellToken to sender + if (_sellToken != address(0)) { + IERC20(sellToken).safeTransfer( + msg.sender, initialSenderBalance - calculatedAmount + ); + } else { + (bool sent,) = payable(msg.sender).call{ + value: initialSenderBalance - calculatedAmount + }(""); + require(sent, "Failed to transfer ETH"); + } + } + } + + function getAmountOutERC4626AndERC20( + address pool, + address sellToken, + address buyToken, + uint256 specifiedAmount, + ERC4626_SWAP_TYPE kind, + address outputAddress + ) internal returns (uint256 calculatedAmount) { + (IBatchRouter.SwapPathExactAmountIn[] memory paths,) = + prepareERC4626SellOrBuy( + pool, + sellToken, + buyToken, + specifiedAmount, + kind, + outputAddress, + false + ); + (,, uint256[] memory amountsOut) = + router.querySwapExactIn(paths, address(0), bytes("")); + calculatedAmount = amountsOut[0]; + } + + function getLimitsERC4626AndERC20( + bytes32 poolId, + address sellToken, + address buyToken, + ERC4626_SWAP_TYPE kind, + address outputAddress + ) internal view returns (uint256[] memory limits) { + limits = new uint256[](2); + address pool = address(bytes20(poolId)); + (IERC20[] memory tokens,, uint256[] memory balancesRaw,) = + vault.getPoolTokenInfo(pool); + + uint256 tokenLimit; + + if (kind == ERC4626_SWAP_TYPE.SWAP_WRAP) { + for (uint256 i = 0; i < tokens.length; i++) { + address token = address(tokens[i]); + if (token == sellToken) { + limits[0] = balancesRaw[i] * RESERVE_LIMIT_FACTOR / 10; + } + + if (token == IERC4626(buyToken).asset()) { + tokenLimit = balancesRaw[i] * RESERVE_LIMIT_FACTOR / 10; + } + } + limits[1] = IERC4626(buyToken).previewDeposit(tokenLimit); + } else if (kind == ERC4626_SWAP_TYPE.SWAP_UNWRAP) { + for (uint256 i = 0; i < tokens.length; i++) { + address token = address(tokens[i]); + if (token == sellToken) { + limits[0] = balancesRaw[i] * RESERVE_LIMIT_FACTOR / 10; + } else if (token == outputAddress) { + tokenLimit = balancesRaw[i] * RESERVE_LIMIT_FACTOR / 10; + } + } + limits[1] = IERC4626(outputAddress).previewRedeem(tokenLimit); + } else if (kind == ERC4626_SWAP_TYPE.WRAP_SWAP) { + for (uint256 i = 0; i < tokens.length; i++) { + address token = address(tokens[i]); + + if (token == outputAddress) { + limits[0] = IERC4626(outputAddress).previewRedeem( + balancesRaw[i] * RESERVE_LIMIT_FACTOR / 10 + ); + } + + if (token == buyToken) { + limits[1] = balancesRaw[i] * RESERVE_LIMIT_FACTOR / 10; + } + } + } else if (kind == ERC4626_SWAP_TYPE.UNWRAP_SWAP) { + for (uint256 i = 0; i < tokens.length; i++) { + address token = address(tokens[i]); + + if (token == buyToken) { + limits[1] = balancesRaw[i] * RESERVE_LIMIT_FACTOR / 10; + } + + if (token == IERC4626(sellToken).asset()) { + limits[0] = IERC4626(sellToken).previewDeposit( + balancesRaw[i] * RESERVE_LIMIT_FACTOR / 10 + ); + } + } + } + } +} diff --git a/evm/src/balancer-v3/lib/BalancerInterfaces.sol b/evm/src/balancer-v3/lib/BalancerInterfaces.sol new file mode 100644 index 0000000..40eaaff --- /dev/null +++ b/evm/src/balancer-v3/lib/BalancerInterfaces.sol @@ -0,0 +1,206 @@ +// SPDX-License-Identifier: AGPL-3.0-or-later +pragma solidity ^0.8.26; + +import {ISwapAdapter} from "../../interfaces/ISwapAdapter.sol"; +import {CustomBytesAppend} from "../../libraries/CustomBytesAppend.sol"; +import { + IERC20, + SafeERC20 +} from + "../../../lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; +import {IERC4626} from + "../../../lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; + +interface IVault { + type PoolConfigBits is bytes32; + + enum SwapKind { + EXACT_IN, + EXACT_OUT + } + + enum TokenType { + STANDARD, + WITH_RATE + } + + enum WrappingDirection { + WRAP, + UNWRAP + } + + struct VaultSwapParams { + SwapKind kind; + address pool; + IERC20 tokenIn; + IERC20 tokenOut; + uint256 amountGivenRaw; + uint256 limitRaw; + bytes userData; + } + + struct BufferWrapOrUnwrapParams { + SwapKind kind; + WrappingDirection direction; + IERC4626 wrappedToken; + uint256 amountGivenRaw; + uint256 limitRaw; + } + + struct PoolData { + PoolConfigBits poolConfigBits; + IERC20[] tokens; + TokenInfo[] tokenInfo; + uint256[] balancesRaw; + uint256[] balancesLiveScaled18; + uint256[] tokenRates; + uint256[] decimalScalingFactors; + } + + struct TokenInfo { + TokenType tokenType; + IRateProvider rateProvider; + bool paysYieldFees; + } + + function swap(VaultSwapParams memory vaultSwapParams) + external + returns ( + uint256 amountCalculatedRaw, + uint256 amountInRaw, + uint256 amountOutRaw + ); + + function getPoolTokenCountAndIndexOfToken(address pool, IERC20 token) + external + view + returns (uint256 tokenCount, uint256 index); + + function erc4626BufferWrapOrUnwrap(BufferWrapOrUnwrapParams memory params) + external + returns ( + uint256 amountCalculatedRaw, + uint256 amountInRaw, + uint256 amountOutRaw + ); + + function getPoolData(address pool) + external + view + returns (PoolData memory); + + function getPoolTokenInfo(address pool) + external + view + returns ( + IERC20[] memory tokens, + TokenInfo[] memory tokenInfo, + uint256[] memory balancesRaw, + uint256[] memory lastBalancesLiveScaled18 + ); + + function getPoolTokens(address pool) + external + view + returns (IERC20[] memory tokens); +} + +interface IRateProvider { + /** + * @dev Returns an 18 decimal fixed point number that is the exchange rate + * of the token to some other underlying + * token. The meaning of this rate depends on the context. + */ + function getRate() external view returns (uint256); +} + +interface IBatchRouter { + struct SwapPathStep { + address pool; + IERC20 tokenOut; + // If true, the "pool" is an ERC4626 Buffer. Used to wrap/unwrap tokens + // if pool doesn't have enough liquidity. + bool isBuffer; + } + + struct SwapPathExactAmountIn { + IERC20 tokenIn; + // For each step: + // If tokenIn == pool, use removeLiquidity SINGLE_TOKEN_EXACT_IN. + // If tokenOut == pool, use addLiquidity UNBALANCED. + SwapPathStep[] steps; + uint256 exactAmountIn; + uint256 minAmountOut; + } + + struct SwapPathExactAmountOut { + IERC20 tokenIn; + // for each step: + // If tokenIn == pool, use removeLiquidity SINGLE_TOKEN_EXACT_OUT. + // If tokenOut == pool, use addLiquidity SINGLE_TOKEN_EXACT_OUT. + SwapPathStep[] steps; + uint256 maxAmountIn; + uint256 exactAmountOut; + } + + function querySwapExactIn( + SwapPathExactAmountIn[] memory paths, + address sender, + bytes calldata userData + ) + external + returns ( + uint256[] memory pathAmountsOut, + address[] memory tokensOut, + uint256[] memory amountsOut + ); + + function querySwapExactOut( + SwapPathExactAmountOut[] memory paths, + address sender, + bytes calldata userData + ) + external + returns ( + uint256[] memory pathAmountsIn, + address[] memory tokensIn, + uint256[] memory amountsIn + ); + + function swapExactIn( + SwapPathExactAmountIn[] memory paths, + uint256 deadline, + bool wethIsEth, + bytes calldata userData + ) + external + payable + returns ( + uint256[] memory pathAmountsOut, + address[] memory tokensOut, + uint256[] memory amountsOut + ); + + function swapExactOut( + SwapPathExactAmountOut[] memory paths, + uint256 deadline, + bool wethIsEth, + bytes calldata userData + ) + external + payable + returns ( + uint256[] memory pathAmountsIn, + address[] memory tokensIn, + uint256[] memory amountsIn + ); +} + +interface IPermit2 { + function approve( + address token, + address spender, + uint160 amount, + uint48 expiration + ) external; +} diff --git a/evm/src/balancer-v3/lib/BalancerStorage.sol b/evm/src/balancer-v3/lib/BalancerStorage.sol new file mode 100644 index 0000000..3c9e33f --- /dev/null +++ b/evm/src/balancer-v3/lib/BalancerStorage.sol @@ -0,0 +1,42 @@ +//SPDX-License-Identifier: AGPL-3.0-or-later +pragma solidity ^0.8.26; + +import "./BalancerInterfaces.sol"; + +/** + * @title Balancer V3 Storage + */ +abstract contract BalancerStorage { + // Balancer V3 constants + uint256 constant RESERVE_LIMIT_FACTOR = 3; // 30% as being divided by 10 + uint256 constant SWAP_DEADLINE_SEC = 1000; + + // Balancer V3 contracts + IVault immutable vault; + IBatchRouter immutable router; + + // ETH and Wrapped ETH addresses, using ETH as address(0) + address immutable WETH_ADDRESS; + address constant ETH_ADDRESS = address(0); + + // permit2 address + address immutable permit2; + + enum CUSTOM_WRAP_KIND { + NONE, + ERC20_TO_ERC20, // swap ERC20 to ERC20, passing through a ERC4626_4626 + // pool + // pool + ERC4626_TO_ERC4626 // swap ERC4626 to ERC4626, passing through a + // ERC20_20_20 pool + + } + + enum ERC4626_SWAP_TYPE { + NONE, + SWAP_WRAP, + SWAP_UNWRAP, + WRAP_SWAP, + UNWRAP_SWAP + } +} diff --git a/evm/src/balancer-v3/lib/BalancerSwapHelpers.sol b/evm/src/balancer-v3/lib/BalancerSwapHelpers.sol new file mode 100644 index 0000000..bdcce0f --- /dev/null +++ b/evm/src/balancer-v3/lib/BalancerSwapHelpers.sol @@ -0,0 +1,247 @@ +//SPDX-License-Identifier: AGPL-3.0-or-later +pragma solidity ^0.8.26; + +import "./BalancerERC4626Helpers.sol"; + +/** + * @title Balancer V3 Swap Helpers + * @dev A wrapped library containing swap functions, helpers and storage for the + * Balancer V3 Swap Adapter contract + */ +abstract contract BalancerSwapHelpers is + BalancerERC4626Helpers, + ISwapAdapter +{ + function getAmountOutMiddleware( + bytes32 pool, + address sellToken, + address buyToken, + uint256 specifiedAmount + ) internal returns (uint256 amountOut) { + address poolAddress = address(bytes20(pool)); + + // getTokens() -> [token0, token1] -> if([sellToken,buyToken) in + // [token0, token1]) -> direct + IERC20[] memory tokens = vault.getPoolTokens(poolAddress); + + bool sellTokenFound; + bool buyTokenFound; + if (sellToken == address(0) || buyToken == address(0)) { + sellTokenFound = true; + buyTokenFound = true; + } else { + for (uint256 i = 0; i < tokens.length; i++) { + address token = address(tokens[i]); + if (token == sellToken) { + sellTokenFound = true; + } else if (token == buyToken) { + buyTokenFound = true; + } + } + } + + if (sellTokenFound && buyTokenFound) { + // Direct Swap + (IBatchRouter.SwapPathExactAmountIn memory sellPath,,) = + createERC20Path( + poolAddress, + IERC20(sellToken), + IERC20(buyToken), + specifiedAmount, + false, + sellToken == address(0) || buyToken == address(0) + ); + return getAmountOut(sellPath); + } else if (!sellTokenFound && !buyTokenFound) { + // 3 step (4 tokens) + ( + CUSTOM_WRAP_KIND kindWrap, + address sellTokenOutput, + address buyTokenOutput + ) = getCustomWrap(sellToken, buyToken, poolAddress); + return getAmountOutCustomWrap( + poolAddress, + sellToken, + buyToken, + specifiedAmount, + kindWrap, + sellTokenOutput, + buyTokenOutput + ); + } else { + // 2 step (3 tokens) + (ERC4626_SWAP_TYPE kind, address outputAddress) = getERC4626PathType( + poolAddress, sellToken, buyToken, sellTokenFound + ); + + if (kind != ERC4626_SWAP_TYPE.NONE) { + return getAmountOutERC4626AndERC20( + poolAddress, + sellToken, + buyToken, + specifiedAmount, + kind, + outputAddress + ); + } + } + } + + /** + * @notice Middleware for swaps + */ + function swapMiddleware( + bytes32 pool, + address sellToken, + address buyToken, + OrderSide side, + uint256 specifiedAmount + ) internal returns (uint256) { + address poolAddress = address(bytes20(pool)); + + // getTokens() -> [token0, token1] -> if([sellToken,buyToken) in + // [token0, token1]) -> direct + IERC20[] memory tokens = vault.getPoolTokens(poolAddress); + + bool sellTokenFound; + bool buyTokenFound; + if (sellToken == address(0) || buyToken == address(0)) { + sellTokenFound = true; + buyTokenFound = true; + } else { + for (uint256 i = 0; i < tokens.length; i++) { + address token = address(tokens[i]); + if (token == sellToken) { + sellTokenFound = true; + } else if (token == buyToken) { + buyTokenFound = true; + } + } + } + + if (sellTokenFound && buyTokenFound) { + // Direct Swap + // Fallback (used for ERC20<->ERC20 and ERC4626<->ERC4626 as + // inherits + // IERC20 logic) + if (side == OrderSide.Buy) { + return buyERC20WithERC20( + poolAddress, + IERC20(sellToken), + IERC20(buyToken), + specifiedAmount, + true + ); + } else { + return sellERC20ForERC20( + poolAddress, + IERC20(sellToken), + IERC20(buyToken), + specifiedAmount, + true + ); + } + } else if (!sellTokenFound && !buyTokenFound) { + // 3 step (4 tokens) + ( + CUSTOM_WRAP_KIND kindWrap, + address sellTokenOutput, + address buyTokenOutput + ) = getCustomWrap(sellToken, buyToken, poolAddress); + + if (side == OrderSide.Sell) { + return sellCustomWrap( + poolAddress, + sellToken, + buyToken, + specifiedAmount, + kindWrap, + sellTokenOutput, + buyTokenOutput + ); + } else { + return buyCustomWrap( + poolAddress, + sellToken, + buyToken, + specifiedAmount, + kindWrap, + sellTokenOutput, + buyTokenOutput + ); + } + } else { + // 2 step (3 tokens) + (ERC4626_SWAP_TYPE kind, address outputAddress) = getERC4626PathType( + poolAddress, sellToken, buyToken, sellTokenFound + ); + + return swapERC4626AndERC20( + poolAddress, + sellToken, + buyToken, + specifiedAmount, + kind, + outputAddress, + side == OrderSide.Buy + ); + } + } + + function getLimitsMiddleware( + bytes32 poolId, + address sellToken, + address buyToken + ) internal view returns (uint256[] memory limits) { + address poolAddress = address(bytes20(poolId)); + + // getTokens() -> [token0, token1] -> if([sellToken,buyToken) in + // [token0, token1]) -> direct + IERC20[] memory tokens = vault.getPoolTokens(poolAddress); + + bool sellTokenFound; + bool buyTokenFound; + if (sellToken == address(0) || buyToken == address(0)) { + sellTokenFound = true; + buyTokenFound = true; + } else { + for (uint256 i = 0; i < tokens.length; i++) { + address token = address(tokens[i]); + if (token == sellToken) { + sellTokenFound = true; + } else if (token == buyToken) { + buyTokenFound = true; + } + } + } + + if (sellTokenFound && buyTokenFound) { + // Direct Swap + return getLimitsERC20(poolId, sellToken, buyToken); + } else if (!sellTokenFound && !buyTokenFound) { + // 3 step (4 tokens) + ( + CUSTOM_WRAP_KIND kindWrap, + address sellTokenOutput, + address buyTokenOutput + ) = getCustomWrap(sellToken, buyToken, poolAddress); + + return getLimitsCustomWrap( + poolId, + sellToken, + buyToken, + kindWrap, + sellTokenOutput, + buyTokenOutput + ); + } else { + // 2 step (3 tokens) + (ERC4626_SWAP_TYPE kind, address outputAddress) = getERC4626PathType( + poolAddress, sellToken, buyToken, sellTokenFound + ); + return getLimitsERC4626AndERC20( + poolId, sellToken, buyToken, kind, outputAddress + ); + } + } +} diff --git a/evm/src/balancer-v3/lib/BalancerV3Errors.sol b/evm/src/balancer-v3/lib/BalancerV3Errors.sol new file mode 100644 index 0000000..521f239 --- /dev/null +++ b/evm/src/balancer-v3/lib/BalancerV3Errors.sol @@ -0,0 +1,661 @@ +// SPDX-License-Identifier: AGPL-3.0-or-later +pragma solidity ^0.8.26; + +import {IERC20, IERC4626} from "src/balancer-v3/BalancerV3SwapAdapter.sol"; + +interface BalancerV3Errors { + /** + * @notice A pool has already been registered. `registerPool` may only be + * called once. + * @param pool The already registered pool + */ + error PoolAlreadyRegistered(address pool); + + /** + * @notice A pool has already been initialized. `initialize` may only be + * called once. + * @param pool The already initialized pool + */ + error PoolAlreadyInitialized(address pool); + + /** + * @notice A pool has not been registered. + * @param pool The unregistered pool + */ + error PoolNotRegistered(address pool); + + /** + * @notice A referenced pool has not been initialized. + * @param pool The uninitialized pool + */ + error PoolNotInitialized(address pool); + + /** + * @notice A hook contract rejected a pool on registration. + * @param poolHooksContract Address of the hook contract that rejected the + * pool registration + * @param pool Address of the rejected pool + * @param poolFactory Address of the pool factory + */ + error HookRegistrationFailed( + address poolHooksContract, address pool, address poolFactory + ); + + /** + * @notice A token was already registered (i.e., it is a duplicate in the + * pool). + * @param token The duplicate token + */ + error TokenAlreadyRegistered(IERC20 token); + + /// @notice The token count is below the minimum allowed. + error MinTokens(); + + /// @notice The token count is above the maximum allowed. + error MaxTokens(); + + /// @notice Invalid tokens (e.g., zero) cannot be registered. + error InvalidToken(); + + /// @notice The token type given in a TokenConfig during pool registration + /// is invalid. + error InvalidTokenType(); + + /// @notice The data in a TokenConfig struct is inconsistent or unsupported. + error InvalidTokenConfiguration(); + + /// @notice Tokens with more than 18 decimals are not supported. + error InvalidTokenDecimals(); + + /** + * @notice The token list passed into an operation does not match the pool + * tokens in the pool. + * @param pool Address of the pool + * @param expectedToken The correct token at a given index in the pool + * @param actualToken The actual token found at that index + */ + error TokensMismatch( + address pool, address expectedToken, address actualToken + ); + + /** + * + * Transient Accounting + * + */ + + /// @notice A transient accounting operation completed with outstanding + /// token deltas. + error BalanceNotSettled(); + + /// @notice A user called a Vault function (swap, add/remove liquidity) + /// outside the lock context. + error VaultIsNotUnlocked(); + + /// @notice The pool has returned false to the beforeSwap hook, indicating + /// the transaction should revert. + error DynamicSwapFeeHookFailed(); + + /// @notice The pool has returned false to the beforeSwap hook, indicating + /// the transaction should revert. + error BeforeSwapHookFailed(); + + /// @notice The pool has returned false to the afterSwap hook, indicating + /// the transaction should revert. + error AfterSwapHookFailed(); + + /// @notice The pool has returned false to the beforeInitialize hook, + /// indicating the transaction should revert. + error BeforeInitializeHookFailed(); + + /// @notice The pool has returned false to the afterInitialize hook, + /// indicating the transaction should revert. + error AfterInitializeHookFailed(); + + /// @notice The pool has returned false to the beforeAddLiquidity hook, + /// indicating the transaction should revert. + error BeforeAddLiquidityHookFailed(); + + /// @notice The pool has returned false to the afterAddLiquidity hook, + /// indicating the transaction should revert. + error AfterAddLiquidityHookFailed(); + + /// @notice The pool has returned false to the beforeRemoveLiquidity hook, + /// indicating the transaction should revert. + error BeforeRemoveLiquidityHookFailed(); + + /// @notice The pool has returned false to the afterRemoveLiquidity hook, + /// indicating the transaction should revert. + error AfterRemoveLiquidityHookFailed(); + + /// @notice An unauthorized Router tried to call a permissioned function + /// (i.e., using the Vault's token allowance). + error RouterNotTrusted(); + + /** + * + * Swaps + * + */ + + /// @notice The user tried to swap zero tokens. + error AmountGivenZero(); + + /// @notice The user attempted to swap a token for itself. + error CannotSwapSameToken(); + + /** + * @notice The user attempted to operate with a token that is not in the + * pool. + * @param token The unregistered token + */ + error TokenNotRegistered(IERC20 token); + + /** + * @notice An amount in or out has exceeded the limit specified in the swap + * request. + * @param amount The total amount in or out + * @param limit The amount of the limit that has been exceeded + */ + error SwapLimit(uint256 amount, uint256 limit); + + /** + * @notice A hook adjusted amount in or out has exceeded the limit specified + * in the swap request. + * @param amount The total amount in or out + * @param limit The amount of the limit that has been exceeded + */ + error HookAdjustedSwapLimit(uint256 amount, uint256 limit); + + /// @notice The amount given or calculated for an operation is below the + /// minimum limit. + error TradeAmountTooSmall(); + + /** + * + * Add Liquidity + * + */ + + /// @notice Add liquidity kind not supported. + error InvalidAddLiquidityKind(); + + /** + * @notice A required amountIn exceeds the maximum limit specified for the + * operation. + * @param tokenIn The incoming token + * @param amountIn The total token amount in + * @param maxAmountIn The amount of the limit that has been exceeded + */ + error AmountInAboveMax( + IERC20 tokenIn, uint256 amountIn, uint256 maxAmountIn + ); + + /** + * @notice A hook adjusted amountIn exceeds the maximum limit specified for + * the operation. + * @param tokenIn The incoming token + * @param amountIn The total token amount in + * @param maxAmountIn The amount of the limit that has been exceeded + */ + error HookAdjustedAmountInAboveMax( + IERC20 tokenIn, uint256 amountIn, uint256 maxAmountIn + ); + + /** + * @notice The BPT amount received from adding liquidity is below the + * minimum specified for the operation. + * @param amountOut The total BPT amount out + * @param minAmountOut The amount of the limit that has been exceeded + */ + error BptAmountOutBelowMin(uint256 amountOut, uint256 minAmountOut); + + /// @notice Pool does not support adding liquidity with a customized input. + error DoesNotSupportAddLiquidityCustom(); + + /// @notice Pool does not support adding liquidity through donation. + error DoesNotSupportDonation(); + + /** + * + * Remove Liquidity + * + */ + + /// @notice Remove liquidity kind not supported. + error InvalidRemoveLiquidityKind(); + + /** + * @notice The actual amount out is below the minimum limit specified for + * the operation. + * @param tokenOut The outgoing token + * @param amountOut The total BPT amount out + * @param minAmountOut The amount of the limit that has been exceeded + */ + error AmountOutBelowMin( + IERC20 tokenOut, uint256 amountOut, uint256 minAmountOut + ); + + /** + * @notice The hook adjusted amount out is below the minimum limit specified + * for the operation. + * @param tokenOut The outgoing token + * @param amountOut The total BPT amount out + * @param minAmountOut The amount of the limit that has been exceeded + */ + error HookAdjustedAmountOutBelowMin( + IERC20 tokenOut, uint256 amountOut, uint256 minAmountOut + ); + + /** + * @notice The required BPT amount in exceeds the maximum limit specified + * for the operation. + * @param amountIn The total BPT amount in + * @param maxAmountIn The amount of the limit that has been exceeded + */ + error BptAmountInAboveMax(uint256 amountIn, uint256 maxAmountIn); + + /// @notice Pool does not support removing liquidity with a customized + /// input. + error DoesNotSupportRemoveLiquidityCustom(); + + /** + * + * Fees + * + */ + + /** + * @notice Error raised when there is an overflow in the fee calculation. + * @dev This occurs when the sum of the parts (aggregate swap or yield fee) + * is greater than the whole + * (total swap or yield fee). Also validated when the protocol fee + * controller updates aggregate fee + * percentages in the Vault. + */ + error ProtocolFeesExceedTotalCollected(); + + /** + * @notice Error raised when the swap fee percentage is less than the + * minimum allowed value. + * @dev The Vault itself does not impose a universal minimum. Rather, it + * validates against the + * range specified by the `ISwapFeePercentageBounds` interface. and reverts + * with this error + * if it is below the minimum value returned by the pool. + * + * Pools with dynamic fees do not check these limits. + */ + error SwapFeePercentageTooLow(); + + /** + * @notice Error raised when the swap fee percentage is greater than the + * maximum allowed value. + * @dev The Vault itself does not impose a universal minimum. Rather, it + * validates against the + * range specified by the `ISwapFeePercentageBounds` interface. and reverts + * with this error + * if it is above the maximum value returned by the pool. + * + * Pools with dynamic fees do not check these limits. + */ + error SwapFeePercentageTooHigh(); + + /** + * @notice Primary fee percentages result in an aggregate fee that cannot be + * stored with the required precision. + * @dev Primary fee percentages are 18-decimal values, stored here in 64 + * bits, and calculated with full 256-bit + * precision. However, the resulting aggregate fees are stored in the Vault + * with 24-bit precision, which + * corresponds to 0.00001% resolution (i.e., a fee can be 1%, 1.00001%, + * 1.00002%, but not 1.000005%). + * Disallow setting fees such that there would be precision loss in the + * Vault, leading to a discrepancy between + * the aggregate fee calculated here and that stored in the Vault. + */ + error FeePrecisionTooHigh(); + + /// @notice A given percentage is above the maximum (usually a value close + /// to FixedPoint.ONE, or 1e18 wei). + error PercentageAboveMax(); + + /** + * + * Queries + * + */ + + /// @notice A user tried to execute a query operation when they were + /// disabled. + error QueriesDisabled(); + + /// @notice An admin tried to re-enable queries, but they were disabled + /// permanently. + error QueriesDisabledPermanently(); + + /** + * + * Recovery Mode + * + */ + + /** + * @notice Cannot enable recovery mode when already enabled. + * @param pool The pool + */ + error PoolInRecoveryMode(address pool); + + /** + * @notice Cannot disable recovery mode when not enabled. + * @param pool The pool + */ + error PoolNotInRecoveryMode(address pool); + + /** + * + * Authentication + * + */ + + /** + * @notice Error indicating the sender is not the Vault (e.g., someone is + * trying to call a permissioned function). + * @param sender The account attempting to call a permissioned function + */ + error SenderIsNotVault(address sender); + + /** + * + * Pausing + * + */ + + /// @notice The caller specified a pause window period longer than the + /// maximum. + error VaultPauseWindowDurationTooLarge(); + + /// @notice The caller specified a buffer period longer than the maximum. + error PauseBufferPeriodDurationTooLarge(); + + /// @notice A user tried to perform an operation while the Vault was paused. + error VaultPaused(); + + /// @notice Governance tried to unpause the Vault when it was not paused. + error VaultNotPaused(); + + /// @notice Governance tried to pause the Vault after the pause period + /// expired. + error VaultPauseWindowExpired(); + + /** + * @notice A user tried to perform an operation involving a paused Pool. + * @param pool The paused pool + */ + error PoolPaused(address pool); + + /** + * @notice Governance tried to unpause the Pool when it was not paused. + * @param pool The unpaused pool + */ + error PoolNotPaused(address pool); + + /** + * @notice Governance tried to pause a Pool after the pause period expired. + * @param pool The pool + */ + error PoolPauseWindowExpired(address pool); + + /** + * + * ERC4626 token buffers + * + */ + + /** + * @notice The buffer for the given wrapped token was already initialized. + * @param wrappedToken The wrapped token corresponding to the buffer + */ + error BufferAlreadyInitialized(IERC4626 wrappedToken); + + /** + * @notice The buffer for the given wrapped token was not initialized. + * @param wrappedToken The wrapped token corresponding to the buffer + */ + error BufferNotInitialized(IERC4626 wrappedToken); + + /// @notice The user is trying to remove more than their allocated shares + /// from the buffer. + error NotEnoughBufferShares(); + + /** + * @notice The wrapped token asset does not match the underlying token. + * @dev This should never happen, but a malicious wrapper contract might not + * return the correct address. + * Legitimate wrapper contracts should make the asset a constant or + * immutable value. + * + * @param wrappedToken The wrapped token corresponding to the buffer + * @param underlyingToken The underlying token returned by `asset` + */ + error WrongUnderlyingToken(IERC4626 wrappedToken, address underlyingToken); + + /** + * @notice A wrapped token reported the zero address as its underlying token + * asset. + * @dev This should never happen, but a malicious wrapper contract might do + * this (e.g., in an attempt to + * re-initialize the buffer). + * + * @param wrappedToken The wrapped token corresponding to the buffer + */ + error InvalidUnderlyingToken(IERC4626 wrappedToken); + + /** + * @notice The amount given to wrap/unwrap was too small, which can + * introduce rounding issues. + * @param wrappedToken The wrapped token corresponding to the buffer + */ + error WrapAmountTooSmall(IERC4626 wrappedToken); + + /// @notice Buffer operation attempted while vault buffers are paused. + error VaultBuffersArePaused(); + + /// @notice Buffer shares were minted to the zero address. + error BufferSharesInvalidReceiver(); + + /// @notice Buffer shares were burned from the zero address. + error BufferSharesInvalidOwner(); + + /** + * @notice The total supply of a buffer can't be lower than the absolute + * minimum. + * @param totalSupply The total supply value that was below the minimum + */ + error BufferTotalSupplyTooLow(uint256 totalSupply); + + /// @dev A wrap/unwrap operation consumed more or returned less underlying + /// tokens than it should. + error NotEnoughUnderlying( + IERC4626 wrappedToken, + uint256 expectedUnderlyingAmount, + uint256 actualUnderlyingAmount + ); + + /// @dev A wrap/unwrap operation consumed more or returned less wrapped + /// tokens than it should. + error NotEnoughWrapped( + IERC4626 wrappedToken, + uint256 expectedWrappedAmount, + uint256 actualWrappedAmount + ); + + /// @dev Shares issued during initialization are below the requested amount. + error IssuedSharesBelowMin(uint256 issuedShares, uint256 minIssuedShares); + + /** + * + * Miscellaneous + * + */ + + /// @notice Pool does not support adding / removing liquidity with an + /// unbalanced input. + error DoesNotSupportUnbalancedLiquidity(); + + /// @notice The contract should not receive ETH. + error CannotReceiveEth(); + + /** + * @notice The `VaultExtension` contract was called by an account directly. + * @dev It can only be called by the Vault via delegatecall. + */ + error NotVaultDelegateCall(); + + /// @notice The `VaultExtension` contract was configured with an incorrect + /// Vault address. + error WrongVaultExtensionDeployment(); + + /// @notice The `ProtocolFeeController` contract was configured with an + /// incorrect Vault address. + error WrongProtocolFeeControllerDeployment(); + + /// @notice The `VaultAdmin` contract was configured with an incorrect Vault + /// address. + error WrongVaultAdminDeployment(); + + /// @notice Quote reverted with a reserved error code. + error QuoteResultSpoofed(); + + /// @notice Thrown when the number of tokens permissioned to a spender does + /// not match the number of tokens being transferred + /// @dev If the spender does not need to transfer the number of tokens + /// permitted, the spender can request amount 0 to be transferred + error LengthMismatch(); + + /// @notice Emits an event when the owner successfully invalidates an + /// unordered nonce. + event UnorderedNonceInvalidation( + address indexed owner, uint256 word, uint256 mask + ); + /// @notice Thrown when an allowance on a token has expired. + /// @param deadline The timestamp at which the allowed amount is no longer + /// valid + + error AllowanceExpired(uint256 deadline); + + /// @notice Thrown when an allowance on a token has been depleted. + /// @param amount The maximum amount allowed + error InsufficientAllowance(uint256 amount); + + error NotStaticCall(); + error VaultQueriesDisabled(); + error SwapDeadline(); + error InsufficientEth(); + error InvalidAmount(uint256 maxAmount); + + /** + * @notice Error raised when the protocol swap fee percentage exceeds the + * maximum allowed value. + * @dev Note that this is checked for both the global and pool-specific + * protocol swap fee percentages. + */ + error ProtocolSwapFeePercentageTooHigh(); + + /** + * @notice Error raised when the protocol yield fee percentage exceeds the + * maximum allowed value. + * @dev Note that this is checked for both the global and pool-specific + * protocol yield fee percentages. + */ + error ProtocolYieldFeePercentageTooHigh(); + + /** + * @notice Error raised if there is no pool creator on a withdrawal attempt + * from the given pool. + * @param pool The pool with no creator + */ + error PoolCreatorNotRegistered(address pool); + + /** + * @notice Error raised if the wrong account attempts to withdraw pool + * creator fees. + * @param caller The account attempting to withdraw pool creator fees + * @param pool The pool the caller tried to withdraw from + */ + error CallerIsNotPoolCreator(address caller, address pool); + + /// @notice Error raised when the pool creator swap or yield fee percentage + /// exceeds the maximum allowed value. + error PoolCreatorFeePercentageTooHigh(); + + error AssetBoundsExceeded(); + + /// @notice The amplification factor is below the minimum of the range (1 - + /// 5000). + error AmplificationFactorTooLow(); + + /// @notice The amplification factor is above the maximum of the range (1 - + /// 5000). + error AmplificationFactorTooHigh(); + + /// @notice The amplification change duration is too short. + error AmpUpdateDurationTooShort(); + + /// @notice The amplification change rate is too fast. + error AmpUpdateRateTooFast(); + + /// @notice Amplification update operations must be done one at a time. + error AmpUpdateAlreadyStarted(); + error StandardPoolWithCreator(); + + /// @notice Indicates that one of the pool tokens' weight is below the + /// minimum allowed. + error MinWeight(); + + /// @notice Indicates that the sum of the pool tokens' weights is not + /// FixedPoint.ONE. + error NormalizedWeightInvariant(); + error WeightedPoolBptRateUnsupported(); + /// @notice Arrays passed to a function and intended to be parallel have + /// different lengths. + error InputLengthMismatch(); + + /** + * @notice More than one non-zero value was given for a single token + * operation. + * @dev Input arrays for single token add/remove liquidity operations are + * expected to have only one non-zero value, + * corresponding to the token being added or removed. This error results if + * there are multiple non-zero entries. + */ + error MultipleNonZeroInputs(); + + /** + * @notice No valid input was given for a single token operation. + * @dev Input arrays for single token add/remove liquidity operations are + * expected to have one non-zero value, + * corresponding to the token being added or removed. This error results if + * all entries are zero. + */ + error AllZeroInputs(); + + /** + * @notice The tokens supplied to an array argument were not sorted in + * numerical order. + * @dev Tokens are not sorted by address on registration. This is an + * optimization so that off-chain processes can + * predict the token order without having to query the Vault. (It is also + * legacy v2 behavior.) + */ + error TokensNotSorted(); + error ExcessiveInvalidation(); + + error PoolAddressMismatch(address pool); + + error StaticATokenInvalidZeroShares(); + + error OnlyPauseGuardian(address caller); + + error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value); +} diff --git a/evm/src/balancer-v3/manifest.yaml b/evm/src/balancer-v3/manifest.yaml new file mode 100644 index 0000000..a389032 --- /dev/null +++ b/evm/src/balancer-v3/manifest.yaml @@ -0,0 +1,36 @@ +# information about the author helps us reach out in case of issues. +author: + name: Shadowy Creators + email: hello@shadowycoders.dev + +# Protocol Constants +constants: + protocol_gas: 30000 + # minimum capabilities we can expect, individual pools may extend these + capabilities: + - SellSide + - BuySide + - HardLimits + +# The file containing the adapter contract +contract: BalancerV3SwapAdapter.sol + +# Deployment instances used to generate chain specific bytecode. +instances: + - chain: + name: mainnet + id: 1 + arguments: + - "0xBA12222222228d8Ba445958a75a0704d566BF2C8" + +# Specify some automatic test cases in case getPoolIds and +# getTokens are not implemented. +tests: + instances: + - pool_id: "0x5c6ee304399dbdb9c8ef030ab642b10820db8f56000200000000000000000014" + sell_token: "0xba100000625a3754423978a60c9317c58a424e3D" + buy_token: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2" + block: 17000000 + chain: + name: mainnet + id: 1 diff --git a/evm/src/libraries/CustomBytesAppend.sol b/evm/src/libraries/CustomBytesAppend.sol new file mode 100644 index 0000000..c8328c7 --- /dev/null +++ b/evm/src/libraries/CustomBytesAppend.sol @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +library CustomBytesAppend { + // Constants for the custom prefix used in the bytes32 format + string private constant CUSTOM = "_CUSTOM_"; + + /** + * @dev Extracts an address from a bytes32 input, assuming it is either + * prepended or appended with `_CUSTOM_`. + * @param input The bytes32 input containing the address and custom + * prefix/suffix. + * @return extractedAddress The extracted address. + */ + function extractAddress(bytes32 input) + public + pure + returns (address extractedAddress) + { + // Convert the bytes32 input into a dynamic bytes array for manipulation + bytes memory inputBytes = abi.encodePacked(input); + + // Check if the bytes contain the custom prefix + if (hasPrefix(inputBytes)) { + // If prefixed, extract the 20 bytes after the prefix as the address + extractedAddress = + bytesToAddress(slice(inputBytes, bytes(CUSTOM).length, 20)); + } + // Check if the bytes contain the custom suffix + else if (hasSuffix(inputBytes)) { + // If suffixed, extract the first 20 bytes as the address + extractedAddress = bytesToAddress(slice(inputBytes, 0, 20)); + } else { + // Revert if neither prefix nor suffix is found + revert("Invalid input format"); + } + } + + /** + * @dev Checks if the bytes data has the custom prefix. + * @param data The bytes array to check. + * @return True if the prefix matches, false otherwise. + */ + function hasPrefix(bytes memory data) internal pure returns (bool) { + // Compare the first bytes of the input with the prefix using keccak256 + // for hashing + return keccak256(slice(data, 0, bytes(CUSTOM).length)) + == keccak256(bytes(CUSTOM)); + } + + /** + * @dev Checks if the bytes data has the custom suffix. + * @param data The bytes array to check. + * @return True if the suffix matches, false otherwise. + */ + function hasSuffix(bytes memory data) internal pure returns (bool) { + // Compare the last bytes of the input with the suffix using keccak256 + // for hashing + return keccak256( + slice( + data, data.length - bytes(CUSTOM).length, bytes(CUSTOM).length + ) + ) == keccak256(bytes(CUSTOM)); + } + + /** + * @dev Slices a bytes array. + * @param data The bytes array to slice. + * @param start The starting index of the slice. + * @param length The length of the slice. + * @return The sliced bytes array. + */ + function slice(bytes memory data, uint256 start, uint256 length) + internal + pure + returns (bytes memory) + { + // Ensure the slice operation does not exceed the bounds of the array + require(data.length >= start + length, "Invalid slice"); + + // Create a new bytes array to hold the sliced data + bytes memory result = new bytes(length); + for (uint256 i = 0; i < length; i++) { + result[i] = data[start + i]; + } + return result; + } + + /** + * @dev Converts a bytes array of length 20 into an address. + * @param data The bytes array (must be 20 bytes long). + * @return addr The converted address. + */ + function bytesToAddress(bytes memory data) + internal + pure + returns (address addr) + { + // Ensure the input length is exactly 20 bytes (size of an Ethereum + // address) + require(data.length == 20, "Invalid address length"); + + // Use inline assembly to efficiently convert the bytes to an address + assembly { + addr := mload(add(data, 20)) + } + } +} diff --git a/evm/test/BalancerV3SwapAdapter.t.sol b/evm/test/BalancerV3SwapAdapter.t.sol new file mode 100644 index 0000000..48c1a25 --- /dev/null +++ b/evm/test/BalancerV3SwapAdapter.t.sol @@ -0,0 +1,1310 @@ +// SPDX-License-Identifier: AGPL-3.0-or-later +pragma solidity ^0.8.26; + +import "./AdapterTest.sol"; +import {BalancerV3Errors} from "src/balancer-v3/lib/BalancerV3Errors.sol"; +import { + BalancerV3SwapAdapter, + IERC20, + IVault, + IBatchRouter, + IERC4626, + IPermit2 +} from "src/balancer-v3/BalancerV3SwapAdapter.sol"; +import {ERC20} from "openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; + +import {FractionMath} from "src/libraries/FractionMath.sol"; +import "./mocks/MockSUSDC.sol"; +import "./mocks/MockSETHx.sol"; +import "./mocks/MockSGOETH.sol"; +import {IBufferRouter} from "./interfaces/IBufferRouter.sol"; + +contract BalancerV3SwapAdapterTest is AdapterTest, ERC20, BalancerV3Errors { + using FractionMath for Fraction; + + IVault constant balancerV3Vault = + IVault(payable(0xbA1333333333a1BA1108E8412f11850A5C319bA9)); + BalancerV3SwapAdapter adapter; + IBatchRouter router = + IBatchRouter(0x136f1EFcC3f8f88516B9E94110D56FDBfB1778d1); // Batch router + address constant bufferRouter_address = + 0x9179C06629ef7f17Cb5759F501D89997FE0E7b45; + address constant permit2 = 0x000000000022D473030F116dDEE9F6B43aC78BA3; + + // ETHx waWETH - Stable Pool + address constant ERC4626_ERC20_ETHx_waWETH_STABLE_POOL = + 0x4AB7aB316D43345009B2140e0580B072eEc7DF16; + address constant ERC4626_waEthWETH = + 0x0bfc9d54Fc184518A81162F8fB99c2eACa081202; + address constant ERC20_ETHx = 0xA35b1B31Ce002FBF2058D22F30f95D405200A15b; + + // 50USDC-50@G - Weighted Pool + address constant ERC20_ERC20_GOETH_USDC_WEIGHTED_POOL = + 0xf91c11BA4220b7a72E1dc5E92f2b48D3fdF62726; + address constant ERC20_GOETH = 0x440017A1b021006d556d7fc06A54c32E42Eb745B; + address constant ERC20_USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48; + + // Aave Lido wETH-wstETH - Stable Pool + address constant ERC4626_ERC4626_WETH_wstETH_STABLE_POOL = + 0xc4Ce391d82D164c166dF9c8336DDF84206b2F812; + address constant ERC20_WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; + address constant ERC20_wstETH = 0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0; + address constant ERC4626_waEthLidoWETH = + 0x0FE906e030a44eF24CA8c7dC7B7c53A6C4F00ce9; + address constant ERC4626_waEthLidowstETH = + 0x775F661b0bD1739349b9A2A3EF60be277c5d2D29; + address constant ETH = address(0); + + uint256 constant TEST_ITERATIONS = 100; + + MockSUSDC public ERC4626_sUSDC; + MockSETHx public ERC4626_sETHx; + MockSGOETH public ERC4626_sGOETH; + + constructor() ERC20("", "") {} + + function setUp() public { + uint256 forkBlock = 21421638; + vm.createSelectFork(vm.rpcUrl("mainnet"), forkBlock); + + adapter = new BalancerV3SwapAdapter( + payable(address(balancerV3Vault)), + address(router), + permit2, + ERC20_WETH + ); + + // Create ERC4626_sUSDC first + ERC4626_sUSDC = new MockSUSDC(IERC20(ERC20_USDC)); + vm.label(address(ERC4626_sUSDC), "ERC4626_sUSDC"); + + // Create sGOETH + ERC4626_sGOETH = new MockSGOETH(IERC20(ERC20_GOETH)); + vm.label(address(ERC4626_sGOETH), "ERC4626_sGOETH"); + + // Create sETHx first + ERC4626_sETHx = new MockSETHx(IERC20(ERC20_ETHx)); + vm.label(address(ERC4626_sETHx), "ERC4626_sETHx"); + + // Deal ERC20_USDC to this contract for buffer initialization + deal(ERC20_USDC, address(this), 1000000 * 10 ** 6); + // Deal ETHx to this contract for buffer initialization + deal(ERC20_ETHx, address(this), 100000 * 10 ** 18); + deal(ERC20_GOETH, address(this), 10000000 * (10 ** 18)); + IERC20(ERC20_GOETH).approve(permit2, type(uint256).max); + IERC20(ERC4626_sGOETH).approve(permit2, type(uint256).max); + + // Approve ERC20_USDC spending through Permit2 + IERC20(ERC20_USDC).approve(permit2, type(uint256).max); + // Approve ETHx spending through Permit2 + IERC20(ERC20_ETHx).approve(permit2, type(uint256).max); + + IPermit2(permit2).approve( + ERC20_GOETH, + address(bufferRouter_address), + uint160(type(uint256).max), + uint48(block.timestamp + 1 days) + ); + + IPermit2(permit2).approve( + address(ERC4626_sGOETH), + address(bufferRouter_address), + uint160(type(uint256).max), + uint48(block.timestamp + 1 days) + ); + + // Approve both tokens for Buffer Router through Permit2 + IPermit2(permit2).approve( + ERC20_USDC, + address(bufferRouter_address), // Buffer + // Router + uint160(type(uint256).max), + uint48(block.timestamp + 1 days) + ); + + IPermit2(permit2).approve( + ERC20_ETHx, + address(bufferRouter_address), // Buffer + // Router + uint160(type(uint256).max), + uint48(block.timestamp + 1 days) + ); + + // Also approve ERC4626_sUSDC for Buffer Router + IERC20(address(ERC4626_sUSDC)).approve(permit2, type(uint256).max); + IPermit2(permit2).approve( + address(ERC4626_sUSDC), + address(bufferRouter_address), // Buffer + // Router + uint160(type(uint256).max), + uint48(block.timestamp + 1 days) + ); + + // Also approve sETHx for Buffer Router + IERC20(address(ERC4626_sETHx)).approve(permit2, type(uint256).max); + IPermit2(permit2).approve( + address(ERC4626_sETHx), + address(bufferRouter_address), // Buffer + // Router + uint160(type(uint256).max), + uint48(block.timestamp + 1 days) + ); + + // Approve Permit2 to spend sUSDC for the Balancer vault + IPermit2(permit2).approve( + address(ERC4626_sUSDC), + address(balancerV3Vault), + uint160(type(uint256).max), + uint48(block.timestamp + 1 days) + ); + + // Approve Permit2 to spend sETHx for the Balancer vault + IPermit2(permit2).approve( + address(ERC4626_sETHx), + address(balancerV3Vault), + uint160(type(uint256).max), + uint48(block.timestamp + 1 days) + ); + + // Approve Permit2 to spend sETHx for the Balancer vault + IPermit2(permit2).approve( + address(ERC4626_sGOETH), + address(balancerV3Vault), + uint160(type(uint256).max), + uint48(block.timestamp + 1 days) + ); + + // Initialize Balancer's internal ERC4626 buffer through the Buffer + // Router + IBufferRouter bufferRouter = IBufferRouter(bufferRouter_address); + + IERC20(ERC20_USDC).approve(address(ERC4626_sUSDC), type(uint256).max); + + IERC20(ERC20_ETHx).approve(address(ERC4626_sETHx), type(uint256).max); + + IERC20(ERC20_GOETH).approve(address(ERC4626_sGOETH), type(uint256).max); + + // Mint some ERC4626_sUSDC first + ERC4626_sUSDC.deposit(1000 * 10 ** 6, address(this)); + + // Mint some sETHx first + ERC4626_sETHx.deposit(1000 * 10 ** 18, address(this)); + + // Mint some sGOETH first + ERC4626_sGOETH.deposit(1000000 * (10 ** 18), address(this)); + + // Initialize buffer with equal amounts of underlying and wrapped tokens + bufferRouter.initializeBuffer( + IERC4626(address(ERC4626_sUSDC)), // wrapped token + 10 * 10 ** 6, // exactAmountUnderlyingIn (10 ERC20_USDC) + 10 * 10 ** 6, // exactAmountWrappedIn (10 ERC4626_sUSDC) + 9 * 10 ** 6 // minIssuedShares (90% of input as safety) + ); + + bufferRouter.initializeBuffer( + IERC4626(address(ERC4626_sETHx)), // wrapped token + 10 * 10 ** 18, // exactAmountUnderlyingIn (10 ETHx) + 10 * 10 ** 18, // exactAmountWrappedIn (10 sETHx) + 9 * 10 ** 18 // minIssuedShares (90% of input as safety) + ); + + bufferRouter.initializeBuffer( + IERC4626(address(ERC4626_sGOETH)), // wrapped token + 10 * 10 ** 18, // exactAmountUnderlyingIn (10 ETHx) + 10 * 10 ** 18, // exactAmountWrappedIn (10 sETHx) + 9 * 10 ** 18 // minIssuedShares (90% of input as safety) + ); + + // Deal ERC20_USDC to test contract + deal(ERC20_USDC, address(this), 1000000 * 10 ** 6); + + // Deal ETHx to test contract + deal(ERC20_ETHx, address(this), 1000 * 10 ** 18); + + // Approve ERC20_USDC spending to ERC4626_sUSDC vault + IERC20(ERC20_USDC).approve(address(ERC4626_sUSDC), type(uint256).max); + + // Approve ETHx spending to sETHx vault + IERC20(ERC20_ETHx).approve(address(ERC4626_sETHx), type(uint256).max); + + // Deposit ERC20_USDC to get ERC4626_sUSDC + ERC4626_sUSDC.deposit(1000000 * 10 ** 6, address(this)); + + // Deposit ETHx to get sETHx + ERC4626_sETHx.deposit(1000 * 10 ** 18, address(this)); + + IERC20(ERC20_USDC).approve(address(balancerV3Vault), type(uint256).max); + + IERC20(ERC20_ETHx).approve(address(balancerV3Vault), type(uint256).max); + + vm.label(address(balancerV3Vault), "BalancerV3Vault"); + vm.label(address(router), "BalancerV3BatchRouter"); + vm.label(address(adapter), "BalancerV3SwapAdapter"); + vm.label(ERC4626_waEthWETH, "ERC4626_waEthWETH"); + vm.label(ERC20_ETHx, "ERC20_ETHx"); + vm.label( + ERC4626_ERC20_ETHx_waWETH_STABLE_POOL, + "ERC4626_ERC20_ETHx_waWETH_STABLE_POOL" + ); + vm.label( + ERC20_ERC20_GOETH_USDC_WEIGHTED_POOL, + "ERC20_ERC20_GOETH_USDC_WEIGHTED_POOL" + ); + vm.label(ERC20_GOETH, "ERC20_GOETH"); + vm.label(ERC20_USDC, "ERC20_USDC"); + vm.label( + ERC4626_ERC4626_WETH_wstETH_STABLE_POOL, + "ERC4626_ERC4626_WETH_wstETH_STABLE_POOL" + ); + vm.label(ERC20_WETH, "ERC20_WETH"); + vm.label(ERC20_wstETH, "ERC20_wstETH"); + vm.label(ERC4626_waEthLidoWETH, "ERC4626_waEthLidoWETH"); + vm.label(ERC4626_waEthLidoWETH, "ERC4626_waEthLidoWETH"); + vm.label(permit2, "Permit2"); + } + + ///////////////////////////////////////// ERC4626_ERC20_DIRECT + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + function testPriceFuzzBalancerV3_ERC4626_ERC20_DIRECT(uint256 amount0) + public + { + address token0 = ERC4626_waEthWETH; + address token1 = ERC20_ETHx; + + bytes32 pool = bytes32(bytes20(ERC4626_ERC20_ETHx_waWETH_STABLE_POOL)); + uint256[] memory limits = adapter.getLimits(pool, token0, token1); + uint256 minTradeAmount = getMinTradeAmount(token0); + + vm.assume(amount0 < limits[0]); + vm.assume(amount0 > minTradeAmount); + + uint256[] memory amounts = new uint256[](1); + amounts[0] = amount0; + + __prankStaticCall(); + Fraction[] memory prices = adapter.price(pool, token0, token1, amounts); + + for (uint256 i = 0; i < prices.length; i++) { + assertGt(prices[i].numerator, 0); + assertGt(prices[i].denominator, 0); + } + } + + function testSwapFuzzBalancerV3_ERC4626_ERC20_DIRECT( + uint256 specifiedAmount, + bool isBuy + ) public { + address token0 = ERC4626_waEthWETH; + address token1 = ERC20_ETHx; + + OrderSide side = isBuy ? OrderSide.Buy : OrderSide.Sell; + bytes32 pool = bytes32(bytes20(ERC4626_ERC20_ETHx_waWETH_STABLE_POOL)); + uint256[] memory limits = adapter.getLimits(pool, token0, token1); + + if (side == OrderSide.Buy) { + vm.assume( + specifiedAmount < limits[1] + && specifiedAmount > getMinTradeAmount(token0) + ); + } else { + vm.assume( + specifiedAmount < limits[0] + && specifiedAmount > getMinTradeAmount(token0) + ); + } + + deal(token0, address(this), type(uint256).max); + IERC4626(token0).approve(address(adapter), type(uint256).max); + + uint256 bal0 = IERC4626(token0).balanceOf(address(this)); + uint256 bal1 = IERC20(token1).balanceOf(address(this)); + + uint256[] memory amounts = new uint256[](1); + amounts[0] = specifiedAmount; + Trade memory trade = + adapter.swap(pool, token0, token1, side, specifiedAmount); + + if (side == OrderSide.Buy) { + assertEq( + specifiedAmount, IERC20(token1).balanceOf(address(this)) - bal1 + ); + assertEq( + trade.calculatedAmount, + bal0 - IERC4626(token0).balanceOf(address(this)) + ); + } else { + assertEq( + specifiedAmount, + bal0 - IERC4626(token0).balanceOf(address(this)) + ); + assertEq( + trade.calculatedAmount, + IERC20(token1).balanceOf(address(this)) - bal1 + ); + } + } + + ///////////////////////////////////////// ERC20_ERC20_DIRECT + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + function testPriceFuzzBalancerV3_ERC20_ERC20_DIRECT(uint256 amount0) + public + { + address token0 = ERC20_GOETH; + address token1 = ERC20_USDC; + + bytes32 pool = bytes32(bytes20(ERC20_ERC20_GOETH_USDC_WEIGHTED_POOL)); + uint256[] memory limits = adapter.getLimits(pool, token0, token1); + + vm.assume(amount0 < limits[0] && amount0 > getMinTradeAmount(token0)); + + uint256[] memory amounts = new uint256[](1); + amounts[0] = amount0; + + __prankStaticCall(); + Fraction[] memory prices = adapter.price(pool, token0, token1, amounts); + + for (uint256 i = 0; i < prices.length; i++) { + // assertGt(prices[i].numerator, 0); + assertGt(prices[i].denominator, 0); + } + } + + function testSwapFuzzBalancerV3_ERC20_ERC20_DIRECT( + uint256 specifiedAmount, + bool isBuy + ) public { + address token0 = ERC20_GOETH; + address token1 = ERC20_USDC; + + OrderSide side = isBuy ? OrderSide.Buy : OrderSide.Sell; + bytes32 pool = bytes32(bytes20(ERC20_ERC20_GOETH_USDC_WEIGHTED_POOL)); + uint256[] memory limits = adapter.getLimits(pool, token0, token1); + + if (side == OrderSide.Buy) { + vm.assume( + specifiedAmount < limits[1] + && specifiedAmount > getMinTradeAmount(token1) + ); + } else { + vm.assume( + specifiedAmount < limits[0] + && specifiedAmount > getMinTradeAmount(token0) + ); + } + + deal(token0, address(this), type(uint256).max); + IERC20(token0).approve(address(adapter), type(uint256).max); + + uint256 bal0 = IERC20(token0).balanceOf(address(this)); + uint256 bal1 = IERC20(token1).balanceOf(address(this)); + + uint256[] memory amounts = new uint256[](1); + amounts[0] = specifiedAmount; + Trade memory trade = + adapter.swap(pool, token0, token1, side, specifiedAmount); + + if (side == OrderSide.Buy) { + assertEq( + specifiedAmount, IERC20(token1).balanceOf(address(this)) - bal1 + ); + assertEq( + trade.calculatedAmount, + bal0 - IERC20(token0).balanceOf(address(this)) + ); + } else { + assertEq( + specifiedAmount, bal0 - IERC20(token0).balanceOf(address(this)) + ); + assertEq( + trade.calculatedAmount, + IERC20(token1).balanceOf(address(this)) - bal1 + ); + } + } + + ///////////////////////////////////////// ERC20-->ERC20-->ERC4626 SWAP_WRAP + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + function testPriceFuzzBalancerV3_ERC20_ERC20_ERC4626_SWAP_WRAP( + uint256 amount0 + ) public { + address token0 = ERC20_GOETH; + address token1 = address(ERC4626_sUSDC); + + bytes32 pool = bytes32(bytes20(ERC20_ERC20_GOETH_USDC_WEIGHTED_POOL)); + uint256[] memory limits = adapter.getLimits(pool, token0, token1); + + // Use same bounds as swap test for sell orders + amount0 = bound(amount0, 10 ** 17, 1000 * 10 ** 18); + vm.assume(amount0 < limits[0]); + + uint256[] memory amounts = new uint256[](1); + amounts[0] = amount0; + + __prankStaticCall(); + Fraction[] memory prices = adapter.price(pool, token0, token1, amounts); + + for (uint256 i = 0; i < prices.length; i++) { + assertGt(prices[i].numerator, 0); + assertGt(prices[i].denominator, 0); + } + } + + function testSwapFuzzBalancerV3_ERC20_ERC20_ERC4626_SWAP_WRAP( + uint256 specifiedAmount, + bool isBuy + ) public { + // Scale bounds based on whether it's a buy or sell order + if (isBuy) { + specifiedAmount = + bound(specifiedAmount, 10 * 10 ** 6, 100000 * 10 ** 6); + } else { + specifiedAmount = bound(specifiedAmount, 10 ** 17, 1000 * 10 ** 18); + } + + address token0 = ERC20_GOETH; + address token1 = address(ERC4626_sUSDC); + + OrderSide side = isBuy ? OrderSide.Buy : OrderSide.Sell; + bytes32 pool = bytes32(bytes20(ERC20_ERC20_GOETH_USDC_WEIGHTED_POOL)); + uint256[] memory limits = adapter.getLimits(pool, token0, token1); + + if (side == OrderSide.Buy) { + vm.assume(specifiedAmount < limits[1]); + } else { + vm.assume(specifiedAmount < limits[0]); + } + + deal(token0, address(this), IERC20(token0).totalSupply() * 2); + IERC20(token0).approve(address(adapter), type(uint256).max); + + uint256 bal0 = IERC20(token0).balanceOf(address(this)); + uint256 bal1 = IERC4626(token1).balanceOf(address(this)); + + Trade memory trade = + adapter.swap(pool, token0, token1, side, specifiedAmount); + + if (side == OrderSide.Buy) { + assertEq( + specifiedAmount, + IERC4626(token1).balanceOf(address(this)) - bal1 + ); + assertEq( + trade.calculatedAmount, + bal0 - IERC20(token0).balanceOf(address(this)) + ); + } else { + assertEq( + specifiedAmount, bal0 - IERC20(token0).balanceOf(address(this)) + ); + assertEq( + trade.calculatedAmount, + IERC4626(token1).balanceOf(address(this)) - bal1 + ); + } + } + + //////////////////////////////////////// + // !!!////////////////////////////////////////////////// + ///////////////////////////////////////// ERC4626-->ERC20-->ERC20 + // UNWRAP_SWAP + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + function testPriceFuzzBalancerV3_ERC4626_ERC20_ERC20_UNWRAP_SWAP( + uint256 amount0 + ) public { + address token0 = address(ERC4626_sUSDC); + address token1 = ERC20_GOETH; + + bytes32 pool = bytes32(bytes20(ERC20_ERC20_GOETH_USDC_WEIGHTED_POOL)); + uint256[] memory limits = adapter.getLimits(pool, token0, token1); + + vm.assume(amount0 < limits[0] && amount0 > getMinTradeAmount(token0)); + + uint256[] memory amounts = new uint256[](1); + amounts[0] = amount0; + + __prankStaticCall(); + Fraction[] memory prices = adapter.price(pool, token0, token1, amounts); + + for (uint256 i = 0; i < prices.length; i++) { + assertGt(prices[i].numerator, 0); + assertGt(prices[i].denominator, 0); + } + } + + function testSwapFuzzBalancerV3_ERC4626_ERC20_ERC20_UNWRAP_SWAP( + uint256 specifiedAmount, + bool isBuy + ) public { + address token0 = address(ERC4626_sUSDC); + address token1 = ERC20_GOETH; + + OrderSide side = isBuy ? OrderSide.Buy : OrderSide.Sell; + + bytes32 pool = bytes32(bytes20(ERC20_ERC20_GOETH_USDC_WEIGHTED_POOL)); + uint256[] memory limits = adapter.getLimits(pool, token0, token1); + if (isBuy) { + vm.assume( + specifiedAmount < limits[1] && specifiedAmount > 10 ** 18 // as + // using a mock USDC, we set a custom limit here. + ); + } else { + vm.assume( + specifiedAmount < limits[0] + && specifiedAmount > getMinTradeAmount(token0) + ); + } + + if (side == OrderSide.Buy) { + vm.assume(specifiedAmount < limits[1]); + } else { + vm.assume(specifiedAmount < limits[0]); + } + + deal(token0, address(this), IERC20(token0).totalSupply() * 2); + IERC4626(token0).approve(address(adapter), type(uint256).max); + + uint256 bal0 = IERC4626(token0).balanceOf(address(this)); + uint256 bal1 = IERC20(token1).balanceOf(address(this)); + + Trade memory trade = + adapter.swap(pool, token0, token1, side, specifiedAmount); + + if (side == OrderSide.Buy) { + assertEq( + specifiedAmount, IERC20(token1).balanceOf(address(this)) - bal1 + ); + assertEq( + trade.calculatedAmount, + bal0 - IERC4626(token0).balanceOf(address(this)) + ); + } else { + assertEq( + specifiedAmount, + bal0 - IERC4626(token0).balanceOf(address(this)) + ); + assertEq( + trade.calculatedAmount, + IERC20(token1).balanceOf(address(this)) - bal1 + ); + } + } + + ///////////////////////////////////////// ERC4626_ERC4626_DIRECT + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + function testPriceFuzzBalancerV3_ERC4626_ERC4626_DIRECT(uint256 amount0) + public + { + address token0 = ERC4626_waEthLidoWETH; + address token1 = ERC4626_waEthLidowstETH; + + bytes32 pool = bytes32(bytes20(ERC4626_ERC4626_WETH_wstETH_STABLE_POOL)); + + uint256[] memory limits = adapter.getLimits(pool, token0, token1); + + uint256 minTradeAmount = getMinTradeAmount(token0); + + vm.assume(amount0 < limits[0]); + vm.assume(amount0 > minTradeAmount); + + uint256[] memory amounts = new uint256[](1); + amounts[0] = amount0; + + __prankStaticCall(); + Fraction[] memory prices = adapter.price(pool, token0, token1, amounts); + + for (uint256 i = 0; i < prices.length; i++) { + assertGt(prices[i].numerator, 0); + assertGt(prices[i].denominator, 0); + } + } + + function testSwapFuzzBalancerV3_ERC4626_ERC4626_DIRECT( + uint256 specifiedAmount, + bool isBuy + ) public { + address token0 = ERC4626_waEthLidoWETH; + address token1 = ERC4626_waEthLidowstETH; + + OrderSide side = isBuy ? OrderSide.Buy : OrderSide.Sell; + bytes32 pool = bytes32(bytes20(ERC4626_ERC4626_WETH_wstETH_STABLE_POOL)); + uint256[] memory limits = adapter.getLimits(pool, token0, token1); + + if (side == OrderSide.Buy) { + vm.assume( + specifiedAmount < limits[1] + && specifiedAmount > getMinTradeAmount(token1) + ); + } else { + vm.assume( + specifiedAmount < limits[0] + && specifiedAmount > getMinTradeAmount(token0) + ); + } + + deal(token0, address(this), IERC4626(token0).totalSupply() * 2); + IERC4626(token0).approve(address(adapter), type(uint256).max); + + uint256 bal0 = IERC4626(token0).balanceOf(address(this)); + uint256 bal1 = IERC4626(token1).balanceOf(address(this)); + + uint256[] memory amounts = new uint256[](1); + amounts[0] = specifiedAmount; + Trade memory trade = + adapter.swap(pool, token0, token1, side, specifiedAmount); + + if (side == OrderSide.Buy) { + assertEq( + specifiedAmount, + IERC4626(token1).balanceOf(address(this)) - bal1 + ); + assertEq( + trade.calculatedAmount, + bal0 - IERC4626(token0).balanceOf(address(this)) + ); + } else { + assertEq( + specifiedAmount, + bal0 - IERC4626(token0).balanceOf(address(this)) + ); + assertEq( + trade.calculatedAmount, + IERC4626(token1).balanceOf(address(this)) - bal1 + ); + } + } + + ///////////////////////////////////////// ERC20-->(ERC4626 --> ERC4626) + // WRAP_SWAP + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + function testPriceFuzzBalancerV3_ERC20_ERC4626_ERC4626_WRAP_SWAP( + uint256 amount0 + ) public { + address token0 = ERC20_WETH; + address token1 = ERC4626_waEthLidowstETH; + + bytes32 pool = bytes32(bytes20(ERC4626_ERC4626_WETH_wstETH_STABLE_POOL)); + + uint256[] memory limits = adapter.getLimits(pool, token0, token1); + + uint256 minTradeAmount = getMinTradeAmount(token0); + + vm.assume(amount0 < limits[0]); + vm.assume(amount0 > minTradeAmount); + + uint256[] memory amounts = new uint256[](1); + amounts[0] = amount0; + + __prankStaticCall(); + Fraction[] memory prices = adapter.price(pool, token0, token1, amounts); + + for (uint256 i = 0; i < prices.length; i++) { + assertGt(prices[i].numerator, 0); + assertGt(prices[i].denominator, 0); + } + } + + function testSwapFuzzBalancerV3_ERC20_ERC4626_ERC4626_WRAP_SWAP( + uint256 specifiedAmount, + bool isBuy + ) public { + address token0 = ERC20_WETH; + address token1 = ERC4626_waEthLidowstETH; + + OrderSide side = isBuy ? OrderSide.Buy : OrderSide.Sell; + bytes32 pool = bytes32(bytes20(ERC4626_ERC4626_WETH_wstETH_STABLE_POOL)); + uint256[] memory limits = adapter.getLimits(pool, token0, token1); + + if (side == OrderSide.Buy) { + vm.assume( + specifiedAmount < limits[1] + && specifiedAmount > getMinTradeAmount(token1) + ); + } else { + vm.assume( + specifiedAmount < limits[0] + && specifiedAmount > getMinTradeAmount(token0) + ); + } + + deal(token0, address(this), IERC20(token0).totalSupply() * 2); + IERC20(token0).approve(address(adapter), type(uint256).max); + + uint256 bal0 = IERC20(token0).balanceOf(address(this)); + uint256 bal1 = IERC4626(token1).balanceOf(address(this)); + + uint256[] memory amounts = new uint256[](1); + amounts[0] = specifiedAmount; + Trade memory trade = + adapter.swap(pool, token0, token1, side, specifiedAmount); + + if (side == OrderSide.Buy) { + assertEq( + specifiedAmount, + IERC4626(token1).balanceOf(address(this)) - bal1 + ); + assertEq( + trade.calculatedAmount, + bal0 - IERC20(token0).balanceOf(address(this)) + ); + } else { + assertEq( + specifiedAmount, bal0 - IERC20(token0).balanceOf(address(this)) + ); + assertEq( + trade.calculatedAmount, + IERC4626(token1).balanceOf(address(this)) - bal1 + ); + } + } + + ///////////////////////////////////////// (ERC4626-->ERC4626)--> ERC20 + // SWAP_UNWRAP + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + function testPriceFuzzBalancerV3_ERC4626_ERC4626_ERC20_SWAP_UNWRAP( + uint256 amount0 + ) public { + address token0 = ERC4626_waEthLidowstETH; + address token1 = ERC20_WETH; + + bytes32 pool = bytes32(bytes20(ERC4626_ERC4626_WETH_wstETH_STABLE_POOL)); + + uint256[] memory limits = adapter.getLimits(pool, token0, token1); + + uint256 minTradeAmount = getMinTradeAmount(token0); + + vm.assume(amount0 < limits[0]); + vm.assume(amount0 > minTradeAmount); + + uint256[] memory amounts = new uint256[](1); + amounts[0] = amount0; + + __prankStaticCall(); + Fraction[] memory prices = adapter.price(pool, token0, token1, amounts); + + for (uint256 i = 0; i < prices.length; i++) { + assertGt(prices[i].numerator, 0); + assertGt(prices[i].denominator, 0); + } + } + + function testSwapFuzzBalancerV3_ERC4626_ERC4626_ERC20_SWAP_UNWRAP( + uint256 specifiedAmount, + bool isBuy + ) public { + address token0 = ERC4626_waEthLidowstETH; + address token1 = ERC20_WETH; + + OrderSide side = isBuy ? OrderSide.Buy : OrderSide.Sell; + bytes32 pool = bytes32(bytes20(ERC4626_ERC4626_WETH_wstETH_STABLE_POOL)); + uint256[] memory limits = adapter.getLimits(pool, token0, token1); + + if (side == OrderSide.Buy) { + vm.assume( + specifiedAmount < limits[1] + && specifiedAmount > getMinTradeAmount(token1) + ); + } else { + vm.assume( + specifiedAmount < limits[0] + && specifiedAmount > getMinTradeAmount(token0) + ); + } + + deal(token0, address(this), type(uint256).max); + IERC4626(token0).approve(address(adapter), type(uint256).max); + + uint256 bal0 = IERC4626(token0).balanceOf(address(this)); + uint256 bal1 = IERC20(token1).balanceOf(address(this)); + + uint256[] memory amounts = new uint256[](1); + amounts[0] = specifiedAmount; + Trade memory trade = + adapter.swap(pool, token0, token1, side, specifiedAmount); + + if (side == OrderSide.Buy) { + assertEq( + specifiedAmount, IERC20(token1).balanceOf(address(this)) - bal1 + ); + assertEq( + trade.calculatedAmount, + bal0 - IERC4626(token0).balanceOf(address(this)) + ); + } else { + assertEq( + specifiedAmount, bal0 - IERC20(token0).balanceOf(address(this)) + ); + assertEq( + trade.calculatedAmount, + IERC20(token1).balanceOf(address(this)) - bal1 + ); + } + } + + ///////////////////////////////////////// (ERC20-->ERC4626)--> ERC20 + // SWAP_UNWRAP + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + function testPriceFuzzBalancerV3_ERC20_ERC4626_ERC20_SWAP_UNWRAP( + uint256 amount0 + ) public { + address token0 = ERC20_ETHx; + address token1 = ERC20_WETH; + + bytes32 pool = bytes32(bytes20(ERC4626_ERC20_ETHx_waWETH_STABLE_POOL)); + + uint256[] memory limits = adapter.getLimits(pool, token0, token1); + + uint256 minTradeAmount = getMinTradeAmount(token0); + + vm.assume(amount0 < limits[0]); + vm.assume(amount0 > minTradeAmount); + + uint256[] memory amounts = new uint256[](1); + amounts[0] = amount0; + + __prankStaticCall(); + Fraction[] memory prices = adapter.price(pool, token0, token1, amounts); + + for (uint256 i = 0; i < prices.length; i++) { + assertGt(prices[i].numerator, 0); + assertGt(prices[i].denominator, 0); + } + } + + function testSwapFuzzBalancerV3_ERC20_ERC4626_ERC20_SWAP_UNWRAP( + uint256 specifiedAmount, + bool isBuy + ) public { + address token0 = ERC20_ETHx; + address token1 = ERC20_WETH; + + OrderSide side = isBuy ? OrderSide.Buy : OrderSide.Sell; + bytes32 pool = bytes32(bytes20(ERC4626_ERC20_ETHx_waWETH_STABLE_POOL)); + uint256[] memory limits = adapter.getLimits(pool, token0, token1); + + if (side == OrderSide.Buy) { + vm.assume( + specifiedAmount < limits[1] + && specifiedAmount > getMinTradeAmount(token1) + ); + } else { + vm.assume( + specifiedAmount < limits[0] + && specifiedAmount > getMinTradeAmount(token0) + ); + } + + deal(token0, address(this), IERC20(token0).totalSupply() * 2); + IERC20(token0).approve(address(adapter), type(uint256).max); + + uint256 bal0 = IERC20(token0).balanceOf(address(this)); + uint256 bal1 = IERC20(token1).balanceOf(address(this)); + + uint256[] memory amounts = new uint256[](1); + amounts[0] = specifiedAmount; + Trade memory trade = + adapter.swap(pool, token0, token1, side, specifiedAmount); + + if (side == OrderSide.Buy) { + assertEq( + specifiedAmount, IERC20(token1).balanceOf(address(this)) - bal1 + ); + assertEq( + trade.calculatedAmount, + bal0 - IERC20(token0).balanceOf(address(this)) + ); + } else { + assertEq( + specifiedAmount, bal0 - IERC20(token0).balanceOf(address(this)) + ); + assertEq( + trade.calculatedAmount, + IERC20(token1).balanceOf(address(this)) - bal1 + ); + } + } + + ///////////////////////////////////////// (ERC20-->ERC4626)--> ERC20 + // SWAP_UNWRAP + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + function testPriceFuzzBalancerV3_ERC20_ERC4626_ERC20_ALTERNATIVE_SWAP_UNWRAP( + uint256 amount0 + ) public { + address token0 = ERC20_WETH; + address token1 = ERC20_ETHx; + + bytes32 pool = bytes32(bytes20(ERC4626_ERC20_ETHx_waWETH_STABLE_POOL)); + + uint256[] memory limits = adapter.getLimits(pool, token0, token1); + + uint256 minTradeAmount = getMinTradeAmount(token0); + + vm.assume(amount0 < limits[0]); + vm.assume(amount0 > minTradeAmount); + + uint256[] memory amounts = new uint256[](1); + amounts[0] = amount0; + + __prankStaticCall(); + Fraction[] memory prices = adapter.price(pool, token0, token1, amounts); + + for (uint256 i = 0; i < prices.length; i++) { + assertGt(prices[i].numerator, 0); + assertGt(prices[i].denominator, 0); + } + } + + function testSwapFuzzBalancerV3_ERC20_ERC4626_ERC20_ALTERNATIVE_SWAP_UNWRAP( + uint256 specifiedAmount, + bool isBuy + ) public { + address token0 = ERC20_WETH; + address token1 = ERC20_ETHx; + + OrderSide side = isBuy ? OrderSide.Buy : OrderSide.Sell; + bytes32 pool = bytes32(bytes20(ERC4626_ERC20_ETHx_waWETH_STABLE_POOL)); + uint256[] memory limits = adapter.getLimits(pool, token0, token1); + + if (side == OrderSide.Buy) { + vm.assume( + specifiedAmount < limits[1] + && specifiedAmount > getMinTradeAmount(token1) + ); + } else { + vm.assume( + specifiedAmount < limits[0] + && specifiedAmount > getMinTradeAmount(token0) + ); + } + + deal(token0, address(this), IERC20(token0).totalSupply() * 2); + IERC20(token0).approve(address(adapter), type(uint256).max); + + uint256 bal0 = IERC20(token0).balanceOf(address(this)); + uint256 bal1 = IERC20(token1).balanceOf(address(this)); + + uint256[] memory amounts = new uint256[](1); + amounts[0] = specifiedAmount; + Trade memory trade = + adapter.swap(pool, token0, token1, side, specifiedAmount); + + if (side == OrderSide.Buy) { + assertEq( + specifiedAmount, IERC20(token1).balanceOf(address(this)) - bal1 + ); + assertEq( + trade.calculatedAmount, + bal0 - IERC20(token0).balanceOf(address(this)) + ); + } else { + assertEq( + specifiedAmount, bal0 - IERC20(token0).balanceOf(address(this)) + ); + assertEq( + trade.calculatedAmount, + IERC20(token1).balanceOf(address(this)) - bal1 + ); + } + } + + ///////////////////////////////////////// ERC20-->ERC20 UNDERLYING DIRECT + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + function testPriceFuzzBalancerV3_ERC20_ERC20_UNDERLYING_DIRECT( + uint256 amount0 + ) public { + address token0 = ERC20_WETH; + address token1 = ERC20_wstETH; + + bytes32 pool = bytes32(bytes20(ERC4626_ERC4626_WETH_wstETH_STABLE_POOL)); + + uint256[] memory limits = adapter.getLimits(pool, token0, token1); + + uint256 minTradeAmount = getMinTradeAmount(token0); + + vm.assume(amount0 < limits[0]); + vm.assume(amount0 > minTradeAmount); + + uint256[] memory amounts = new uint256[](1); + amounts[0] = amount0; + + __prankStaticCall(); + Fraction[] memory prices = adapter.price(pool, token0, token1, amounts); + + for (uint256 i = 0; i < prices.length; i++) { + assertGt(prices[i].numerator, 0); + assertGt(prices[i].denominator, 0); + } + } + + function testSwapFuzzBalancerV3_ERC20_ERC20_UNDERLYING_DIRECT( + uint256 specifiedAmount, + bool isBuy + ) public { + address token0 = ERC20_WETH; + address token1 = ERC20_wstETH; + + OrderSide side = isBuy ? OrderSide.Buy : OrderSide.Sell; + bytes32 pool = bytes32(bytes20(ERC4626_ERC4626_WETH_wstETH_STABLE_POOL)); + uint256[] memory limits = adapter.getLimits(pool, token0, token1); + + if (side == OrderSide.Buy) { + vm.assume( + specifiedAmount < limits[1] + && specifiedAmount > getMinTradeAmount(token1) + ); + } else { + vm.assume( + specifiedAmount < limits[0] + && specifiedAmount > getMinTradeAmount(token0) + ); + } + + deal(token0, address(this), IERC20(token0).totalSupply() * 2); + IERC20(token0).approve(address(adapter), type(uint256).max); + + uint256 bal0 = IERC20(token0).balanceOf(address(this)); + uint256 bal1 = IERC20(token1).balanceOf(address(this)); + + uint256[] memory amounts = new uint256[](1); + amounts[0] = specifiedAmount; + Trade memory trade = + adapter.swap(pool, token0, token1, side, specifiedAmount); + + if (side == OrderSide.Buy) { + assertEq( + specifiedAmount, IERC20(token1).balanceOf(address(this)) - bal1 + ); + assertEq( + trade.calculatedAmount, + bal0 - IERC20(token0).balanceOf(address(this)) + ); + } else { + assertEq( + specifiedAmount, bal0 - IERC20(token0).balanceOf(address(this)) + ); + assertEq( + trade.calculatedAmount, + IERC20(token1).balanceOf(address(this)) - bal1 + ); + } + } + + ///////////////////////////////////////// ERC4626-->ERC20-->ERC4626 + // UNWRAP_SWAP + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + function testPriceFuzzBalancerV3_ERC4626_ERC20_ERC4626_UNWRAP_SWAP( + uint256 amount0 + ) public { + address token0 = address(ERC4626_sETHx); + address token1 = ERC4626_waEthWETH; + + bytes32 pool = bytes32(bytes20(ERC4626_ERC20_ETHx_waWETH_STABLE_POOL)); + + uint256[] memory limits = adapter.getLimits(pool, token0, token1); + + // Use same bounds as swap test + amount0 = bound(amount0, 10 ** 15, 1000 * 10 ** 18); + vm.assume(amount0 < limits[0]); + + uint256[] memory amounts = new uint256[](1); + amounts[0] = amount0; + + __prankStaticCall(); + Fraction[] memory prices = adapter.price(pool, token0, token1, amounts); + + for (uint256 i = 0; i < prices.length; i++) { + assertGt(prices[i].numerator, 0); + assertGt(prices[i].denominator, 0); + } + } + + function testSwapFuzzBalancerV3_ERC4626_ERC20_ERC4626_UNWRAP_SWAP( + uint256 specifiedAmount, + bool isBuy + ) public { + // Scale bounds based on whether it's a buy or sell order + if (isBuy) { + specifiedAmount = bound(specifiedAmount, 10 ** 15, 1000 * 10 ** 18); + } else { + specifiedAmount = bound(specifiedAmount, 10 ** 15, 1000 * 10 ** 18); + } + + address token0 = address(ERC4626_sETHx); + address token1 = ERC4626_waEthWETH; + + OrderSide side = isBuy ? OrderSide.Buy : OrderSide.Sell; + bytes32 pool = bytes32(bytes20(ERC4626_ERC20_ETHx_waWETH_STABLE_POOL)); + uint256[] memory limits = adapter.getLimits(pool, token0, token1); + + if (side == OrderSide.Buy) { + vm.assume(specifiedAmount < limits[1]); + } else { + vm.assume(specifiedAmount < limits[0]); + } + + // Deal tokens to test contract + deal(token0, address(this), IERC4626(token0).totalSupply() * 2); + IERC4626(token0).approve(address(adapter), type(uint256).max); + + uint256 bal0 = IERC4626(token0).balanceOf(address(this)); + uint256 bal1 = IERC4626(token1).balanceOf(address(this)); + + Trade memory trade = + adapter.swap(pool, token0, token1, side, specifiedAmount); + + if (side == OrderSide.Buy) { + assertEq( + specifiedAmount, + IERC4626(token1).balanceOf(address(this)) - bal1 + ); + assertEq( + trade.calculatedAmount, + bal0 - IERC4626(token0).balanceOf(address(this)) + ); + } else { + assertEq( + specifiedAmount, + bal0 - IERC4626(token0).balanceOf(address(this)) + ); + assertEq( + trade.calculatedAmount, + IERC4626(token1).balanceOf(address(this)) - bal1 + ); + } + } + + ///////////////////////////////////////// ERC4626-->ERC20-->ERC20-->ERC4626 + // UNWRAP_SWAP_WRAP + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + function testPriceFuzzBalancerV3_ERC4626_ERC20_ERC20_ERC4626_UNWRAP_SWAP_WRAP( + uint256 amount0 + ) public { + address token0 = address(ERC4626_sGOETH); + address token1 = address(ERC4626_sUSDC); + + bytes32 pool = bytes32(bytes20(ERC20_ERC20_GOETH_USDC_WEIGHTED_POOL)); + uint256[] memory limits = adapter.getLimits(pool, token0, token1); + + vm.assume(amount0 < limits[0] && amount0 > 1e17); + + uint256[] memory amounts = new uint256[](1); + amounts[0] = amount0; + + __prankStaticCall(); + Fraction[] memory prices = adapter.price(pool, token0, token1, amounts); + + for (uint256 i = 0; i < prices.length; i++) { + assertGt(prices[i].numerator, 0); + assertGt(prices[i].denominator, 0); + } + } + + function testSwapFuzzBalancerV3_ERC4626_ERC20_ERC20_ERC4626_UNWRAP_SWAP_WRAP( + uint256 specifiedAmount, + bool isBuy + ) public { + address token0 = address(ERC4626_sGOETH); + address token1 = address(ERC4626_sUSDC); + + bytes32 pool = bytes32(bytes20(ERC20_ERC20_GOETH_USDC_WEIGHTED_POOL)); + uint256[] memory limits = adapter.getLimits(pool, token0, token1); + OrderSide side = isBuy ? OrderSide.Buy : OrderSide.Sell; + + if (isBuy) { + vm.assume(specifiedAmount < limits[1] && specifiedAmount > 1e17); + deal(token0, address(this), type(uint256).max); + } else { + vm.assume(specifiedAmount < limits[0] && specifiedAmount > 1e17); + deal(token0, address(this), type(uint256).max); + } + + deal(token0, address(this), specifiedAmount); + + IERC4626(token0).approve(address(this), type(uint256).max); + IERC4626(token0).approve(address(adapter), type(uint256).max); + + uint256 bal0 = IERC4626(token0).balanceOf(address(this)); + uint256 bal1 = IERC4626(token1).balanceOf(address(this)); + + Trade memory trade = + adapter.swap(pool, token0, token1, side, specifiedAmount); + + if (side == OrderSide.Buy) { + assertEq( + specifiedAmount, + IERC4626(token1).balanceOf(address(this)) - bal1 + ); + assertEq( + trade.calculatedAmount, + bal0 - IERC4626(token0).balanceOf(address(this)) + ); + } else { + assertEq( + specifiedAmount, + bal0 - IERC4626(token0).balanceOf(address(this)) + ); + assertEq( + trade.calculatedAmount, + IERC4626(token1).balanceOf(address(this)) - bal1 + ); + } + } + + ///////////////////////////////////////// ERC20-->ERC4626-->ERC4626-->ERC20 + // UNWRAP_SWAP_WRAP + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + function testPriceFuzzBalancerV3_ERC20_ERC4626_ERC4626_ERC20_WRAP_SWAP_UNWRAP( + uint256 amount0 + ) public { + address token0 = address(ERC20_GOETH); + address token1 = address(ERC20_USDC); + + bytes32 pool = bytes32(bytes20(ERC20_ERC20_GOETH_USDC_WEIGHTED_POOL)); + uint256[] memory limits = adapter.getLimits(pool, token0, token1); + + vm.assume(amount0 < limits[0] && amount0 > 1e17); + + uint256[] memory amounts = new uint256[](1); + amounts[0] = amount0; + + __prankStaticCall(); + Fraction[] memory prices = adapter.price(pool, token0, token1, amounts); + + for (uint256 i = 0; i < prices.length; i++) { + assertGt(prices[i].numerator, 0); + assertGt(prices[i].denominator, 0); + } + } + + function __prankStaticCall() internal { + // Prank address 0x0 for both msg.sender and tx.origin (to identify as a + // staticcall). + vm.prank(address(0), address(0)); + } + + function getMinTradeAmount(address token) internal view returns (uint256) { + uint256 decimals = ERC20(token).decimals(); + uint256 decimalFactor = decimals; // n, e.g. stablecoins + if (decimals > 6) { + decimalFactor = decimals - 1; // 0.n + } + if (decimals > 12) { + decimalFactor = decimals - 3; // e.g. ETH, BTC, ... + } + + uint256 minTradeAmount = 10 ** decimalFactor; + + return minTradeAmount; + } +} diff --git a/evm/test/interfaces/IBufferRouter.sol b/evm/test/interfaces/IBufferRouter.sol new file mode 100644 index 0000000..4eb5920 --- /dev/null +++ b/evm/test/interfaces/IBufferRouter.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.26; + +import {IERC4626} from + "openzeppelin-contracts/contracts/interfaces/IERC4626.sol"; + +interface IBufferRouter { + function initializeBuffer( + IERC4626 wrappedToken, + uint256 exactAmountUnderlyingIn, + uint256 exactAmountWrappedIn, + uint256 minIssuedShares + ) external returns (uint256 issuedShares); +} diff --git a/evm/test/mocks/MockSETHx.sol b/evm/test/mocks/MockSETHx.sol new file mode 100644 index 0000000..dbf027a --- /dev/null +++ b/evm/test/mocks/MockSETHx.sol @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: AGPL-3.0-or-later +pragma solidity ^0.8.26; + +import "openzeppelin-contracts/contracts/token/ERC20/extensions/ERC4626.sol"; +import "openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; + +contract MockSETHx is ERC4626 { + bool public isBufferInitialized; + + constructor(IERC20 _asset) ERC4626(_asset) ERC20("Staked ETHx", "sETHx") {} + + function _decimals() internal pure returns (uint8) { + return 18; + } + + // Override convertToShares to implement 1:1 conversion for testing + function convertToShares(uint256 assets) + public + view + virtual + override + returns (uint256) + { + return assets; + } + + // Override convertToAssets to implement 1:1 conversion for testing + function convertToAssets(uint256 shares) + public + view + virtual + override + returns (uint256) + { + return shares; + } +} diff --git a/evm/test/mocks/MockSGOETH.sol b/evm/test/mocks/MockSGOETH.sol new file mode 100644 index 0000000..8556f47 --- /dev/null +++ b/evm/test/mocks/MockSGOETH.sol @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: AGPL-3.0-or-later +pragma solidity ^0.8.26; + +import "openzeppelin-contracts/contracts/token/ERC20/extensions/ERC4626.sol"; +import "openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; + +contract MockSGOETH is ERC4626 { + bool public isBufferInitialized; + + constructor(IERC20 _asset) + ERC4626(_asset) + ERC20("Staked GOETH", "sGOETH") + {} + + function _decimals() internal pure returns (uint8) { + return 18; + } + + // Override convertToShares to implement 1:1 conversion for testing + function convertToShares(uint256 assets) + public + view + virtual + override + returns (uint256) + { + return assets; + } + + // Override convertToAssets to implement 1:1 conversion for testing + function convertToAssets(uint256 shares) + public + view + virtual + override + returns (uint256) + { + return shares; + } +} diff --git a/evm/test/mocks/MockSUSDC.sol b/evm/test/mocks/MockSUSDC.sol new file mode 100644 index 0000000..1d6886b --- /dev/null +++ b/evm/test/mocks/MockSUSDC.sol @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: AGPL-3.0-or-later +pragma solidity ^0.8.26; + +import "openzeppelin-contracts/contracts/token/ERC20/extensions/ERC4626.sol"; +import "openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; + +contract MockSUSDC is ERC4626 { + bool public isBufferInitialized; + + constructor(IERC20 _asset) ERC4626(_asset) ERC20("Staked USDC", "sUSDC") {} + + function _decimals() internal pure returns (uint8) { + return 6; // Same as USDC + } + + // Override convertToShares to implement 1:1 conversion for testing + function convertToShares(uint256 assets) + public + view + virtual + override + returns (uint256) + { + return assets; + } + + // Override convertToAssets to implement 1:1 conversion for testing + function convertToAssets(uint256 shares) + public + view + virtual + override + returns (uint256) + { + return shares; + } +} diff --git a/substreams/Cargo.lock b/substreams/Cargo.lock index 444a962..ff5e2ed 100644 --- a/substreams/Cargo.lock +++ b/substreams/Cargo.lock @@ -174,7 +174,7 @@ dependencies = [ "serde_json", "sha3", "thiserror 1.0.69", - "uint", + "uint 0.9.5", ] [[package]] @@ -191,7 +191,7 @@ dependencies = [ "serde_json", "sha3", "thiserror 1.0.69", - "uint", + "uint 0.9.5", ] [[package]] @@ -253,6 +253,29 @@ dependencies = [ "tycho-substreams 0.2.2", ] +[[package]] +name = "ethereum-balancer-v3" +version = "0.4.0" +dependencies = [ + "anyhow", + "bytes", + "ethabi 18.0.0", + "getrandom", + "hex", + "hex-literal 0.4.1", + "itertools 0.13.0", + "keccak-hash", + "num-bigint", + "prost 0.11.9", + "prost-types 0.12.6", + "regex", + "serde", + "serde_qs", + "substreams", + "substreams-ethereum", + "tycho-substreams 0.2.1 (git+https://github.com/propeller-heads/tycho-protocol-sdk.git?rev=51995f9)", +] + [[package]] name = "ethereum-curve" version = "0.3.3" @@ -417,7 +440,7 @@ dependencies = [ "impl-rlp", "impl-serde 0.3.2", "primitive-types 0.11.1", - "uint", + "uint 0.9.5", ] [[package]] @@ -431,7 +454,7 @@ dependencies = [ "impl-rlp", "impl-serde 0.4.0", "primitive-types 0.12.2", - "uint", + "uint 0.9.5", ] [[package]] @@ -766,6 +789,16 @@ dependencies = [ "cpufeatures", ] +[[package]] +name = "keccak-hash" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e1b8590eb6148af2ea2d75f38e7d29f5ca970d5a4df456b3ef19b8b415d0264" +dependencies = [ + "primitive-types 0.13.1", + "tiny-keccak", +] + [[package]] name = "lazy_static" version = "1.5.0" @@ -973,7 +1006,7 @@ dependencies = [ "impl-codec", "impl-rlp", "impl-serde 0.3.2", - "uint", + "uint 0.9.5", ] [[package]] @@ -986,7 +1019,17 @@ dependencies = [ "impl-codec", "impl-rlp", "impl-serde 0.4.0", - "uint", + "uint 0.9.5", +] + +[[package]] +name = "primitive-types" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d15600a7d856470b7d278b3fe0e311fe28c2526348549f8ef2ff7db3299c87f5" +dependencies = [ + "fixed-hash 0.8.0", + "uint 0.10.0", ] [[package]] @@ -1738,6 +1781,18 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "uint" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "909988d098b2f738727b161a106cfc7cab00c539c2687a8836f8e565976fb53e" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + [[package]] name = "unicode-ident" version = "1.0.14" diff --git a/substreams/Cargo.toml b/substreams/Cargo.toml index a74a1e2..328d8dc 100644 --- a/substreams/Cargo.toml +++ b/substreams/Cargo.toml @@ -16,6 +16,7 @@ members = [ "ethereum-uniswap-v4", "ethereum-ekubo-v2", "ethereum-maverick-v2", + "ethereum-balancer-v3", ] resolver = "2" diff --git a/substreams/crates/tycho-substreams/src/contract.rs b/substreams/crates/tycho-substreams/src/contract.rs index 44a0207..16537ae 100644 --- a/substreams/crates/tycho-substreams/src/contract.rs +++ b/substreams/crates/tycho-substreams/src/contract.rs @@ -14,9 +14,9 @@ use crate::{ models::{InterimContractChange, TransactionChanges}, prelude::TransactionChangesBuilder, }; -use substreams_ethereum::pb::{ - eth, - eth::v2::{block::DetailLevel, CallType, TransactionTrace}, +use substreams_ethereum::pb::eth::{ + self, + v2::{block::DetailLevel, CallType, TransactionTrace}, }; /// Extracts and aggregates contract changes from a block. diff --git a/substreams/ethereum-balancer-v3/Cargo.lock b/substreams/ethereum-balancer-v3/Cargo.lock new file mode 100644 index 0000000..46d30eb --- /dev/null +++ b/substreams/ethereum-balancer-v3/Cargo.lock @@ -0,0 +1,1330 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "anyhow" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "bigdecimal" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6773ddc0eafc0e509fb60e48dff7f450f8e674a0686ae8605e8d9901bd5eefa" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "bitflags" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "byte-slice-cast" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crunchy" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "ethabi" +version = "17.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4966fba78396ff92db3b817ee71143eccd98acf0f876b8d600e585a670c5d1b" +dependencies = [ + "ethereum-types", + "hex", + "once_cell", + "regex", + "serde", + "serde_json", + "sha3", + "thiserror 1.0.69", + "uint", +] + +[[package]] +name = "ethbloom" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11da94e443c60508eb62cf256243a64da87304c2802ac2528847f79d750007ef" +dependencies = [ + "crunchy", + "fixed-hash", + "impl-rlp", + "impl-serde", + "tiny-keccak", +] + +[[package]] +name = "ethereum-balancer-v3" +version = "0.0.1" +dependencies = [ + "anyhow", + "getrandom", + "itertools 0.12.1", + "num-bigint", + "num-traits", + "regex", + "substreams-database-change", + "substreams-entity-change", + "substreams-ethereum", +] + +[[package]] +name = "ethereum-types" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2827b94c556145446fcce834ca86b7abf0c39a805883fe20e72c5bfdb5a0dc6" +dependencies = [ + "ethbloom", + "fixed-hash", + "impl-rlp", + "impl-serde", + "primitive-types", + "uint", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "fixed-hash" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcf0ed7fe52a17a03854ec54a9f76d6d84508d1c0e66bc1793301c73fc8493c" +dependencies = [ + "byteorder", + "rand", + "rustc-hex", + "static_assertions", +] + +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hex-literal" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" + +[[package]] +name = "home" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "impl-codec" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" +dependencies = [ + "parity-scale-codec", +] + +[[package]] +name = "impl-rlp" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28220f89297a075ddc7245cd538076ee98b01f2a9c23a53a4f1105d5a322808" +dependencies = [ + "rlp", +] + +[[package]] +name = "impl-serde" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4551f042f3438e64dbd6226b20527fc84a6e1fe65688b58746a2f53623f25f5c" +dependencies = [ + "serde", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "indexmap" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +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 = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" + +[[package]] +name = "keccak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.169" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" + +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "log" +version = "0.4.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "multimap" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" + +[[package]] +name = "multimap" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "defc4c55412d89136f966bbb339008b474350e5e6e78d2714439c386b3137a03" + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[package]] +name = "pad" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2ad9b889f1b12e0b9ee24db044b5129150d5eada288edc800f789928dc8c0e3" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "parity-scale-codec" +version = "3.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" +dependencies = [ + "arrayvec", + "bitvec", + "byte-slice-cast", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "serde", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "pest" +version = "2.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b7cafe60d6cf8e62e1b9b2ea516a089c008945bb5a275416789e7db0bc199dc" +dependencies = [ + "memchr", + "thiserror 2.0.11", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "816518421cfc6887a0d62bf441b6ffb4536fcc926395a69e1a85852d4363f57e" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d1396fd3a870fc7838768d171b4616d5c91f6cc25e377b673d714567d99377b" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "pest_meta" +version = "2.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1e58089ea25d717bfd31fb534e4f3afcc2cc569c70de3e239778991ea3b7dea" +dependencies = [ + "once_cell", + "pest", + "sha2", +] + +[[package]] +name = "petgraph" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" +dependencies = [ + "fixedbitset", + "indexmap", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "prettyplease" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86" +dependencies = [ + "proc-macro2", + "syn 1.0.109", +] + +[[package]] +name = "prettyplease" +version = "0.2.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6924ced06e1f7dfe3fa48d57b9f74f55d8915f5036121bef647ef4b204895fac" +dependencies = [ + "proc-macro2", + "syn 2.0.96", +] + +[[package]] +name = "primitive-types" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e28720988bff275df1f51b171e1b2a18c30d194c4d2b61defdacecd625a5d94a" +dependencies = [ + "fixed-hash", + "impl-codec", + "impl-rlp", + "impl-serde", + "uint", +] + +[[package]] +name = "proc-macro-crate" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro2" +version = "1.0.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "prost" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" +dependencies = [ + "bytes", + "prost-derive 0.11.9", +] + +[[package]] +name = "prost" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c0fef6c4230e4ccf618a35c59d7ede15dea37de8427500f50aff708806e42ec" +dependencies = [ + "bytes", + "prost-derive 0.13.4", +] + +[[package]] +name = "prost-build" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "119533552c9a7ffacc21e099c24a0ac8bb19c2a2a3f363de84cd9b844feab270" +dependencies = [ + "bytes", + "heck 0.4.1", + "itertools 0.10.5", + "lazy_static", + "log", + "multimap 0.8.3", + "petgraph", + "prettyplease 0.1.25", + "prost 0.11.9", + "prost-types 0.11.9", + "regex", + "syn 1.0.109", + "tempfile", + "which", +] + +[[package]] +name = "prost-build" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0f3e5beed80eb580c68e2c600937ac2c4eedabdfd5ef1e5b7ea4f3fba84497b" +dependencies = [ + "heck 0.5.0", + "itertools 0.13.0", + "log", + "multimap 0.10.0", + "once_cell", + "petgraph", + "prettyplease 0.2.29", + "prost 0.13.4", + "prost-types 0.13.4", + "regex", + "syn 2.0.96", + "tempfile", +] + +[[package]] +name = "prost-derive" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" +dependencies = [ + "anyhow", + "itertools 0.10.5", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "prost-derive" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "157c5a9d7ea5c2ed2d9fb8f495b64759f7816c7eaea54ba3978f0d63000162e3" +dependencies = [ + "anyhow", + "itertools 0.13.0", + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "prost-types" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213622a1460818959ac1181aaeb2dc9c7f63df720db7d788b3e24eacd1983e13" +dependencies = [ + "prost 0.11.9", +] + +[[package]] +name = "prost-types" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc2f1e56baa61e93533aebc21af4d2134b70f66275e0fcdf3cbe43d77ff7e8fc" +dependencies = [ + "prost 0.13.4", +] + +[[package]] +name = "quote" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "rlp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" +dependencies = [ + "bytes", + "rustc-hex", +] + +[[package]] +name = "rustc-hex" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" + +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "serde" +version = "1.0.217" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.217" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "serde_json" +version = "1.0.137" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "930cfb6e6abf99298aaad7d29abbef7a9999a9a8806a40088f55f0dcec03146b" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest", + "keccak", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "substreams" +version = "0.5.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92e47e531af83a3cbb78c627ee8232a0ac86604f11c89e34bd4b721ec41e03e5" +dependencies = [ + "anyhow", + "bigdecimal", + "hex", + "hex-literal", + "num-bigint", + "num-integer", + "num-traits", + "pad", + "pest", + "pest_derive", + "prost 0.11.9", + "prost-build 0.11.9", + "prost-types 0.11.9", + "substreams-macro 0.5.22", + "thiserror 1.0.69", +] + +[[package]] +name = "substreams" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bb63116b90d4c174114fb237a8916dd995c939874f7576333990a44d78b642a" +dependencies = [ + "anyhow", + "bigdecimal", + "hex", + "hex-literal", + "num-bigint", + "num-integer", + "num-traits", + "pad", + "pest", + "pest_derive", + "prost 0.13.4", + "prost-build 0.13.4", + "prost-types 0.13.4", + "substreams-macro 0.6.0", + "thiserror 1.0.69", +] + +[[package]] +name = "substreams-database-change" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06fe88d25f4c3d56fc2a92583708dc34822ea99fb3f96609f9d684f717974b27" +dependencies = [ + "prost 0.13.4", + "prost-types 0.13.4", + "substreams 0.6.0", +] + +[[package]] +name = "substreams-entity-change" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0587b8d5dd7bffb0415d544c31e742c4cabdb81bbe9a3abfffff125185e4e9e8" +dependencies = [ + "base64", + "prost 0.13.4", + "prost-types 0.13.4", + "substreams 0.6.0", +] + +[[package]] +name = "substreams-ethereum" +version = "0.9.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d033738be190ad9c9a63712cf121e4f33ae9c57845c64021e421c45aac688b5" +dependencies = [ + "getrandom", + "num-bigint", + "substreams 0.5.22", + "substreams-ethereum-abigen", + "substreams-ethereum-core", + "substreams-ethereum-derive", +] + +[[package]] +name = "substreams-ethereum-abigen" +version = "0.9.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27ef0adda971fbbd085545e73ccd7efbc12e31139cd301252f478e6b9743ff65" +dependencies = [ + "anyhow", + "ethabi", + "heck 0.4.1", + "hex", + "prettyplease 0.1.25", + "proc-macro2", + "quote", + "substreams-ethereum-core", + "syn 1.0.109", +] + +[[package]] +name = "substreams-ethereum-core" +version = "0.9.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a38e740018de8c2453f08621bab84ac55b0f1bfd42d56cf8b43ad340e670862" +dependencies = [ + "bigdecimal", + "ethabi", + "getrandom", + "num-bigint", + "prost 0.11.9", + "prost-build 0.11.9", + "prost-types 0.11.9", + "substreams 0.5.22", +] + +[[package]] +name = "substreams-ethereum-derive" +version = "0.9.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55c934c70e6ab1fe11a89f401f36e7d9be3fe087687395767a4c13ab3d6bd055" +dependencies = [ + "ethabi", + "heck 0.4.1", + "hex", + "num-bigint", + "proc-macro2", + "quote", + "substreams-ethereum-abigen", + "syn 1.0.109", +] + +[[package]] +name = "substreams-macro" +version = "0.5.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4ac77f08d723dace35739d65df8ed122f6d04e2a3e47929831d4021e3339240" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "thiserror 1.0.69", +] + +[[package]] +name = "substreams-macro" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36f36e9da94db29f49daf3ab6b47b529b57c43fc5d58bc35b160aaad1a7233f" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "thiserror 1.0.69", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.96" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "tempfile" +version = "3.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8a559c81686f576e8cd0290cd2a24a2a9ad80c98b3478856500fcbd7acd704" +dependencies = [ + "cfg-if", + "fastrand", + "getrandom", + "once_cell", + "rustix", + "windows-sys", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc" +dependencies = [ + "thiserror-impl 2.0.11", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" + +[[package]] +name = "toml_edit" +version = "0.22.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "ucd-trie" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" + +[[package]] +name = "uint" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + +[[package]] +name = "unicode-ident" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11cd88e12b17c6494200a9c1b683a04fcac9573ed74cd1b62aeb2727c5592243" + +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.6.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8d71a593cc5c42ad7876e2c1fda56f314f3754c084128833e64f1345ff8a03a" +dependencies = [ + "memchr", +] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] diff --git a/substreams/ethereum-balancer-v3/Cargo.toml b/substreams/ethereum-balancer-v3/Cargo.toml new file mode 100644 index 0000000..0538409 --- /dev/null +++ b/substreams/ethereum-balancer-v3/Cargo.toml @@ -0,0 +1,34 @@ +[package] +name = "ethereum-balancer-v3" +version = "0.4.0" +edition = "2021" + +[lib] +name = "ethereum_balancer_v3" +crate-type = ["cdylib"] + +[dependencies] +substreams = "0.5.22" +substreams-ethereum = "0.9.9" +prost = "0.11" +prost-types = "0.12.3" +hex-literal = "0.4.1" +ethabi = "18.0.0" +hex = "0.4.3" +bytes = "1.5.0" +anyhow = "1.0.75" +num-bigint = "0.4.4" +tycho-substreams = { git = "https://github.com/propeller-heads/tycho-protocol-sdk.git", rev = "51995f9" } +serde = { version = "1.0", features = ["derive"] } +serde_qs = "0.13.0" +itertools = "0.13.0" +keccak-hash = "0.11.0" + +[build-dependencies] +anyhow = "1" +substreams-ethereum = "0.9" +regex = "1.10.0" + +# 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-v3/Readme.md b/substreams/ethereum-balancer-v3/Readme.md new file mode 100644 index 0000000..1d13889 --- /dev/null +++ b/substreams/ethereum-balancer-v3/Readme.md @@ -0,0 +1,38 @@ +# balancer_v3 Substreams modules + +This package was initialized via `substreams init`, using the `evm-events-calls` template. + +## Usage + +```bash +substreams build +substreams auth +substreams gui # Get streaming! +substreams registry login # Login to substreams.dev +substreams registry publish # Publish your Substreams to substreams.dev +``` + +## Modules + +All of these modules produce data filtered by these contracts: +- _vault_ at **0xba1333333333a1ba1108e8412f11850a5c319ba9** +- _stable_pool_factory_ at **0xb9d01ca61b9c181da1051bfdd28e1097e920ab14** +- _weighted_pool_factory_ at **0x201efd508c8dfe9de1a13c2452863a78cb2a86cc** +- stable_pool contracts created from _stable_pool_factory_ +- weighted_pool contracts created from _weighted_pool_factory_ +### `map_events_calls` + +This module gets you events _and_ calls + + +### `map_events` + +This module gets you only events that matched. + + + +### `map_calls` + +This module gets you only calls that matched. + + diff --git a/substreams/ethereum-balancer-v3/abi/stable_pool_contract.abi.json b/substreams/ethereum-balancer-v3/abi/stable_pool_contract.abi.json new file mode 100644 index 0000000..4378028 --- /dev/null +++ b/substreams/ethereum-balancer-v3/abi/stable_pool_contract.abi.json @@ -0,0 +1 @@ +[{"inputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"uint256","name":"amplificationParameter","type":"uint256"},{"internalType":"string","name":"version","type":"string"}],"internalType":"struct StablePool.NewPoolParams","name":"params","type":"tuple"},{"internalType":"contract IVault","name":"vault","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AmpUpdateAlreadyStarted","type":"error"},{"inputs":[],"name":"AmpUpdateDurationTooShort","type":"error"},{"inputs":[],"name":"AmpUpdateNotStarted","type":"error"},{"inputs":[],"name":"AmpUpdateRateTooFast","type":"error"},{"inputs":[],"name":"AmplificationFactorTooHigh","type":"error"},{"inputs":[],"name":"AmplificationFactorTooLow","type":"error"},{"inputs":[],"name":"ECDSAInvalidSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"name":"ECDSAInvalidSignatureLength","type":"error"},{"inputs":[{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"ECDSAInvalidSignatureS","type":"error"},{"inputs":[{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"ERC2612ExpiredSignature","type":"error"},{"inputs":[{"internalType":"address","name":"signer","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC2612InvalidSigner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"currentNonce","type":"uint256"}],"name":"InvalidAccountNonce","type":"error"},{"inputs":[],"name":"InvalidShortString","type":"error"},{"inputs":[{"internalType":"uint8","name":"bits","type":"uint8"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"SafeCastOverflowedUintDowncast","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"SenderIsNotVault","type":"error"},{"inputs":[],"name":"SenderNotAllowed","type":"error"},{"inputs":[],"name":"StableComputeBalanceDidNotConverge","type":"error"},{"inputs":[],"name":"StableInvariantDidNotConverge","type":"error"},{"inputs":[{"internalType":"string","name":"str","type":"string"}],"name":"StringTooLong","type":"error"},{"inputs":[],"name":"ZeroDivision","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"startValue","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"endValue","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startTime","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"endTime","type":"uint256"}],"name":"AmpUpdateStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"currentValue","type":"uint256"}],"name":"AmpUpdateStopped","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[],"name":"EIP712DomainChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERMIT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"balancesLiveScaled18","type":"uint256[]"},{"internalType":"uint256","name":"tokenInIndex","type":"uint256"},{"internalType":"uint256","name":"invariantRatio","type":"uint256"}],"name":"computeBalance","outputs":[{"internalType":"uint256","name":"newBalance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"balancesLiveScaled18","type":"uint256[]"},{"internalType":"enum Rounding","name":"rounding","type":"uint8"}],"name":"computeInvariant","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"eip712Domain","outputs":[{"internalType":"bytes1","name":"fields","type":"bytes1"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"verifyingContract","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256[]","name":"extensions","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"emitApproval","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"emitTransfer","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":"getAggregateFeePercentages","outputs":[{"internalType":"uint256","name":"aggregateSwapFeePercentage","type":"uint256"},{"internalType":"uint256","name":"aggregateYieldFeePercentage","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAmplificationParameter","outputs":[{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bool","name":"isUpdating","type":"bool"},{"internalType":"uint256","name":"precision","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAmplificationState","outputs":[{"components":[{"internalType":"uint64","name":"startValue","type":"uint64"},{"internalType":"uint64","name":"endValue","type":"uint64"},{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"endTime","type":"uint32"}],"internalType":"struct AmplificationState","name":"amplificationState","type":"tuple"},{"internalType":"uint256","name":"precision","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentLiveBalances","outputs":[{"internalType":"uint256[]","name":"balancesLiveScaled18","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMaximumInvariantRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getMaximumSwapFeePercentage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getMinimumInvariantRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getMinimumSwapFeePercentage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStablePoolDynamicData","outputs":[{"components":[{"internalType":"uint256[]","name":"balancesLiveScaled18","type":"uint256[]"},{"internalType":"uint256[]","name":"tokenRates","type":"uint256[]"},{"internalType":"uint256","name":"staticSwapFeePercentage","type":"uint256"},{"internalType":"uint256","name":"totalSupply","type":"uint256"},{"internalType":"uint256","name":"bptRate","type":"uint256"},{"internalType":"uint256","name":"amplificationParameter","type":"uint256"},{"internalType":"uint256","name":"startValue","type":"uint256"},{"internalType":"uint256","name":"endValue","type":"uint256"},{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"endTime","type":"uint32"},{"internalType":"bool","name":"isAmpUpdating","type":"bool"},{"internalType":"bool","name":"isPoolInitialized","type":"bool"},{"internalType":"bool","name":"isPoolPaused","type":"bool"},{"internalType":"bool","name":"isPoolInRecoveryMode","type":"bool"}],"internalType":"struct StablePoolDynamicData","name":"data","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStablePoolImmutableData","outputs":[{"components":[{"internalType":"contract IERC20[]","name":"tokens","type":"address[]"},{"internalType":"uint256[]","name":"decimalScalingFactors","type":"uint256[]"},{"internalType":"uint256","name":"amplificationParameterPrecision","type":"uint256"}],"internalType":"struct StablePoolImmutableData","name":"data","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStaticSwapFeePercentage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTokenInfo","outputs":[{"internalType":"contract IERC20[]","name":"tokens","type":"address[]"},{"components":[{"internalType":"enum TokenType","name":"tokenType","type":"uint8"},{"internalType":"contract IRateProvider","name":"rateProvider","type":"address"},{"internalType":"bool","name":"paysYieldFees","type":"bool"}],"internalType":"struct TokenInfo[]","name":"tokenInfo","type":"tuple[]"},{"internalType":"uint256[]","name":"balancesRaw","type":"uint256[]"},{"internalType":"uint256[]","name":"lastBalancesLiveScaled18","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTokens","outputs":[{"internalType":"contract IERC20[]","name":"tokens","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getVault","outputs":[{"internalType":"contract IVault","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"incrementNonce","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"enum SwapKind","name":"kind","type":"uint8"},{"internalType":"uint256","name":"amountGivenScaled18","type":"uint256"},{"internalType":"uint256[]","name":"balancesScaled18","type":"uint256[]"},{"internalType":"uint256","name":"indexIn","type":"uint256"},{"internalType":"uint256","name":"indexOut","type":"uint256"},{"internalType":"address","name":"router","type":"address"},{"internalType":"bytes","name":"userData","type":"bytes"}],"internalType":"struct PoolSwapParams","name":"request","type":"tuple"}],"name":"onSwap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"rawEndValue","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"}],"name":"startAmplificationParameterUpdate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stopAmplificationParameterUpdate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","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-v3/abi/stable_pool_factory_contract.abi.json b/substreams/ethereum-balancer-v3/abi/stable_pool_factory_contract.abi.json new file mode 100644 index 0000000..2616433 --- /dev/null +++ b/substreams/ethereum-balancer-v3/abi/stable_pool_factory_contract.abi.json @@ -0,0 +1 @@ +[{"inputs":[{"internalType":"contract IVault","name":"vault","type":"address"},{"internalType":"uint32","name":"pauseWindowDuration","type":"uint32"},{"internalType":"string","name":"factoryVersion","type":"string"},{"internalType":"string","name":"poolVersion","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"Create2EmptyBytecode","type":"error"},{"inputs":[],"name":"Create2FailedDeployment","type":"error"},{"inputs":[{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"Create2InsufficientBalance","type":"error"},{"inputs":[],"name":"Disabled","type":"error"},{"inputs":[],"name":"IndexOutOfBounds","type":"error"},{"inputs":[],"name":"MaxTokens","type":"error"},{"inputs":[],"name":"PoolPauseWindowDurationOverflow","type":"error"},{"inputs":[],"name":"SenderNotAllowed","type":"error"},{"inputs":[],"name":"StandardPoolWithCreator","type":"error"},{"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"},{"components":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"enum TokenType","name":"tokenType","type":"uint8"},{"internalType":"contract IRateProvider","name":"rateProvider","type":"address"},{"internalType":"bool","name":"paysYieldFees","type":"bool"}],"internalType":"struct TokenConfig[]","name":"tokens","type":"tuple[]"},{"internalType":"uint256","name":"amplificationParameter","type":"uint256"},{"components":[{"internalType":"address","name":"pauseManager","type":"address"},{"internalType":"address","name":"swapFeeManager","type":"address"},{"internalType":"address","name":"poolCreator","type":"address"}],"internalType":"struct PoolRoleAccounts","name":"roleAccounts","type":"tuple"},{"internalType":"uint256","name":"swapFeePercentage","type":"uint256"},{"internalType":"address","name":"poolHooksContract","type":"address"},{"internalType":"bool","name":"enableDonation","type":"bool"},{"internalType":"bool","name":"disableUnbalancedLiquidity","type":"bool"},{"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":"getDefaultLiquidityManagement","outputs":[{"components":[{"internalType":"bool","name":"disableUnbalancedLiquidity","type":"bool"},{"internalType":"bool","name":"enableAddLiquidityCustom","type":"bool"},{"internalType":"bool","name":"enableRemoveLiquidityCustom","type":"bool"},{"internalType":"bool","name":"enableDonation","type":"bool"}],"internalType":"struct LiquidityManagement","name":"liquidityManagement","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getDefaultPoolHooksContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"constructorArgs","type":"bytes"},{"internalType":"bytes32","name":"salt","type":"bytes32"}],"name":"getDeploymentAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNewPoolPauseWindowEndTime","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOriginalPauseWindowEndTime","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPauseWindowDuration","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPoolCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPoolVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPools","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint256","name":"count","type":"uint256"}],"name":"getPoolsInRange","outputs":[{"internalType":"address[]","name":"pools","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-v3/abi/vault_contract.abi.json b/substreams/ethereum-balancer-v3/abi/vault_contract.abi.json new file mode 100644 index 0000000..558877d --- /dev/null +++ b/substreams/ethereum-balancer-v3/abi/vault_contract.abi.json @@ -0,0 +1 @@ +[{"inputs":[{"internalType":"contract IVaultExtension","name":"vaultExtension","type":"address"},{"internalType":"contract IAuthorizer","name":"authorizer","type":"address"},{"internalType":"contract IProtocolFeeController","name":"protocolFeeController","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"AfterAddLiquidityHookFailed","type":"error"},{"inputs":[],"name":"AfterInitializeHookFailed","type":"error"},{"inputs":[],"name":"AfterRemoveLiquidityHookFailed","type":"error"},{"inputs":[],"name":"AfterSwapHookFailed","type":"error"},{"inputs":[],"name":"AllZeroInputs","type":"error"},{"inputs":[],"name":"AmountGivenZero","type":"error"},{"inputs":[{"internalType":"contract IERC20","name":"tokenIn","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"maxAmountIn","type":"uint256"}],"name":"AmountInAboveMax","type":"error"},{"inputs":[{"internalType":"contract IERC20","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"minAmountOut","type":"uint256"}],"name":"AmountOutBelowMin","type":"error"},{"inputs":[],"name":"BalanceNotSettled","type":"error"},{"inputs":[],"name":"BalanceOverflow","type":"error"},{"inputs":[],"name":"BeforeAddLiquidityHookFailed","type":"error"},{"inputs":[],"name":"BeforeInitializeHookFailed","type":"error"},{"inputs":[],"name":"BeforeRemoveLiquidityHookFailed","type":"error"},{"inputs":[],"name":"BeforeSwapHookFailed","type":"error"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"maxAmountIn","type":"uint256"}],"name":"BptAmountInAboveMax","type":"error"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"minAmountOut","type":"uint256"}],"name":"BptAmountOutBelowMin","type":"error"},{"inputs":[{"internalType":"contract IERC4626","name":"wrappedToken","type":"address"}],"name":"BufferAlreadyInitialized","type":"error"},{"inputs":[{"internalType":"contract IERC4626","name":"wrappedToken","type":"address"}],"name":"BufferNotInitialized","type":"error"},{"inputs":[],"name":"BufferSharesInvalidOwner","type":"error"},{"inputs":[],"name":"BufferSharesInvalidReceiver","type":"error"},{"inputs":[{"internalType":"uint256","name":"totalSupply","type":"uint256"}],"name":"BufferTotalSupplyTooLow","type":"error"},{"inputs":[],"name":"CannotReceiveEth","type":"error"},{"inputs":[],"name":"CannotSwapSameToken","type":"error"},{"inputs":[],"name":"DoesNotSupportAddLiquidityCustom","type":"error"},{"inputs":[],"name":"DoesNotSupportDonation","type":"error"},{"inputs":[],"name":"DoesNotSupportRemoveLiquidityCustom","type":"error"},{"inputs":[],"name":"DoesNotSupportUnbalancedLiquidity","type":"error"},{"inputs":[],"name":"DynamicSwapFeeHookFailed","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC20InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC20InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC20InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"ERC20InvalidSpender","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"FeePrecisionTooHigh","type":"error"},{"inputs":[{"internalType":"contract IERC20","name":"tokenIn","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"maxAmountIn","type":"uint256"}],"name":"HookAdjustedAmountInAboveMax","type":"error"},{"inputs":[{"internalType":"contract IERC20","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"minAmountOut","type":"uint256"}],"name":"HookAdjustedAmountOutBelowMin","type":"error"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"limit","type":"uint256"}],"name":"HookAdjustedSwapLimit","type":"error"},{"inputs":[{"internalType":"address","name":"poolHooksContract","type":"address"},{"internalType":"address","name":"pool","type":"address"},{"internalType":"address","name":"poolFactory","type":"address"}],"name":"HookRegistrationFailed","type":"error"},{"inputs":[],"name":"InputLengthMismatch","type":"error"},{"inputs":[],"name":"InvalidAddLiquidityKind","type":"error"},{"inputs":[],"name":"InvalidRemoveLiquidityKind","type":"error"},{"inputs":[],"name":"InvalidToken","type":"error"},{"inputs":[],"name":"InvalidTokenConfiguration","type":"error"},{"inputs":[],"name":"InvalidTokenDecimals","type":"error"},{"inputs":[],"name":"InvalidTokenType","type":"error"},{"inputs":[{"internalType":"contract IERC4626","name":"wrappedToken","type":"address"}],"name":"InvalidUnderlyingToken","type":"error"},{"inputs":[{"internalType":"uint256","name":"invariantRatio","type":"uint256"},{"internalType":"uint256","name":"maxInvariantRatio","type":"uint256"}],"name":"InvariantRatioAboveMax","type":"error"},{"inputs":[{"internalType":"uint256","name":"invariantRatio","type":"uint256"},{"internalType":"uint256","name":"minInvariantRatio","type":"uint256"}],"name":"InvariantRatioBelowMin","type":"error"},{"inputs":[{"internalType":"uint256","name":"issuedShares","type":"uint256"},{"internalType":"uint256","name":"minIssuedShares","type":"uint256"}],"name":"IssuedSharesBelowMin","type":"error"},{"inputs":[],"name":"MaxTokens","type":"error"},{"inputs":[],"name":"MinTokens","type":"error"},{"inputs":[],"name":"MultipleNonZeroInputs","type":"error"},{"inputs":[],"name":"NotEnoughBufferShares","type":"error"},{"inputs":[{"internalType":"contract IERC4626","name":"wrappedToken","type":"address"},{"internalType":"uint256","name":"expectedUnderlyingAmount","type":"uint256"},{"internalType":"uint256","name":"actualUnderlyingAmount","type":"uint256"}],"name":"NotEnoughUnderlying","type":"error"},{"inputs":[{"internalType":"contract IERC4626","name":"wrappedToken","type":"address"},{"internalType":"uint256","name":"expectedWrappedAmount","type":"uint256"},{"internalType":"uint256","name":"actualWrappedAmount","type":"uint256"}],"name":"NotEnoughWrapped","type":"error"},{"inputs":[],"name":"NotStaticCall","type":"error"},{"inputs":[],"name":"NotVaultDelegateCall","type":"error"},{"inputs":[],"name":"PauseBufferPeriodDurationTooLarge","type":"error"},{"inputs":[],"name":"PercentageAboveMax","type":"error"},{"inputs":[{"internalType":"address","name":"pool","type":"address"}],"name":"PoolAlreadyInitialized","type":"error"},{"inputs":[{"internalType":"address","name":"pool","type":"address"}],"name":"PoolAlreadyRegistered","type":"error"},{"inputs":[{"internalType":"address","name":"pool","type":"address"}],"name":"PoolInRecoveryMode","type":"error"},{"inputs":[{"internalType":"address","name":"pool","type":"address"}],"name":"PoolNotInRecoveryMode","type":"error"},{"inputs":[{"internalType":"address","name":"pool","type":"address"}],"name":"PoolNotInitialized","type":"error"},{"inputs":[{"internalType":"address","name":"pool","type":"address"}],"name":"PoolNotPaused","type":"error"},{"inputs":[{"internalType":"address","name":"pool","type":"address"}],"name":"PoolNotRegistered","type":"error"},{"inputs":[{"internalType":"address","name":"pool","type":"address"}],"name":"PoolPauseWindowExpired","type":"error"},{"inputs":[{"internalType":"address","name":"pool","type":"address"}],"name":"PoolPaused","type":"error"},{"inputs":[{"internalType":"uint256","name":"totalSupply","type":"uint256"}],"name":"PoolTotalSupplyTooLow","type":"error"},{"inputs":[],"name":"ProtocolFeesExceedTotalCollected","type":"error"},{"inputs":[],"name":"QueriesDisabled","type":"error"},{"inputs":[],"name":"QueriesDisabledPermanently","type":"error"},{"inputs":[],"name":"QuoteResultSpoofed","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[],"name":"RouterNotTrusted","type":"error"},{"inputs":[{"internalType":"int256","name":"value","type":"int256"}],"name":"SafeCastOverflowedIntToUint","type":"error"},{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"name":"SafeCastOverflowedUintToInt","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"SenderIsNotVault","type":"error"},{"inputs":[],"name":"SwapFeePercentageTooHigh","type":"error"},{"inputs":[],"name":"SwapFeePercentageTooLow","type":"error"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"limit","type":"uint256"}],"name":"SwapLimit","type":"error"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"}],"name":"TokenAlreadyRegistered","type":"error"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"}],"name":"TokenNotRegistered","type":"error"},{"inputs":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"address","name":"expectedToken","type":"address"},{"internalType":"address","name":"actualToken","type":"address"}],"name":"TokensMismatch","type":"error"},{"inputs":[],"name":"TradeAmountTooSmall","type":"error"},{"inputs":[],"name":"VaultBuffersArePaused","type":"error"},{"inputs":[],"name":"VaultIsNotUnlocked","type":"error"},{"inputs":[],"name":"VaultNotPaused","type":"error"},{"inputs":[],"name":"VaultPauseWindowDurationTooLarge","type":"error"},{"inputs":[],"name":"VaultPauseWindowExpired","type":"error"},{"inputs":[],"name":"VaultPaused","type":"error"},{"inputs":[{"internalType":"contract IERC4626","name":"wrappedToken","type":"address"}],"name":"WrapAmountTooSmall","type":"error"},{"inputs":[],"name":"WrongProtocolFeeControllerDeployment","type":"error"},{"inputs":[{"internalType":"contract IERC4626","name":"wrappedToken","type":"address"},{"internalType":"address","name":"underlyingToken","type":"address"}],"name":"WrongUnderlyingToken","type":"error"},{"inputs":[],"name":"WrongVaultAdminDeployment","type":"error"},{"inputs":[],"name":"WrongVaultExtensionDeployment","type":"error"},{"inputs":[],"name":"ZeroDivision","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pool","type":"address"},{"indexed":false,"internalType":"uint256","name":"aggregateSwapFeePercentage","type":"uint256"}],"name":"AggregateSwapFeePercentageChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pool","type":"address"},{"indexed":false,"internalType":"uint256","name":"aggregateYieldFeePercentage","type":"uint256"}],"name":"AggregateYieldFeePercentageChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pool","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IAuthorizer","name":"newAuthorizer","type":"address"}],"name":"AuthorizerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IERC4626","name":"wrappedToken","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"burnedShares","type":"uint256"}],"name":"BufferSharesBurned","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IERC4626","name":"wrappedToken","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"issuedShares","type":"uint256"}],"name":"BufferSharesMinted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pool","type":"address"},{"indexed":true,"internalType":"address","name":"liquidityProvider","type":"address"},{"indexed":true,"internalType":"enum AddLiquidityKind","name":"kind","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"totalSupply","type":"uint256"},{"indexed":false,"internalType":"uint256[]","name":"amountsAddedRaw","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"swapFeeAmountsRaw","type":"uint256[]"}],"name":"LiquidityAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IERC4626","name":"wrappedToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountUnderlying","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountWrapped","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"bufferBalances","type":"bytes32"}],"name":"LiquidityAddedToBuffer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pool","type":"address"},{"indexed":true,"internalType":"address","name":"liquidityProvider","type":"address"},{"indexed":true,"internalType":"enum RemoveLiquidityKind","name":"kind","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"totalSupply","type":"uint256"},{"indexed":false,"internalType":"uint256[]","name":"amountsRemovedRaw","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"swapFeeAmountsRaw","type":"uint256[]"}],"name":"LiquidityRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IERC4626","name":"wrappedToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountUnderlying","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountWrapped","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"bufferBalances","type":"bytes32"}],"name":"LiquidityRemovedFromBuffer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pool","type":"address"}],"name":"PoolInitialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pool","type":"address"},{"indexed":false,"internalType":"bool","name":"paused","type":"bool"}],"name":"PoolPausedStateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pool","type":"address"},{"indexed":false,"internalType":"bool","name":"recoveryMode","type":"bool"}],"name":"PoolRecoveryModeStateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pool","type":"address"},{"indexed":true,"internalType":"address","name":"factory","type":"address"},{"components":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"enum TokenType","name":"tokenType","type":"uint8"},{"internalType":"contract IRateProvider","name":"rateProvider","type":"address"},{"internalType":"bool","name":"paysYieldFees","type":"bool"}],"indexed":false,"internalType":"struct TokenConfig[]","name":"tokenConfig","type":"tuple[]"},{"indexed":false,"internalType":"uint256","name":"swapFeePercentage","type":"uint256"},{"indexed":false,"internalType":"uint32","name":"pauseWindowEndTime","type":"uint32"},{"components":[{"internalType":"address","name":"pauseManager","type":"address"},{"internalType":"address","name":"swapFeeManager","type":"address"},{"internalType":"address","name":"poolCreator","type":"address"}],"indexed":false,"internalType":"struct PoolRoleAccounts","name":"roleAccounts","type":"tuple"},{"components":[{"internalType":"bool","name":"enableHookAdjustedAmounts","type":"bool"},{"internalType":"bool","name":"shouldCallBeforeInitialize","type":"bool"},{"internalType":"bool","name":"shouldCallAfterInitialize","type":"bool"},{"internalType":"bool","name":"shouldCallComputeDynamicSwapFee","type":"bool"},{"internalType":"bool","name":"shouldCallBeforeSwap","type":"bool"},{"internalType":"bool","name":"shouldCallAfterSwap","type":"bool"},{"internalType":"bool","name":"shouldCallBeforeAddLiquidity","type":"bool"},{"internalType":"bool","name":"shouldCallAfterAddLiquidity","type":"bool"},{"internalType":"bool","name":"shouldCallBeforeRemoveLiquidity","type":"bool"},{"internalType":"bool","name":"shouldCallAfterRemoveLiquidity","type":"bool"},{"internalType":"address","name":"hooksContract","type":"address"}],"indexed":false,"internalType":"struct HooksConfig","name":"hooksConfig","type":"tuple"},{"components":[{"internalType":"bool","name":"disableUnbalancedLiquidity","type":"bool"},{"internalType":"bool","name":"enableAddLiquidityCustom","type":"bool"},{"internalType":"bool","name":"enableRemoveLiquidityCustom","type":"bool"},{"internalType":"bool","name":"enableDonation","type":"bool"}],"indexed":false,"internalType":"struct LiquidityManagement","name":"liquidityManagement","type":"tuple"}],"name":"PoolRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IProtocolFeeController","name":"newProtocolFeeController","type":"address"}],"name":"ProtocolFeeControllerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pool","type":"address"},{"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"},{"indexed":false,"internalType":"uint256","name":"swapFeePercentage","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"swapFeeAmount","type":"uint256"}],"name":"Swap","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pool","type":"address"},{"indexed":false,"internalType":"uint256","name":"swapFeePercentage","type":"uint256"}],"name":"SwapFeePercentageChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pool","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IERC4626","name":"wrappedToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"burnedShares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"withdrawnUnderlying","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"bufferBalances","type":"bytes32"}],"name":"Unwrap","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pool","type":"address"},{"indexed":true,"internalType":"bytes32","name":"eventKey","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"eventData","type":"bytes"}],"name":"VaultAuxiliary","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"paused","type":"bool"}],"name":"VaultBuffersPausedStateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"paused","type":"bool"}],"name":"VaultPausedStateChanged","type":"event"},{"anonymous":false,"inputs":[],"name":"VaultQueriesDisabled","type":"event"},{"anonymous":false,"inputs":[],"name":"VaultQueriesEnabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IERC4626","name":"wrappedToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"depositedUnderlying","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"mintedShares","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"bufferBalances","type":"bytes32"}],"name":"Wrap","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[{"components":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"maxAmountsIn","type":"uint256[]"},{"internalType":"uint256","name":"minBptAmountOut","type":"uint256"},{"internalType":"enum AddLiquidityKind","name":"kind","type":"uint8"},{"internalType":"bytes","name":"userData","type":"bytes"}],"internalType":"struct AddLiquidityParams","name":"params","type":"tuple"}],"name":"addLiquidity","outputs":[{"internalType":"uint256[]","name":"amountsIn","type":"uint256[]"},{"internalType":"uint256","name":"bptAmountOut","type":"uint256"},{"internalType":"bytes","name":"returnData","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"enum SwapKind","name":"kind","type":"uint8"},{"internalType":"enum WrappingDirection","name":"direction","type":"uint8"},{"internalType":"contract IERC4626","name":"wrappedToken","type":"address"},{"internalType":"uint256","name":"amountGivenRaw","type":"uint256"},{"internalType":"uint256","name":"limitRaw","type":"uint256"}],"internalType":"struct BufferWrapOrUnwrapParams","name":"params","type":"tuple"}],"name":"erc4626BufferWrapOrUnwrap","outputs":[{"internalType":"uint256","name":"amountCalculatedRaw","type":"uint256"},{"internalType":"uint256","name":"amountInRaw","type":"uint256"},{"internalType":"uint256","name":"amountOutRaw","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"contract IERC20","name":"token","type":"address"}],"name":"getPoolTokenCountAndIndexOfToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getVaultExtension","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"reentrancyGuardEntered","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"maxBptAmountIn","type":"uint256"},{"internalType":"uint256[]","name":"minAmountsOut","type":"uint256[]"},{"internalType":"enum RemoveLiquidityKind","name":"kind","type":"uint8"},{"internalType":"bytes","name":"userData","type":"bytes"}],"internalType":"struct RemoveLiquidityParams","name":"params","type":"tuple"}],"name":"removeLiquidity","outputs":[{"internalType":"uint256","name":"bptAmountIn","type":"uint256"},{"internalType":"uint256[]","name":"amountsOut","type":"uint256[]"},{"internalType":"bytes","name":"returnData","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"sendTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"uint256","name":"amountHint","type":"uint256"}],"name":"settle","outputs":[{"internalType":"uint256","name":"credit","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"enum SwapKind","name":"kind","type":"uint8"},{"internalType":"address","name":"pool","type":"address"},{"internalType":"contract IERC20","name":"tokenIn","type":"address"},{"internalType":"contract IERC20","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"amountGivenRaw","type":"uint256"},{"internalType":"uint256","name":"limitRaw","type":"uint256"},{"internalType":"bytes","name":"userData","type":"bytes"}],"internalType":"struct VaultSwapParams","name":"vaultSwapParams","type":"tuple"}],"name":"swap","outputs":[{"internalType":"uint256","name":"amountCalculated","type":"uint256"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"}],"name":"unlock","outputs":[{"internalType":"bytes","name":"result","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}] \ No newline at end of file diff --git a/substreams/ethereum-balancer-v3/abi/weighted_pool_contract.abi.json b/substreams/ethereum-balancer-v3/abi/weighted_pool_contract.abi.json new file mode 100644 index 0000000..d389d91 --- /dev/null +++ b/substreams/ethereum-balancer-v3/abi/weighted_pool_contract.abi.json @@ -0,0 +1 @@ +[{"inputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"uint256","name":"numTokens","type":"uint256"},{"internalType":"uint256[]","name":"normalizedWeights","type":"uint256[]"},{"internalType":"string","name":"version","type":"string"}],"internalType":"struct WeightedPool.NewPoolParams","name":"params","type":"tuple"},{"internalType":"contract IVault","name":"vault","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"BaseOutOfBounds","type":"error"},{"inputs":[],"name":"ECDSAInvalidSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"name":"ECDSAInvalidSignatureLength","type":"error"},{"inputs":[{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"ECDSAInvalidSignatureS","type":"error"},{"inputs":[{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"ERC2612ExpiredSignature","type":"error"},{"inputs":[{"internalType":"address","name":"signer","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC2612InvalidSigner","type":"error"},{"inputs":[],"name":"ExponentOutOfBounds","type":"error"},{"inputs":[],"name":"InputLengthMismatch","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"currentNonce","type":"uint256"}],"name":"InvalidAccountNonce","type":"error"},{"inputs":[],"name":"InvalidExponent","type":"error"},{"inputs":[],"name":"InvalidShortString","type":"error"},{"inputs":[],"name":"InvalidToken","type":"error"},{"inputs":[],"name":"MaxInRatio","type":"error"},{"inputs":[],"name":"MaxOutRatio","type":"error"},{"inputs":[],"name":"MinWeight","type":"error"},{"inputs":[],"name":"NormalizedWeightInvariant","type":"error"},{"inputs":[],"name":"ProductOutOfBounds","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"SenderIsNotVault","type":"error"},{"inputs":[{"internalType":"string","name":"str","type":"string"}],"name":"StringTooLong","type":"error"},{"inputs":[],"name":"WeightedPoolBptRateUnsupported","type":"error"},{"inputs":[],"name":"ZeroDivision","type":"error"},{"inputs":[],"name":"ZeroInvariant","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[],"name":"EIP712DomainChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERMIT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"balancesLiveScaled18","type":"uint256[]"},{"internalType":"uint256","name":"tokenInIndex","type":"uint256"},{"internalType":"uint256","name":"invariantRatio","type":"uint256"}],"name":"computeBalance","outputs":[{"internalType":"uint256","name":"newBalance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"balancesLiveScaled18","type":"uint256[]"},{"internalType":"enum Rounding","name":"rounding","type":"uint8"}],"name":"computeInvariant","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"eip712Domain","outputs":[{"internalType":"bytes1","name":"fields","type":"bytes1"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"verifyingContract","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256[]","name":"extensions","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"emitApproval","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"emitTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getAggregateFeePercentages","outputs":[{"internalType":"uint256","name":"aggregateSwapFeePercentage","type":"uint256"},{"internalType":"uint256","name":"aggregateYieldFeePercentage","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentLiveBalances","outputs":[{"internalType":"uint256[]","name":"balancesLiveScaled18","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMaximumInvariantRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getMaximumSwapFeePercentage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getMinimumInvariantRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getMinimumSwapFeePercentage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getNormalizedWeights","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getStaticSwapFeePercentage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTokenInfo","outputs":[{"internalType":"contract IERC20[]","name":"tokens","type":"address[]"},{"components":[{"internalType":"enum TokenType","name":"tokenType","type":"uint8"},{"internalType":"contract IRateProvider","name":"rateProvider","type":"address"},{"internalType":"bool","name":"paysYieldFees","type":"bool"}],"internalType":"struct TokenInfo[]","name":"tokenInfo","type":"tuple[]"},{"internalType":"uint256[]","name":"balancesRaw","type":"uint256[]"},{"internalType":"uint256[]","name":"lastBalancesLiveScaled18","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTokens","outputs":[{"internalType":"contract IERC20[]","name":"tokens","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getVault","outputs":[{"internalType":"contract IVault","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWeightedPoolDynamicData","outputs":[{"components":[{"internalType":"uint256[]","name":"balancesLiveScaled18","type":"uint256[]"},{"internalType":"uint256[]","name":"tokenRates","type":"uint256[]"},{"internalType":"uint256","name":"staticSwapFeePercentage","type":"uint256"},{"internalType":"uint256","name":"totalSupply","type":"uint256"},{"internalType":"bool","name":"isPoolInitialized","type":"bool"},{"internalType":"bool","name":"isPoolPaused","type":"bool"},{"internalType":"bool","name":"isPoolInRecoveryMode","type":"bool"}],"internalType":"struct WeightedPoolDynamicData","name":"data","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWeightedPoolImmutableData","outputs":[{"components":[{"internalType":"contract IERC20[]","name":"tokens","type":"address[]"},{"internalType":"uint256[]","name":"decimalScalingFactors","type":"uint256[]"},{"internalType":"uint256[]","name":"normalizedWeights","type":"uint256[]"}],"internalType":"struct WeightedPoolImmutableData","name":"data","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"incrementNonce","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"enum SwapKind","name":"kind","type":"uint8"},{"internalType":"uint256","name":"amountGivenScaled18","type":"uint256"},{"internalType":"uint256[]","name":"balancesScaled18","type":"uint256[]"},{"internalType":"uint256","name":"indexIn","type":"uint256"},{"internalType":"uint256","name":"indexOut","type":"uint256"},{"internalType":"address","name":"router","type":"address"},{"internalType":"bytes","name":"userData","type":"bytes"}],"internalType":"struct PoolSwapParams","name":"request","type":"tuple"}],"name":"onSwap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","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-v3/abi/weighted_pool_factory_contract.abi.json b/substreams/ethereum-balancer-v3/abi/weighted_pool_factory_contract.abi.json new file mode 100644 index 0000000..d2b849a --- /dev/null +++ b/substreams/ethereum-balancer-v3/abi/weighted_pool_factory_contract.abi.json @@ -0,0 +1 @@ +[{"inputs":[{"internalType":"contract IVault","name":"vault","type":"address"},{"internalType":"uint32","name":"pauseWindowDuration","type":"uint32"},{"internalType":"string","name":"factoryVersion","type":"string"},{"internalType":"string","name":"poolVersion","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"Create2EmptyBytecode","type":"error"},{"inputs":[],"name":"Create2FailedDeployment","type":"error"},{"inputs":[{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"Create2InsufficientBalance","type":"error"},{"inputs":[],"name":"Disabled","type":"error"},{"inputs":[],"name":"IndexOutOfBounds","type":"error"},{"inputs":[],"name":"PoolPauseWindowDurationOverflow","type":"error"},{"inputs":[],"name":"SenderNotAllowed","type":"error"},{"inputs":[],"name":"StandardPoolWithCreator","type":"error"},{"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"},{"components":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"enum TokenType","name":"tokenType","type":"uint8"},{"internalType":"contract IRateProvider","name":"rateProvider","type":"address"},{"internalType":"bool","name":"paysYieldFees","type":"bool"}],"internalType":"struct TokenConfig[]","name":"tokens","type":"tuple[]"},{"internalType":"uint256[]","name":"normalizedWeights","type":"uint256[]"},{"components":[{"internalType":"address","name":"pauseManager","type":"address"},{"internalType":"address","name":"swapFeeManager","type":"address"},{"internalType":"address","name":"poolCreator","type":"address"}],"internalType":"struct PoolRoleAccounts","name":"roleAccounts","type":"tuple"},{"internalType":"uint256","name":"swapFeePercentage","type":"uint256"},{"internalType":"address","name":"poolHooksContract","type":"address"},{"internalType":"bool","name":"enableDonation","type":"bool"},{"internalType":"bool","name":"disableUnbalancedLiquidity","type":"bool"},{"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":"getDefaultLiquidityManagement","outputs":[{"components":[{"internalType":"bool","name":"disableUnbalancedLiquidity","type":"bool"},{"internalType":"bool","name":"enableAddLiquidityCustom","type":"bool"},{"internalType":"bool","name":"enableRemoveLiquidityCustom","type":"bool"},{"internalType":"bool","name":"enableDonation","type":"bool"}],"internalType":"struct LiquidityManagement","name":"liquidityManagement","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getDefaultPoolHooksContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"constructorArgs","type":"bytes"},{"internalType":"bytes32","name":"salt","type":"bytes32"}],"name":"getDeploymentAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNewPoolPauseWindowEndTime","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOriginalPauseWindowEndTime","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPauseWindowDuration","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPoolCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPoolVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPools","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint256","name":"count","type":"uint256"}],"name":"getPoolsInRange","outputs":[{"internalType":"address[]","name":"pools","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-v3/buf.gen.yaml b/substreams/ethereum-balancer-v3/buf.gen.yaml new file mode 100644 index 0000000..6a1c3ef --- /dev/null +++ b/substreams/ethereum-balancer-v3/buf.gen.yaml @@ -0,0 +1,11 @@ +version: v1 +plugins: +- plugin: buf.build/community/neoeinstein-prost:v0.4.0 + out: src/pb + opt: + - file_descriptor_set=false + +- plugin: buf.build/community/neoeinstein-prost-crate:v0.4.1 + out: src/pb + opt: + - no_features diff --git a/substreams/ethereum-balancer-v3/build.rs b/substreams/ethereum-balancer-v3/build.rs new file mode 100644 index 0000000..1a104a8 --- /dev/null +++ b/substreams/ethereum-balancer-v3/build.rs @@ -0,0 +1,50 @@ +#![allow(clippy::all)] + +use anyhow::{Ok, Result}; +use regex::Regex; +use std::fs; +use substreams_ethereum::Abigen; + +fn main() -> Result<(), anyhow::Error> { + let file_names = [ + "abi/vault_contract.abi.json", + "abi/stable_pool_factory_contract.abi.json", + "abi/weighted_pool_factory_contract.abi.json", + "abi/stable_pool_contract.abi.json", + "abi/weighted_pool_contract.abi.json", + ]; + let file_output_names = [ + "src/abi/vault_contract.rs", + "src/abi/stable_pool_factory_contract.rs", + "src/abi/weighted_pool_factory_contract.rs", + "src/abi/stable_pool_contract.rs", + "src/abi/weighted_pool_contract.rs", + ]; + + let mut i = 0; + for f in file_names { + let contents = fs::read_to_string(f).expect("Should have been able to read the file"); + + // sanitize fields and attributes starting with an underscore + let regex = Regex::new(r#"("\w+"\s?:\s?")_(\w+")"#).unwrap(); + let sanitized_abi_file = regex.replace_all(contents.as_str(), "${1}u_${2}"); + + // sanitize fields and attributes with multiple consecutive underscores + let re = Regex::new(r"_+").unwrap(); + + let re_sanitized_abi_file = + re.replace_all(&sanitized_abi_file, |caps: ®ex::Captures| { + let count = caps[0].len(); + let replacement = format!("{}_", "_u".repeat(count - 1)); + replacement + }); + + Abigen::from_bytes("Contract", re_sanitized_abi_file.as_bytes())? + .generate()? + .write_to_file(file_output_names[i])?; + + i = i + 1; + } + + Ok(()) +} diff --git a/substreams/ethereum-balancer-v3/integration_test.tycho.yaml b/substreams/ethereum-balancer-v3/integration_test.tycho.yaml new file mode 100644 index 0000000..2d64bb4 --- /dev/null +++ b/substreams/ethereum-balancer-v3/integration_test.tycho.yaml @@ -0,0 +1,110 @@ +substreams_yaml_path: ./substreams.yaml +protocol_type_names: + - "balancer_v3_pool" +adapter_contract: "BalancerV3SwapAdapter" +adapter_build_signature: "constructor(address,address,address,address)" +adapter_build_args: "0xbA1333333333a1BA1108E8412f11850A5C319bA9,0x136f1EFcC3f8f88516B9E94110D56FDBfB1778d1,0x000000000022D473030F116dDEE9F6B43aC78BA3,0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" +skip_balance_check: true # Skipped because this Balancer V3 uses a Vault, the current version of the testing module doesn't support this. + +# vault address for v3 needed for the router contract +initialized_accounts: + - "0xbA1333333333a1BA1108E8412f11850A5C319bA9" + +tests: + - name: test_stable_pool + start_block: 21374757 + stop_block: 21374777 + expected_components: + - id: "0xc4ce391d82d164c166df9c8336ddf84206b2f812" + tokens: + - "0x0FE906e030a44eF24CA8c7dC7B7c53A6C4F00ce9" + - "0x775F661b0bD1739349b9A2A3EF60be277c5d2D29" + static_attributes: + manual_updates: "0x01" + pool_type: "0x537461626c65506f6f6c466163746f7279" + bpt: "0xc4ce391d82d164c166df9c8336ddf84206b2f812" + fee: "0x5af3107a4000" + rate_providers: "0x5b22307866346235643163323266333561343630623931656464376633336365666536313965326661616634222c22307863646161363863653332323732386665343138356136306631303363313934663165326334376263225d" + skip_simulation: false + creation_tx: "0xecfe638ea155e78ca2698bea0bee5f86c2f77abe3e9dc93ed19ab6e674165b95" + + - name: test_weighted_pool_creation + start_block: 21701410 + stop_block: 21701420 + expected_components: + - id: "0x4Fd081923824D6AbdaCc862d8449e124A8634b12" + tokens: + - "0x249ca82617ec3dfb2589c4c17ab7ec9765350a18" + - "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2" + static_attributes: + manual_updates: "0x01" + normalized_weights: "0x5b22307830623161326263326563353030303030222c22307830326336386166306262313430303030225d" + fee: "0x038d7ea4c68000" + pool_type: "0x5765696768746564506f6f6c466163746f7279" + skip_simulation: true # This test is only for creation, simulation tests are below + creation_tx: "0xaf0f8da4b7b148f156605673c6ac56657f67c47001aadd5b3b64d6cb787daad4" + + - name: test_erc4626_pool_creation # stable pool + start_block: 21375196 + stop_block: 21375216 + expected_components: + - id: "0x89BB794097234E5E930446C0CeC0ea66b35D7570" + tokens: + - "0x7bc3485026ac48b6cf9baf0a377477fff5703af8" + - "0xd4fa2d31b7968e448877f69a96de69f5de8cd23e" + static_attributes: + manual_updates: "0x01" + pool_type: "0x537461626c65506f6f6c466163746f7279" + bpt: "0x89bb794097234e5e930446c0cec0ea66b35d7570" + fee: "0x2d79883d2000" + rate_providers: "0x5b22307865646636336363653462613730636265373430363462373638373838326537316562623065393838222c22307838663465383433396239373033363336343834323163363932646438393766623963306264316439225d" + skip_simulation: false + creation_tx: "0x536baa8f18a5f9e32b08f695593f47d996a509edc886ccab6f89b001f2d2b4e4" + + - name: test_swap_g_usdc # weighted pool + start_block: 21389576 + stop_block: 21389676 + expected_components: + - id: "0xf91c11BA4220b7a72E1dc5E92f2b48D3fdF62726" + tokens: + - "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" + - "0x440017A1b021006d556d7fc06A54c32E42Eb745B" + static_attributes: + pool_type: "0x5765696768746564506f6f6c466163746f7279" + manual_updates: "0x01" + normalized_weights: "0x5b22307830366630356235396433623230303030222c22307830366630356235396433623230303030225d" + fee: "0x0aa87bee538000" + skip_simulation: false + creation_tx: "0x50a58ca41af90029a67bc7f4305cceb1e85800246f9c559fa74d8625ddfe14ed" + + - name: test_obs_weth # weighted pool + start_block: 21420490 + stop_block: 21420516 + expected_components: + - id: "0x4403a2721A9A9956584dc19F553720CEf0Df35b0" + tokens: + - "0xafd9268fdfebee905f7439b12c943bc18ad293c2" + - "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2" + static_attributes: + pool_type: "0x5765696768746564506f6f6c466163746f7279" + manual_updates: "0x01" + normalized_weights: "0x5b22307830646264326663313337613330303030222c2230783233383666323666633130303030225d" + fee: "0x038d7ea4c68000" + skip_simulation: false + creation_tx: "0x8540c2bfbc16dc2db44bc96dd32c2901eb2080d27f959b5831d96cd99903523e" + + - name: test_tbc_verse + start_block: 21722567 + stop_block: 21722950 + expected_components: + - id: "0x82074b99f3E927658BcAFd81F9948d89192CDF91" + tokens: + - "0x18084fba666a33d37592fa2633fd49a74dd93a88" + - "0x249ca82617ec3dfb2589c4c17ab7ec9765350a18" + static_attributes: + pool_type: "0x5765696768746564506f6f6c466163746f7279" + manual_updates: "0x01" + normalized_weights: "0x5b22307830326336386166306262313430303030222c22307830623161326263326563353030303030225d" + fee: "0x038d7ea4c68000" + skip_simulation: false + creation_tx: "0x214064cfcf41f7b94b4f9cdd35644b851e19ba246822b7d8f2bdcc3d6c06074e" diff --git a/substreams/ethereum-balancer-v3/src/abi/mod.rs b/substreams/ethereum-balancer-v3/src/abi/mod.rs new file mode 100644 index 0000000..da8b0ab --- /dev/null +++ b/substreams/ethereum-balancer-v3/src/abi/mod.rs @@ -0,0 +1,7 @@ +#![allow(clippy::all)] + +pub mod stable_pool_contract; +pub mod stable_pool_factory_contract; +pub mod vault_contract; +pub mod weighted_pool_contract; +pub mod weighted_pool_factory_contract; diff --git a/substreams/ethereum-balancer-v3/src/abi/stable_pool_contract.rs b/substreams/ethereum-balancer-v3/src/abi/stable_pool_contract.rs new file mode 100644 index 0000000..053a247 --- /dev/null +++ b/substreams/ethereum-balancer-v3/src/abi/stable_pool_contract.rs @@ -0,0 +1,5241 @@ +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 Allowance { + pub owner: Vec, + pub spender: Vec, + } + impl Allowance { + const METHOD_ID: [u8; 4] = [221u8, 98u8, 237u8, 62u8]; + 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 { + owner: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + spender: 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.owner)), + ethabi::Token::Address(ethabi::Address::from_slice(&self.spender)), + ], + ); + 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 Allowance { + const NAME: &'static str = "allowance"; + 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 Allowance { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct Approve { + pub spender: Vec, + pub amount: substreams::scalar::BigInt, + } + impl Approve { + const METHOD_ID: [u8; 4] = [9u8, 94u8, 167u8, 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::Address, ethabi::ParamType::Uint(256usize)], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + spender: 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) + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::Address(ethabi::Address::from_slice(&self.spender)), + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.amount.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::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 Approve { + const NAME: &'static str = "approve"; + 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 Approve { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct BalanceOf { + pub account: Vec, + } + impl BalanceOf { + const METHOD_ID: [u8; 4] = [112u8, 160u8, 130u8, 49u8]; + 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 { + account: 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.account))], + ); + 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 BalanceOf { + const NAME: &'static str = "balanceOf"; + 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 BalanceOf { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct ComputeBalance { + pub balances_live_scaled18: Vec, + pub token_in_index: substreams::scalar::BigInt, + pub invariant_ratio: substreams::scalar::BigInt, + } + impl ComputeBalance { + const METHOD_ID: [u8; 4] = [22u8, 160u8, 179u8, 224u8]; + 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::Uint(256usize)), + ), + 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 { + balances_live_scaled18: 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(), + token_in_index: { + 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) + }, + invariant_ratio: { + 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( + &[ + { + let v = self + .balances_live_scaled18 + .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.token_in_index.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.invariant_ratio.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 ComputeBalance { + const NAME: &'static str = "computeBalance"; + 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 ComputeBalance { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct ComputeInvariant { + pub balances_live_scaled18: Vec, + pub rounding: substreams::scalar::BigInt, + } + impl ComputeInvariant { + const METHOD_ID: [u8; 4] = [152u8, 77u8, 233u8, 232u8]; + 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::Uint(256usize)), + ), + ethabi::ParamType::Uint(8usize), + ], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + balances_live_scaled18: 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(), + rounding: { + 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( + &[ + { + let v = self + .balances_live_scaled18 + .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.rounding.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 ComputeInvariant { + const NAME: &'static str = "computeInvariant"; + 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 ComputeInvariant { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct Decimals {} + impl Decimals { + const METHOD_ID: [u8; 4] = [49u8, 60u8, 229u8, 103u8]; + 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::Uint(8usize)], + 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 Decimals { + const NAME: &'static str = "decimals"; + 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 Decimals { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct DomainSeparator {} + impl DomainSeparator { + const METHOD_ID: [u8; 4] = [54u8, 68u8, 229u8, 21u8]; + 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 DomainSeparator { + const NAME: &'static str = "DOMAIN_SEPARATOR"; + 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 DomainSeparator { + fn output(data: &[u8]) -> Result<[u8; 32usize], String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct Eip712Domain {} + impl Eip712Domain { + const METHOD_ID: [u8; 4] = [132u8, 176u8, 25u8, 110u8]; + 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; 1usize], + String, + String, + substreams::scalar::BigInt, + Vec, + [u8; 32usize], + Vec, + ), + String, + > { + Self::output(call.return_data.as_ref()) + } + pub fn output( + data: &[u8], + ) -> Result< + ( + [u8; 1usize], + String, + String, + substreams::scalar::BigInt, + Vec, + [u8; 32usize], + Vec, + ), + String, + > { + let mut values = ethabi::decode( + &[ + ethabi::ParamType::FixedBytes(1usize), + ethabi::ParamType::String, + ethabi::ParamType::String, + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Address, + ethabi::ParamType::FixedBytes(32usize), + ethabi::ParamType::Array( + Box::new(ethabi::ParamType::Uint(256usize)), + ), + ], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + values.reverse(); + Ok(( + { + let mut result = [0u8; 1]; + let v = values + .pop() + .expect(INTERNAL_ERR) + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }, + values.pop().expect(INTERNAL_ERR).into_string().expect(INTERNAL_ERR), + values.pop().expect(INTERNAL_ERR).into_string().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) + }, + values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + { + let mut result = [0u8; 32]; + let v = values + .pop() + .expect(INTERNAL_ERR) + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }, + 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(), + )) + } + 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; 1usize], + String, + String, + substreams::scalar::BigInt, + Vec, + [u8; 32usize], + 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 Eip712Domain { + const NAME: &'static str = "eip712Domain"; + 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; 1usize], + String, + String, + substreams::scalar::BigInt, + Vec, + [u8; 32usize], + Vec, + ), + > for Eip712Domain { + fn output( + data: &[u8], + ) -> Result< + ( + [u8; 1usize], + String, + String, + substreams::scalar::BigInt, + Vec, + [u8; 32usize], + Vec, + ), + String, + > { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct EmitApproval { + pub owner: Vec, + pub spender: Vec, + pub amount: substreams::scalar::BigInt, + } + impl EmitApproval { + const METHOD_ID: [u8; 4] = [86u8, 135u8, 242u8, 184u8]; + 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::Uint(256usize), + ], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + owner: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + spender: 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) + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::Address(ethabi::Address::from_slice(&self.owner)), + ethabi::Token::Address(ethabi::Address::from_slice(&self.spender)), + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.amount.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 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 EmitApproval { + const NAME: &'static str = "emitApproval"; + 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 EmitTransfer { + pub from: Vec, + pub to: Vec, + pub amount: substreams::scalar::BigInt, + } + impl EmitTransfer { + const METHOD_ID: [u8; 4] = [35u8, 222u8, 102u8, 81u8]; + 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::Uint(256usize), + ], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + from: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + to: 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) + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::Address(ethabi::Address::from_slice(&self.from)), + ethabi::Token::Address(ethabi::Address::from_slice(&self.to)), + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.amount.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 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 EmitTransfer { + const NAME: &'static str = "emitTransfer"; + 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 GetAggregateFeePercentages {} + impl GetAggregateFeePercentages { + const METHOD_ID: [u8; 4] = [129u8, 250u8, 128u8, 124u8]; + 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 GetAggregateFeePercentages { + const NAME: &'static str = "getAggregateFeePercentages"; + 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 GetAggregateFeePercentages { + fn output( + data: &[u8], + ) -> Result<(substreams::scalar::BigInt, substreams::scalar::BigInt), String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetAmplificationParameter {} + impl GetAmplificationParameter { + const METHOD_ID: [u8; 4] = [109u8, 172u8, 207u8, 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< + (substreams::scalar::BigInt, bool, substreams::scalar::BigInt), + String, + > { + Self::output(call.return_data.as_ref()) + } + pub fn output( + data: &[u8], + ) -> Result< + (substreams::scalar::BigInt, bool, substreams::scalar::BigInt), + String, + > { + let mut values = ethabi::decode( + &[ + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Bool, + 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) + }, + 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) + }, + )) + } + 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, bool, 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 GetAmplificationParameter { + const NAME: &'static str = "getAmplificationParameter"; + 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, bool, substreams::scalar::BigInt), + > for GetAmplificationParameter { + fn output( + data: &[u8], + ) -> Result< + (substreams::scalar::BigInt, bool, substreams::scalar::BigInt), + String, + > { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetAmplificationState {} + impl GetAmplificationState { + const METHOD_ID: [u8; 4] = [33u8, 218u8, 94u8, 25u8]; + 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, + substreams::scalar::BigInt, + 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, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + ), + substreams::scalar::BigInt, + ), + String, + > { + let mut values = ethabi::decode( + &[ + ethabi::ParamType::Tuple( + vec![ + ethabi::ParamType::Uint(64usize), + ethabi::ParamType::Uint(64usize), + ethabi::ParamType::Uint(32usize), + ethabi::ParamType::Uint(32usize) + ], + ), + ethabi::ParamType::Uint(256usize), + ], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + values.reverse(); + Ok(( + { + let tuple_elements = values + .pop() + .expect(INTERNAL_ERR) + .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 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) + }, + ) + }, + { + 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, + substreams::scalar::BigInt, + 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 GetAmplificationState { + const NAME: &'static str = "getAmplificationState"; + 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, + substreams::scalar::BigInt, + ), + substreams::scalar::BigInt, + ), + > for GetAmplificationState { + fn output( + data: &[u8], + ) -> Result< + ( + ( + substreams::scalar::BigInt, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + ), + substreams::scalar::BigInt, + ), + String, + > { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetCurrentLiveBalances {} + impl GetCurrentLiveBalances { + const METHOD_ID: [u8; 4] = [177u8, 86u8, 170u8, 10u8]; + 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::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 GetCurrentLiveBalances { + const NAME: &'static str = "getCurrentLiveBalances"; + 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 GetCurrentLiveBalances { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetMaximumInvariantRatio {} + impl GetMaximumInvariantRatio { + const METHOD_ID: [u8; 4] = [39u8, 60u8, 26u8, 223u8]; + 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::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 GetMaximumInvariantRatio { + const NAME: &'static str = "getMaximumInvariantRatio"; + 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 GetMaximumInvariantRatio { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetMaximumSwapFeePercentage {} + impl GetMaximumSwapFeePercentage { + const METHOD_ID: [u8; 4] = [101u8, 76u8, 241u8, 93u8]; + 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::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 GetMaximumSwapFeePercentage { + const NAME: &'static str = "getMaximumSwapFeePercentage"; + 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 GetMaximumSwapFeePercentage { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetMinimumInvariantRatio {} + impl GetMinimumInvariantRatio { + const METHOD_ID: [u8; 4] = [182u8, 119u8, 250u8, 86u8]; + 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::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 GetMinimumInvariantRatio { + const NAME: &'static str = "getMinimumInvariantRatio"; + 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 GetMinimumInvariantRatio { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetMinimumSwapFeePercentage {} + impl GetMinimumSwapFeePercentage { + const METHOD_ID: [u8; 4] = [206u8, 32u8, 236u8, 231u8]; + 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::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 GetMinimumSwapFeePercentage { + const NAME: &'static str = "getMinimumSwapFeePercentage"; + 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 GetMinimumSwapFeePercentage { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetRate {} + impl GetRate { + const METHOD_ID: [u8; 4] = [103u8, 154u8, 239u8, 206u8]; + 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::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 GetRate { + const NAME: &'static str = "getRate"; + 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 GetRate { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetStablePoolDynamicData {} + impl GetStablePoolDynamicData { + const METHOD_ID: [u8; 4] = [203u8, 212u8, 226u8, 128u8]; + 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, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + bool, + bool, + bool, + bool, + ), + String, + > { + Self::output(call.return_data.as_ref()) + } + pub fn output( + data: &[u8], + ) -> Result< + ( + Vec, + Vec, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + bool, + bool, + bool, + bool, + ), + String, + > { + let mut values = ethabi::decode( + &[ + ethabi::ParamType::Tuple( + vec![ + ethabi::ParamType::Array(Box::new(ethabi::ParamType::Uint(256usize))), + ethabi::ParamType::Array(Box::new(ethabi::ParamType::Uint(256usize))), + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(32usize), + ethabi::ParamType::Uint(32usize), ethabi::ParamType::Bool, + ethabi::ParamType::Bool, ethabi::ParamType::Bool, + ethabi::ParamType::Bool + ], + ), + ], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok({ + let tuple_elements = values + .pop() + .expect("one output data should have existed") + .into_tuple() + .expect(INTERNAL_ERR); + ( + tuple_elements[0usize] + .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[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) + }, + { + 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) + }, + { + 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) + }, + { + 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) + }, + { + let mut v = [0 as u8; 32]; + tuple_elements[7usize] + .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[8usize] + .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[9usize] + .clone() + .into_uint() + .expect(INTERNAL_ERR) + .to_big_endian(v.as_mut_slice()); + substreams::scalar::BigInt::from_unsigned_bytes_be(&v) + }, + tuple_elements[10usize].clone().into_bool().expect(INTERNAL_ERR), + tuple_elements[11usize].clone().into_bool().expect(INTERNAL_ERR), + tuple_elements[12usize].clone().into_bool().expect(INTERNAL_ERR), + tuple_elements[13usize].clone().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< + ( + Vec, + Vec, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + bool, + bool, + bool, + bool, + ), + > { + 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 GetStablePoolDynamicData { + const NAME: &'static str = "getStablePoolDynamicData"; + 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, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + bool, + bool, + bool, + bool, + ), + > for GetStablePoolDynamicData { + fn output( + data: &[u8], + ) -> Result< + ( + Vec, + Vec, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + bool, + bool, + bool, + bool, + ), + String, + > { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetStablePoolImmutableData {} + impl GetStablePoolImmutableData { + const METHOD_ID: [u8; 4] = [92u8, 30u8, 98u8, 89u8]; + 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, 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::Tuple( + vec![ + 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))?; + Ok({ + let tuple_elements = values + .pop() + .expect("one output data should have existed") + .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) + }, + ) + }) + } + 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 GetStablePoolImmutableData { + const NAME: &'static str = "getStablePoolImmutableData"; + 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 GetStablePoolImmutableData { + fn output( + data: &[u8], + ) -> Result< + (Vec>, Vec, substreams::scalar::BigInt), + String, + > { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetStaticSwapFeePercentage {} + impl GetStaticSwapFeePercentage { + const METHOD_ID: [u8; 4] = [211u8, 53u8, 176u8, 207u8]; + 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::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 GetStaticSwapFeePercentage { + const NAME: &'static str = "getStaticSwapFeePercentage"; + 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 GetStaticSwapFeePercentage { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetTokenInfo {} + impl GetTokenInfo { + const METHOD_ID: [u8; 4] = [171u8, 177u8, 220u8, 68u8]; + 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<(substreams::scalar::BigInt, Vec, bool)>, + Vec, + Vec, + ), + String, + > { + Self::output(call.return_data.as_ref()) + } + pub fn output( + data: &[u8], + ) -> Result< + ( + Vec>, + Vec<(substreams::scalar::BigInt, Vec, bool)>, + Vec, + Vec, + ), + String, + > { + let mut values = ethabi::decode( + &[ + ethabi::ParamType::Array(Box::new(ethabi::ParamType::Address)), + ethabi::ParamType::Array( + Box::new( + ethabi::ParamType::Tuple( + vec![ + ethabi::ParamType::Uint(8usize), ethabi::ParamType::Address, + ethabi::ParamType::Bool + ], + ), + ), + ), + ethabi::ParamType::Array( + Box::new(ethabi::ParamType::Uint(256usize)), + ), + ethabi::ParamType::Array( + Box::new(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 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(), + tuple_elements[2usize] + .clone() + .into_bool() + .expect(INTERNAL_ERR), + ) + }) + .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(), + 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(), + )) + } + 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, Vec, bool)>, + 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 GetTokenInfo { + const NAME: &'static str = "getTokenInfo"; + 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, Vec, bool)>, + Vec, + Vec, + ), + > for GetTokenInfo { + fn output( + data: &[u8], + ) -> Result< + ( + Vec>, + Vec<(substreams::scalar::BigInt, Vec, bool)>, + Vec, + Vec, + ), + String, + > { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetTokens {} + impl GetTokens { + const METHOD_ID: [u8; 4] = [170u8, 108u8, 168u8, 8u8]; + 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::Array(Box::new(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_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + inner.into_address().expect(INTERNAL_ERR).as_bytes().to_vec() + }) + .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 GetTokens { + const NAME: &'static str = "getTokens"; + 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 GetTokens { + 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 IncrementNonce {} + impl IncrementNonce { + const METHOD_ID: [u8; 4] = [98u8, 124u8, 220u8, 185u8]; + 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 IncrementNonce { + const NAME: &'static str = "incrementNonce"; + 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 Name {} + impl Name { + const METHOD_ID: [u8; 4] = [6u8, 253u8, 222u8, 3u8]; + 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 Name { + const NAME: &'static str = "name"; + 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 Name { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct Nonces { + pub owner: Vec, + } + impl Nonces { + const METHOD_ID: [u8; 4] = [126u8, 206u8, 190u8, 0u8]; + 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 { + 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::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 { + 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 Nonces { + const NAME: &'static str = "nonces"; + 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 Nonces { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct OnSwap { + pub request: ( + substreams::scalar::BigInt, + substreams::scalar::BigInt, + Vec, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + Vec, + Vec, + ), + } + impl OnSwap { + const METHOD_ID: [u8; 4] = [114u8, 201u8, 129u8, 134u8]; + 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::Uint(8usize), + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Array(Box::new(ethabi::ParamType::Uint(256usize))), + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Address, ethabi::ParamType::Bytes + ], + ), + ], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + request: { + let tuple_elements = values + .pop() + .expect(INTERNAL_ERR) + .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 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_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[3usize] + .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[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_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + tuple_elements[6usize].clone().into_bytes().expect(INTERNAL_ERR), + ) + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::Tuple( + vec![ + ethabi::Token::Uint(ethabi::Uint::from_big_endian(match self + .request.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::Uint(ethabi::Uint::from_big_endian(match self + .request.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(),),), { let v = self.request.2.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 + .request.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::Uint(ethabi::Uint::from_big_endian(match self + .request.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::Address(ethabi::Address::from_slice(& self + .request.5)), ethabi::Token::Bytes(self.request.6.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 { + 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 OnSwap { + const NAME: &'static str = "onSwap"; + 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 OnSwap { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct Permit { + pub owner: Vec, + pub spender: Vec, + pub amount: substreams::scalar::BigInt, + pub deadline: substreams::scalar::BigInt, + pub v: substreams::scalar::BigInt, + pub r: [u8; 32usize], + pub s: [u8; 32usize], + } + impl Permit { + const METHOD_ID: [u8; 4] = [213u8, 5u8, 172u8, 207u8]; + 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::Uint(256usize), + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(8usize), + ethabi::ParamType::FixedBytes(32usize), + ethabi::ParamType::FixedBytes(32usize), + ], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + owner: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + spender: 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) + }, + 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) + }, + 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) + }, + r: { + let mut result = [0u8; 32]; + let v = values + .pop() + .expect(INTERNAL_ERR) + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }, + s: { + 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::Address(ethabi::Address::from_slice(&self.owner)), + ethabi::Token::Address(ethabi::Address::from_slice(&self.spender)), + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.amount.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(), + ), + ), + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.v.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.r.as_ref().to_vec()), + ethabi::Token::FixedBytes(self.s.as_ref().to_vec()), + ], + ); + 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 Permit { + const NAME: &'static str = "permit"; + 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 PermitTypehash {} + impl PermitTypehash { + const METHOD_ID: [u8; 4] = [48u8, 173u8, 248u8, 31u8]; + 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 PermitTypehash { + const NAME: &'static str = "PERMIT_TYPEHASH"; + 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 PermitTypehash { + fn output(data: &[u8]) -> Result<[u8; 32usize], String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct StartAmplificationParameterUpdate { + pub raw_end_value: substreams::scalar::BigInt, + pub end_time: substreams::scalar::BigInt, + } + impl StartAmplificationParameterUpdate { + const METHOD_ID: [u8; 4] = [47u8, 26u8, 11u8, 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(256usize), + ethabi::ParamType::Uint(256usize), + ], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + raw_end_value: { + 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) + }, + end_time: { + 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.raw_end_value.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.end_time.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 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 StartAmplificationParameterUpdate { + const NAME: &'static str = "startAmplificationParameterUpdate"; + 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 StopAmplificationParameterUpdate {} + impl StopAmplificationParameterUpdate { + const METHOD_ID: [u8; 4] = [235u8, 15u8, 36u8, 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 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 StopAmplificationParameterUpdate { + const NAME: &'static str = "stopAmplificationParameterUpdate"; + 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 SupportsInterface { + pub interface_id: [u8; 4usize], + } + impl SupportsInterface { + const METHOD_ID: [u8; 4] = [1u8, 255u8, 201u8, 167u8]; + 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 { + interface_id: { + 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.interface_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 { + 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 SupportsInterface { + const NAME: &'static str = "supportsInterface"; + 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 SupportsInterface { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct Symbol {} + impl Symbol { + const METHOD_ID: [u8; 4] = [149u8, 216u8, 155u8, 65u8]; + 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 Symbol { + const NAME: &'static str = "symbol"; + 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 Symbol { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct TotalSupply {} + impl TotalSupply { + const METHOD_ID: [u8; 4] = [24u8, 22u8, 13u8, 221u8]; + 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::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 TotalSupply { + const NAME: &'static str = "totalSupply"; + 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 TotalSupply { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct Transfer { + pub to: Vec, + pub amount: substreams::scalar::BigInt, + } + impl Transfer { + const METHOD_ID: [u8; 4] = [169u8, 5u8, 156u8, 187u8]; + 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::Uint(256usize)], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + to: 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) + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::Address(ethabi::Address::from_slice(&self.to)), + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.amount.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::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 Transfer { + const NAME: &'static str = "transfer"; + 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 Transfer { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct TransferFrom { + pub from: Vec, + pub to: Vec, + pub amount: substreams::scalar::BigInt, + } + impl TransferFrom { + const METHOD_ID: [u8; 4] = [35u8, 184u8, 114u8, 221u8]; + 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::Uint(256usize), + ], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + from: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + to: 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) + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::Address(ethabi::Address::from_slice(&self.from)), + ethabi::Token::Address(ethabi::Address::from_slice(&self.to)), + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.amount.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::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 TransferFrom { + const NAME: &'static str = "transferFrom"; + 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 TransferFrom { + 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 AmpUpdateStarted { + pub start_value: substreams::scalar::BigInt, + pub end_value: substreams::scalar::BigInt, + pub start_time: substreams::scalar::BigInt, + pub end_time: substreams::scalar::BigInt, + } + impl AmpUpdateStarted { + const TOPIC_ID: [u8; 32] = [ + 24u8, + 53u8, + 136u8, + 46u8, + 231u8, + 163u8, + 74u8, + 193u8, + 148u8, + 247u8, + 23u8, + 163u8, + 94u8, + 9u8, + 187u8, + 29u8, + 36u8, + 200u8, + 42u8, + 59u8, + 157u8, + 133u8, + 74u8, + 182u8, + 201u8, + 116u8, + 149u8, + 37u8, + 183u8, + 20u8, + 205u8, + 242u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 1usize { + 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::Uint(256usize), + ethabi::ParamType::Uint(256usize), + 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 { + start_value: { + 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) + }, + end_value: { + 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) + }, + start_time: { + 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) + }, + end_time: { + 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 AmpUpdateStarted { + const NAME: &'static str = "AmpUpdateStarted"; + 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 AmpUpdateStopped { + pub current_value: substreams::scalar::BigInt, + } + impl AmpUpdateStopped { + const TOPIC_ID: [u8; 32] = [ + 160u8, + 208u8, + 21u8, + 147u8, + 228u8, + 126u8, + 105u8, + 208u8, + 126u8, + 12u8, + 205u8, + 135u8, + 190u8, + 206u8, + 9u8, + 65u8, + 30u8, + 7u8, + 221u8, + 30u8, + 212u8, + 12u8, + 168u8, + 242u8, + 231u8, + 175u8, + 41u8, + 118u8, + 84u8, + 42u8, + 2u8, + 51u8, + ]; + 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::Uint(256usize)], + log.data.as_ref(), + ) + .map_err(|e| format!("unable to decode log.data: {:?}", e))?; + values.reverse(); + Ok(Self { + current_value: { + 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 AmpUpdateStopped { + const NAME: &'static str = "AmpUpdateStopped"; + 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 Approval { + pub owner: Vec, + pub spender: Vec, + pub value: substreams::scalar::BigInt, + } + impl Approval { + const TOPIC_ID: [u8; 32] = [ + 140u8, + 91u8, + 225u8, + 229u8, + 235u8, + 236u8, + 125u8, + 91u8, + 209u8, + 79u8, + 113u8, + 66u8, + 125u8, + 30u8, + 132u8, + 243u8, + 221u8, + 3u8, + 20u8, + 192u8, + 247u8, + 178u8, + 41u8, + 30u8, + 91u8, + 32u8, + 10u8, + 200u8, + 199u8, + 195u8, + 185u8, + 37u8, + ]; + 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(256usize)], + log.data.as_ref(), + ) + .map_err(|e| format!("unable to decode log.data: {:?}", e))?; + values.reverse(); + Ok(Self { + owner: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[1usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'owner' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + spender: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[2usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'spender' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + value: { + 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 Approval { + const NAME: &'static str = "Approval"; + 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 Eip712DomainChanged {} + impl Eip712DomainChanged { + const TOPIC_ID: [u8; 32] = [ + 10u8, + 99u8, + 135u8, + 201u8, + 234u8, + 54u8, + 40u8, + 184u8, + 138u8, + 99u8, + 59u8, + 180u8, + 243u8, + 177u8, + 81u8, + 119u8, + 15u8, + 112u8, + 8u8, + 81u8, + 23u8, + 161u8, + 95u8, + 155u8, + 243u8, + 120u8, + 124u8, + 218u8, + 83u8, + 241u8, + 61u8, + 49u8, + ]; + 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 Eip712DomainChanged { + const NAME: &'static str = "EIP712DomainChanged"; + 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 Transfer { + pub from: Vec, + pub to: Vec, + pub value: substreams::scalar::BigInt, + } + impl Transfer { + const TOPIC_ID: [u8; 32] = [ + 221u8, + 242u8, + 82u8, + 173u8, + 27u8, + 226u8, + 200u8, + 155u8, + 105u8, + 194u8, + 176u8, + 104u8, + 252u8, + 55u8, + 141u8, + 170u8, + 149u8, + 43u8, + 167u8, + 241u8, + 99u8, + 196u8, + 161u8, + 22u8, + 40u8, + 245u8, + 90u8, + 77u8, + 245u8, + 35u8, + 179u8, + 239u8, + ]; + 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(256usize)], + log.data.as_ref(), + ) + .map_err(|e| format!("unable to decode log.data: {:?}", e))?; + values.reverse(); + Ok(Self { + from: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[1usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'from' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + to: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[2usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'to' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + value: { + 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 Transfer { + const NAME: &'static str = "Transfer"; + 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-v3/src/abi/stable_pool_factory_contract.rs b/substreams/ethereum-balancer-v3/src/abi/stable_pool_factory_contract.rs new file mode 100644 index 0000000..f02c9ae --- /dev/null +++ b/substreams/ethereum-balancer-v3/src/abi/stable_pool_factory_contract.rs @@ -0,0 +1,2008 @@ +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<(Vec, substreams::scalar::BigInt, Vec, bool)>, + pub amplification_parameter: substreams::scalar::BigInt, + pub role_accounts: (Vec, Vec, Vec), + pub swap_fee_percentage: substreams::scalar::BigInt, + pub pool_hooks_contract: Vec, + pub enable_donation: bool, + pub disable_unbalanced_liquidity: bool, + pub salt: [u8; 32usize], + } + impl Create { + const METHOD_ID: [u8; 4] = [238u8, 32u8, 66u8, 100u8]; + 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::Tuple( + vec![ + ethabi::ParamType::Address, ethabi::ParamType::Uint(8usize), + ethabi::ParamType::Address, ethabi::ParamType::Bool + ], + ), + ), + ), + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Tuple( + vec![ + ethabi::ParamType::Address, ethabi::ParamType::Address, + ethabi::ParamType::Address + ], + ), + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Address, + ethabi::ParamType::Bool, + ethabi::ParamType::Bool, + 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| { + let tuple_elements = inner.into_tuple().expect(INTERNAL_ERR); + ( + tuple_elements[0usize] + .clone() + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + { + 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_bool() + .expect(INTERNAL_ERR), + ) + }) + .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) + }, + role_accounts: { + 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_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + tuple_elements[2usize] + .clone() + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + }, + 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) + }, + pool_hooks_contract: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + enable_donation: values + .pop() + .expect(INTERNAL_ERR) + .into_bool() + .expect(INTERNAL_ERR), + disable_unbalanced_liquidity: values + .pop() + .expect(INTERNAL_ERR) + .into_bool() + .expect(INTERNAL_ERR), + 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::Tuple( + vec![ + ethabi::Token::Address(ethabi::Address::from_slice(& inner + .0)), + 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::Address(ethabi::Address::from_slice(& inner + .2)), ethabi::Token::Bool(inner.3.clone()) + ], + )) + .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(), + ), + ), + ethabi::Token::Tuple( + vec![ + ethabi::Token::Address(ethabi::Address::from_slice(& self + .role_accounts.0)), + ethabi::Token::Address(ethabi::Address::from_slice(& self + .role_accounts.1)), + ethabi::Token::Address(ethabi::Address::from_slice(& self + .role_accounts.2)) + ], + ), + 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.pool_hooks_contract), + ), + ethabi::Token::Bool(self.enable_donation.clone()), + ethabi::Token::Bool(self.disable_unbalanced_liquidity.clone()), + 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 GetDefaultLiquidityManagement {} + impl GetDefaultLiquidityManagement { + const METHOD_ID: [u8; 4] = [25u8, 58u8, 213u8, 15u8]; + 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, bool, bool, bool), String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result<(bool, bool, bool, bool), String> { + let mut values = ethabi::decode( + &[ + ethabi::ParamType::Tuple( + vec![ + ethabi::ParamType::Bool, ethabi::ParamType::Bool, + ethabi::ParamType::Bool, ethabi::ParamType::Bool + ], + ), + ], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok({ + let tuple_elements = values + .pop() + .expect("one output data should have existed") + .into_tuple() + .expect(INTERNAL_ERR); + ( + tuple_elements[0usize].clone().into_bool().expect(INTERNAL_ERR), + tuple_elements[1usize].clone().into_bool().expect(INTERNAL_ERR), + tuple_elements[2usize].clone().into_bool().expect(INTERNAL_ERR), + tuple_elements[3usize].clone().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<(bool, bool, bool, bool)> { + 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 GetDefaultLiquidityManagement { + const NAME: &'static str = "getDefaultLiquidityManagement"; + 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, bool, bool, bool)> + for GetDefaultLiquidityManagement { + fn output(data: &[u8]) -> Result<(bool, bool, bool, bool), String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetDefaultPoolHooksContract {} + impl GetDefaultPoolHooksContract { + const METHOD_ID: [u8; 4] = [236u8, 136u8, 128u8, 97u8]; + 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 GetDefaultPoolHooksContract { + const NAME: &'static str = "getDefaultPoolHooksContract"; + 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 GetDefaultPoolHooksContract { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetDeploymentAddress { + pub constructor_args: Vec, + pub salt: [u8; 32usize], + } + impl GetDeploymentAddress { + const METHOD_ID: [u8; 4] = [68u8, 246u8, 254u8, 199u8]; + 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::Bytes, ethabi::ParamType::FixedBytes(32usize)], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + constructor_args: values + .pop() + .expect(INTERNAL_ERR) + .into_bytes() + .expect(INTERNAL_ERR), + 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::Bytes(self.constructor_args.clone()), + 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 GetDeploymentAddress { + const NAME: &'static str = "getDeploymentAddress"; + 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 GetDeploymentAddress { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetNewPoolPauseWindowEndTime {} + impl GetNewPoolPauseWindowEndTime { + const METHOD_ID: [u8; 4] = [219u8, 3u8, 94u8, 188u8]; + 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::Uint(32usize)], + 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 GetNewPoolPauseWindowEndTime { + const NAME: &'static str = "getNewPoolPauseWindowEndTime"; + 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 GetNewPoolPauseWindowEndTime { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetOriginalPauseWindowEndTime {} + impl GetOriginalPauseWindowEndTime { + const METHOD_ID: [u8; 4] = [233u8, 213u8, 110u8, 25u8]; + 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::Uint(32usize)], + 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 GetOriginalPauseWindowEndTime { + const NAME: &'static str = "getOriginalPauseWindowEndTime"; + 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 GetOriginalPauseWindowEndTime { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetPauseWindowDuration {} + impl GetPauseWindowDuration { + const METHOD_ID: [u8; 4] = [120u8, 218u8, 128u8, 203u8]; + 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::Uint(32usize)], + 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 GetPauseWindowDuration { + const NAME: &'static str = "getPauseWindowDuration"; + 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 GetPauseWindowDuration { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetPoolCount {} + impl GetPoolCount { + const METHOD_ID: [u8; 4] = [142u8, 236u8, 93u8, 112u8]; + 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::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 GetPoolCount { + const NAME: &'static str = "getPoolCount"; + 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 GetPoolCount { + fn output(data: &[u8]) -> Result { + 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 GetPools {} + impl GetPools { + const METHOD_ID: [u8; 4] = [103u8, 58u8, 42u8, 31u8]; + 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::Array(Box::new(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_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + inner.into_address().expect(INTERNAL_ERR).as_bytes().to_vec() + }) + .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 GetPools { + const NAME: &'static str = "getPools"; + 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 GetPools { + fn output(data: &[u8]) -> Result>, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetPoolsInRange { + pub start: substreams::scalar::BigInt, + pub count: substreams::scalar::BigInt, + } + impl GetPoolsInRange { + const METHOD_ID: [u8; 4] = [83u8, 167u8, 47u8, 126u8]; + 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(256usize), + ethabi::ParamType::Uint(256usize), + ], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + start: { + 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) + }, + count: { + 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.start.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.count.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::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_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + inner.into_address().expect(INTERNAL_ERR).as_bytes().to_vec() + }) + .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 GetPoolsInRange { + const NAME: &'static str = "getPoolsInRange"; + 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 GetPoolsInRange { + 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-v3/src/abi/vault_contract.rs b/substreams/ethereum-balancer-v3/src/abi/vault_contract.rs new file mode 100644 index 0000000..2c1524d --- /dev/null +++ b/substreams/ethereum-balancer-v3/src/abi/vault_contract.rs @@ -0,0 +1,4856 @@ +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 AddLiquidity { + pub params: ( + Vec, + Vec, + Vec, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + Vec, + ), + } + impl AddLiquidity { + const METHOD_ID: [u8; 4] = [74u8, 242u8, 158u8, 196u8]; + 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::Address, ethabi::ParamType::Address, + ethabi::ParamType::Array(Box::new(ethabi::ParamType::Uint(256usize))), + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(8usize), ethabi::ParamType::Bytes + ], + ), + ], + 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_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + tuple_elements[1usize] + .clone() + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + tuple_elements[2usize] + .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[3usize] + .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[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), + ) + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::Tuple( + vec![ + ethabi::Token::Address(ethabi::Address::from_slice(& self + .params.0)), + ethabi::Token::Address(ethabi::Address::from_slice(& self + .params.1)), { let v = self.params.2.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 + .params.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::Uint(ethabi::Uint::from_big_endian(match self + .params.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.params.5.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< + (Vec, substreams::scalar::BigInt, Vec), + String, + > { + Self::output(call.return_data.as_ref()) + } + pub fn output( + data: &[u8], + ) -> Result< + (Vec, substreams::scalar::BigInt, Vec), + String, + > { + let mut values = ethabi::decode( + &[ + ethabi::ParamType::Array( + Box::new(ethabi::ParamType::Uint(256usize)), + ), + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Bytes, + ], + 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| { + 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) + }, + values.pop().expect(INTERNAL_ERR).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< + (Vec, 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 AddLiquidity { + const NAME: &'static str = "addLiquidity"; + 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, Vec), + > for AddLiquidity { + fn output( + data: &[u8], + ) -> Result< + (Vec, substreams::scalar::BigInt, Vec), + String, + > { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct Erc4626BufferWrapOrUnwrap { + pub params: ( + substreams::scalar::BigInt, + substreams::scalar::BigInt, + Vec, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + ), + } + impl Erc4626BufferWrapOrUnwrap { + const METHOD_ID: [u8; 4] = [67u8, 88u8, 59u8, 229u8]; + 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::Uint(8usize), + ethabi::ParamType::Uint(8usize), ethabi::ParamType::Address, + 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 { + params: { + let tuple_elements = values + .pop() + .expect(INTERNAL_ERR) + .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 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(), + { + 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) + }, + { + 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) + }, + ) + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::Tuple( + vec![ + ethabi::Token::Uint(ethabi::Uint::from_big_endian(match self + .params.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::Uint(ethabi::Uint::from_big_endian(match self + .params.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 + .params.2)), + ethabi::Token::Uint(ethabi::Uint::from_big_endian(match self + .params.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::Uint(ethabi::Uint::from_big_endian(match self + .params.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(),),) + ], + ), + ], + ); + 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, + ), + String, + > { + Self::output(call.return_data.as_ref()) + } + pub fn output( + data: &[u8], + ) -> Result< + ( + substreams::scalar::BigInt, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + ), + String, + > { + let mut values = ethabi::decode( + &[ + ethabi::ParamType::Uint(256usize), + 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) + }, + { + 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, + 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 Erc4626BufferWrapOrUnwrap { + const NAME: &'static str = "erc4626BufferWrapOrUnwrap"; + 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, + ), + > for Erc4626BufferWrapOrUnwrap { + fn output( + data: &[u8], + ) -> Result< + ( + substreams::scalar::BigInt, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + ), + String, + > { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetPoolTokenCountAndIndexOfToken { + pub pool: Vec, + pub token: Vec, + } + impl GetPoolTokenCountAndIndexOfToken { + const METHOD_ID: [u8; 4] = [201u8, 193u8, 102u8, 27u8]; + 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 { + pool: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + 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::Address(ethabi::Address::from_slice(&self.pool)), + 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), 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 GetPoolTokenCountAndIndexOfToken { + const NAME: &'static str = "getPoolTokenCountAndIndexOfToken"; + 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 GetPoolTokenCountAndIndexOfToken { + fn output( + data: &[u8], + ) -> Result<(substreams::scalar::BigInt, substreams::scalar::BigInt), String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetVaultExtension {} + impl GetVaultExtension { + const METHOD_ID: [u8; 4] = [185u8, 168u8, 239u8, 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, 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 GetVaultExtension { + const NAME: &'static str = "getVaultExtension"; + 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 GetVaultExtension { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct ReentrancyGuardEntered {} + impl ReentrancyGuardEntered { + const METHOD_ID: [u8; 4] = [210u8, 199u8, 37u8, 224u8]; + 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 ReentrancyGuardEntered { + const NAME: &'static str = "reentrancyGuardEntered"; + 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 ReentrancyGuardEntered { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct RemoveLiquidity { + pub params: ( + Vec, + Vec, + substreams::scalar::BigInt, + Vec, + substreams::scalar::BigInt, + Vec, + ), + } + impl RemoveLiquidity { + const METHOD_ID: [u8; 4] = [33u8, 69u8, 120u8, 151u8]; + 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::Address, ethabi::ParamType::Address, + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Array(Box::new(ethabi::ParamType::Uint(256usize))), + ethabi::ParamType::Uint(8usize), ethabi::ParamType::Bytes + ], + ), + ], + 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_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + 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_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[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), + ) + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::Tuple( + vec![ + ethabi::Token::Address(ethabi::Address::from_slice(& self + .params.0)), + ethabi::Token::Address(ethabi::Address::from_slice(& self + .params.1)), + ethabi::Token::Uint(ethabi::Uint::from_big_endian(match self + .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(),),), { let v = self.params.3.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 + .params.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.params.5.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< + (substreams::scalar::BigInt, Vec, Vec), + String, + > { + Self::output(call.return_data.as_ref()) + } + pub fn output( + data: &[u8], + ) -> Result< + (substreams::scalar::BigInt, Vec, Vec), + String, + > { + let mut values = ethabi::decode( + &[ + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Array( + Box::new(ethabi::ParamType::Uint(256usize)), + ), + ethabi::ParamType::Bytes, + ], + 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) + }, + 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(), + values.pop().expect(INTERNAL_ERR).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< + (substreams::scalar::BigInt, 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 RemoveLiquidity { + const NAME: &'static str = "removeLiquidity"; + 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, Vec, Vec), + > for RemoveLiquidity { + fn output( + data: &[u8], + ) -> Result< + (substreams::scalar::BigInt, Vec, Vec), + String, + > { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct SendTo { + pub token: Vec, + pub to: Vec, + pub amount: substreams::scalar::BigInt, + } + impl SendTo { + const METHOD_ID: [u8; 4] = [174u8, 99u8, 147u8, 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::Address, + ethabi::ParamType::Address, + ethabi::ParamType::Uint(256usize), + ], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + token: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + to: 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) + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::Address(ethabi::Address::from_slice(&self.token)), + ethabi::Token::Address(ethabi::Address::from_slice(&self.to)), + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.amount.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 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 SendTo { + const NAME: &'static str = "sendTo"; + 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 Settle { + pub token: Vec, + pub amount_hint: substreams::scalar::BigInt, + } + impl Settle { + const METHOD_ID: [u8; 4] = [21u8, 175u8, 212u8, 9u8]; + 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::Uint(256usize)], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + token: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + amount_hint: { + 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::Address(ethabi::Address::from_slice(&self.token)), + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.amount_hint.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 Settle { + const NAME: &'static str = "settle"; + 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 Settle { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct Swap { + pub vault_swap_params: ( + substreams::scalar::BigInt, + Vec, + Vec, + Vec, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + Vec, + ), + } + impl Swap { + const METHOD_ID: [u8; 4] = [43u8, 251u8, 120u8, 12u8]; + 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::Uint(8usize), ethabi::ParamType::Address, + ethabi::ParamType::Address, ethabi::ParamType::Address, + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(256usize), ethabi::ParamType::Bytes + ], + ), + ], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + vault_swap_params: { + let tuple_elements = values + .pop() + .expect(INTERNAL_ERR) + .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(), + 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) + }, + { + 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) + }, + tuple_elements[6usize].clone().into_bytes().expect(INTERNAL_ERR), + ) + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::Tuple( + vec![ + ethabi::Token::Uint(ethabi::Uint::from_big_endian(match self + .vault_swap_params.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(& self + .vault_swap_params.1)), + ethabi::Token::Address(ethabi::Address::from_slice(& self + .vault_swap_params.2)), + ethabi::Token::Address(ethabi::Address::from_slice(& self + .vault_swap_params.3)), + ethabi::Token::Uint(ethabi::Uint::from_big_endian(match self + .vault_swap_params.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::Uint(ethabi::Uint::from_big_endian(match self + .vault_swap_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::Bytes(self.vault_swap_params + .6.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< + ( + substreams::scalar::BigInt, + 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, + substreams::scalar::BigInt, + ), + String, + > { + let mut values = ethabi::decode( + &[ + ethabi::ParamType::Uint(256usize), + 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) + }, + { + 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, + 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 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< + ( + substreams::scalar::BigInt, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + ), + > for Swap { + fn output( + data: &[u8], + ) -> Result< + ( + substreams::scalar::BigInt, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + ), + String, + > { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct Transfer { + pub owner: Vec, + pub to: Vec, + pub amount: substreams::scalar::BigInt, + } + impl Transfer { + const METHOD_ID: [u8; 4] = [190u8, 171u8, 172u8, 200u8]; + 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::Uint(256usize), + ], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + owner: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + to: 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) + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::Address(ethabi::Address::from_slice(&self.owner)), + ethabi::Token::Address(ethabi::Address::from_slice(&self.to)), + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.amount.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::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 Transfer { + const NAME: &'static str = "transfer"; + 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 Transfer { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct TransferFrom { + pub spender: Vec, + pub from: Vec, + pub to: Vec, + pub amount: substreams::scalar::BigInt, + } + impl TransferFrom { + const METHOD_ID: [u8; 4] = [21u8, 218u8, 203u8, 234u8]; + 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::Address, + ethabi::ParamType::Uint(256usize), + ], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + spender: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + from: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + to: 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) + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::Address(ethabi::Address::from_slice(&self.spender)), + ethabi::Token::Address(ethabi::Address::from_slice(&self.from)), + ethabi::Token::Address(ethabi::Address::from_slice(&self.to)), + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.amount.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::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 TransferFrom { + const NAME: &'static str = "transferFrom"; + 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 TransferFrom { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct Unlock { + pub data: Vec, + } + impl Unlock { + const METHOD_ID: [u8; 4] = [72u8, 200u8, 148u8, 145u8]; + 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::Bytes], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + data: values.pop().expect(INTERNAL_ERR).into_bytes().expect(INTERNAL_ERR), + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode(&[ethabi::Token::Bytes(self.data.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::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 Unlock { + const NAME: &'static str = "unlock"; + 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 Unlock { + fn output(data: &[u8]) -> Result, String> { + 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 AggregateSwapFeePercentageChanged { + pub pool: Vec, + pub aggregate_swap_fee_percentage: substreams::scalar::BigInt, + } + impl AggregateSwapFeePercentageChanged { + const TOPIC_ID: [u8; 32] = [ + 228u8, + 211u8, + 113u8, + 9u8, + 123u8, + 238u8, + 164u8, + 36u8, + 83u8, + 163u8, + 116u8, + 6u8, + 226u8, + 174u8, + 244u8, + 192u8, + 79u8, + 60u8, + 84u8, + 143u8, + 132u8, + 172u8, + 80u8, + 231u8, + 37u8, + 120u8, + 102u8, + 44u8, + 13u8, + 205u8, + 115u8, + 84u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 2usize { + 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(256usize)], + log.data.as_ref(), + ) + .map_err(|e| format!("unable to decode log.data: {:?}", e))?; + values.reverse(); + 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(), + aggregate_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) + }, + }) + } + } + impl substreams_ethereum::Event for AggregateSwapFeePercentageChanged { + const NAME: &'static str = "AggregateSwapFeePercentageChanged"; + 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 AggregateYieldFeePercentageChanged { + pub pool: Vec, + pub aggregate_yield_fee_percentage: substreams::scalar::BigInt, + } + impl AggregateYieldFeePercentageChanged { + const TOPIC_ID: [u8; 32] = [ + 96u8, + 110u8, + 185u8, + 125u8, + 131u8, + 22u8, + 75u8, + 214u8, + 178u8, + 0u8, + 214u8, + 56u8, + 205u8, + 73u8, + 193u8, + 76u8, + 101u8, + 217u8, + 77u8, + 79u8, + 44u8, + 103u8, + 76u8, + 253u8, + 133u8, + 226u8, + 78u8, + 14u8, + 32u8, + 44u8, + 60u8, + 165u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 2usize { + 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(256usize)], + log.data.as_ref(), + ) + .map_err(|e| format!("unable to decode log.data: {:?}", e))?; + values.reverse(); + 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(), + aggregate_yield_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) + }, + }) + } + } + impl substreams_ethereum::Event for AggregateYieldFeePercentageChanged { + const NAME: &'static str = "AggregateYieldFeePercentageChanged"; + 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 Approval { + pub pool: Vec, + pub owner: Vec, + pub spender: Vec, + pub value: substreams::scalar::BigInt, + } + impl Approval { + const TOPIC_ID: [u8; 32] = [ + 160u8, + 23u8, + 83u8, + 96u8, + 161u8, + 91u8, + 202u8, + 50u8, + 139u8, + 175u8, + 126u8, + 168u8, + 92u8, + 123u8, + 120u8, + 77u8, + 88u8, + 178u8, + 34u8, + 165u8, + 13u8, + 12u8, + 231u8, + 96u8, + 177u8, + 13u8, + 186u8, + 51u8, + 109u8, + 34u8, + 106u8, + 97u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 4usize { + 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(256usize)], + log.data.as_ref(), + ) + .map_err(|e| format!("unable to decode log.data: {:?}", e))?; + values.reverse(); + 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(), + owner: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[2usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'owner' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + spender: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[3usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'spender' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + value: { + 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 Approval { + const NAME: &'static str = "Approval"; + 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 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 BufferSharesBurned { + pub wrapped_token: Vec, + pub from: Vec, + pub burned_shares: substreams::scalar::BigInt, + } + impl BufferSharesBurned { + const TOPIC_ID: [u8; 32] = [ + 78u8, + 9u8, + 247u8, + 247u8, + 252u8, + 55u8, + 206u8, + 40u8, + 151u8, + 128u8, + 14u8, + 44u8, + 42u8, + 144u8, + 153u8, + 86u8, + 94u8, + 219u8, + 10u8, + 19u8, + 61u8, + 25u8, + 216u8, + 74u8, + 104u8, + 113u8, + 179u8, + 83u8, + 10u8, + 248u8, + 132u8, + 107u8, + ]; + 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(256usize)], + log.data.as_ref(), + ) + .map_err(|e| format!("unable to decode log.data: {:?}", e))?; + values.reverse(); + Ok(Self { + wrapped_token: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[1usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'wrapped_token' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + from: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[2usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'from' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + burned_shares: { + 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 BufferSharesBurned { + const NAME: &'static str = "BufferSharesBurned"; + 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 BufferSharesMinted { + pub wrapped_token: Vec, + pub to: Vec, + pub issued_shares: substreams::scalar::BigInt, + } + impl BufferSharesMinted { + const TOPIC_ID: [u8; 32] = [ + 214u8, + 111u8, + 3u8, + 29u8, + 51u8, + 56u8, + 28u8, + 100u8, + 8u8, + 240u8, + 179u8, + 44u8, + 136u8, + 68u8, + 97u8, + 229u8, + 222u8, + 61u8, + 248u8, + 128u8, + 131u8, + 153u8, + 182u8, + 243u8, + 163u8, + 216u8, + 107u8, + 19u8, + 104u8, + 248u8, + 236u8, + 52u8, + ]; + 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(256usize)], + log.data.as_ref(), + ) + .map_err(|e| format!("unable to decode log.data: {:?}", e))?; + values.reverse(); + Ok(Self { + wrapped_token: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[1usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'wrapped_token' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + to: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[2usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'to' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + issued_shares: { + 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 BufferSharesMinted { + const NAME: &'static str = "BufferSharesMinted"; + 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 LiquidityAdded { + pub pool: Vec, + pub liquidity_provider: Vec, + pub kind: substreams::scalar::BigInt, + pub total_supply: substreams::scalar::BigInt, + pub amounts_added_raw: Vec, + pub swap_fee_amounts_raw: Vec, + } + impl LiquidityAdded { + const TOPIC_ID: [u8; 32] = [ + 162u8, + 106u8, + 82u8, + 216u8, + 213u8, + 55u8, + 2u8, + 187u8, + 167u8, + 241u8, + 55u8, + 144u8, + 123u8, + 142u8, + 31u8, + 153u8, + 255u8, + 135u8, + 246u8, + 212u8, + 80u8, + 20u8, + 66u8, + 112u8, + 202u8, + 37u8, + 231u8, + 36u8, + 129u8, + 204u8, + 168u8, + 113u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 4usize { + return false; + } + if log.data.len() < 160usize { + 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::Array( + Box::new(ethabi::ParamType::Uint(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: 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(), + 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(), + kind: { + let mut v = [0 as u8; 32]; + ethabi::decode( + &[ethabi::ParamType::Uint(8usize)], + log.topics[3usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'kind' from topic of type 'uint8': {:?}", + 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) + }, + total_supply: { + 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) + }, + amounts_added_raw: 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_amounts_raw: 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 LiquidityAdded { + const NAME: &'static str = "LiquidityAdded"; + 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 LiquidityAddedToBuffer { + pub wrapped_token: Vec, + pub amount_underlying: substreams::scalar::BigInt, + pub amount_wrapped: substreams::scalar::BigInt, + pub buffer_balances: [u8; 32usize], + } + impl LiquidityAddedToBuffer { + const TOPIC_ID: [u8; 32] = [ + 117u8, + 196u8, + 220u8, + 95u8, + 35u8, + 100u8, + 14u8, + 235u8, + 167u8, + 212u8, + 4u8, + 217u8, + 22u8, + 95u8, + 81u8, + 95u8, + 195u8, + 217u8, + 226u8, + 58u8, + 92u8, + 139u8, + 110u8, + 45u8, + 9u8, + 180u8, + 185u8, + 218u8, + 86u8, + 255u8, + 0u8, + 169u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 2usize { + return false; + } + if log.data.len() != 96usize { + 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), + ethabi::ParamType::FixedBytes(32usize), + ], + log.data.as_ref(), + ) + .map_err(|e| format!("unable to decode log.data: {:?}", e))?; + values.reverse(); + Ok(Self { + wrapped_token: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[1usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'wrapped_token' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + amount_underlying: { + 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_wrapped: { + 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) + }, + buffer_balances: { + let mut result = [0u8; 32]; + let v = values + .pop() + .expect(INTERNAL_ERR) + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }, + }) + } + } + impl substreams_ethereum::Event for LiquidityAddedToBuffer { + const NAME: &'static str = "LiquidityAddedToBuffer"; + 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 LiquidityRemoved { + pub pool: Vec, + pub liquidity_provider: Vec, + pub kind: substreams::scalar::BigInt, + pub total_supply: substreams::scalar::BigInt, + pub amounts_removed_raw: Vec, + pub swap_fee_amounts_raw: Vec, + } + impl LiquidityRemoved { + const TOPIC_ID: [u8; 32] = [ + 251u8, + 229u8, + 176u8, + 215u8, + 159u8, + 185u8, + 79u8, + 30u8, + 129u8, + 192u8, + 169u8, + 43u8, + 248u8, + 106u8, + 233u8, + 211u8, + 161u8, + 158u8, + 157u8, + 27u8, + 246u8, + 32u8, + 44u8, + 13u8, + 62u8, + 117u8, + 18u8, + 15u8, + 101u8, + 213u8, + 216u8, + 165u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 4usize { + return false; + } + if log.data.len() < 160usize { + 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::Array( + Box::new(ethabi::ParamType::Uint(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: 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(), + 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(), + kind: { + let mut v = [0 as u8; 32]; + ethabi::decode( + &[ethabi::ParamType::Uint(8usize)], + log.topics[3usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'kind' from topic of type 'uint8': {:?}", + 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) + }, + total_supply: { + 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) + }, + amounts_removed_raw: 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_amounts_raw: 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 LiquidityRemoved { + const NAME: &'static str = "LiquidityRemoved"; + 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 LiquidityRemovedFromBuffer { + pub wrapped_token: Vec, + pub amount_underlying: substreams::scalar::BigInt, + pub amount_wrapped: substreams::scalar::BigInt, + pub buffer_balances: [u8; 32usize], + } + impl LiquidityRemovedFromBuffer { + const TOPIC_ID: [u8; 32] = [ + 68u8, + 217u8, + 123u8, + 54u8, + 233u8, + 155u8, + 89u8, + 11u8, + 61u8, + 40u8, + 117u8, + 170u8, + 211u8, + 177u8, + 103u8, + 177u8, + 215u8, + 251u8, + 30u8, + 6u8, + 63u8, + 63u8, + 19u8, + 37u8, + 161u8, + 238u8, + 172u8, + 118u8, + 202u8, + 238u8, + 81u8, + 19u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 2usize { + return false; + } + if log.data.len() != 96usize { + 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), + ethabi::ParamType::FixedBytes(32usize), + ], + log.data.as_ref(), + ) + .map_err(|e| format!("unable to decode log.data: {:?}", e))?; + values.reverse(); + Ok(Self { + wrapped_token: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[1usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'wrapped_token' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + amount_underlying: { + 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_wrapped: { + 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) + }, + buffer_balances: { + let mut result = [0u8; 32]; + let v = values + .pop() + .expect(INTERNAL_ERR) + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }, + }) + } + } + impl substreams_ethereum::Event for LiquidityRemovedFromBuffer { + const NAME: &'static str = "LiquidityRemovedFromBuffer"; + 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 PoolInitialized { + pub pool: Vec, + } + impl PoolInitialized { + const TOPIC_ID: [u8; 32] = [ + 202u8, + 216u8, + 201u8, + 211u8, + 37u8, + 7u8, + 57u8, + 59u8, + 101u8, + 8u8, + 202u8, + 74u8, + 136u8, + 139u8, + 129u8, + 151u8, + 153u8, + 25u8, + 180u8, + 119u8, + 81u8, + 5u8, + 133u8, + 189u8, + 232u8, + 72u8, + 143u8, + 21u8, + 48u8, + 114u8, + 214u8, + 243u8, + ]; + 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 PoolInitialized { + const NAME: &'static str = "PoolInitialized"; + 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 PoolPausedStateChanged { + pub pool: Vec, + pub paused: bool, + } + impl PoolPausedStateChanged { + const TOPIC_ID: [u8; 32] = [ + 87u8, + 226u8, + 4u8, + 72u8, + 2u8, + 130u8, + 151u8, + 25u8, + 1u8, + 34u8, + 87u8, + 27u8, + 231u8, + 203u8, + 108u8, + 27u8, + 30u8, + 248u8, + 87u8, + 48u8, + 198u8, + 115u8, + 247u8, + 199u8, + 47u8, + 83u8, + 60u8, + 134u8, + 98u8, + 65u8, + 154u8, + 167u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 2usize { + 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 { + 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(), + paused: values + .pop() + .expect(INTERNAL_ERR) + .into_bool() + .expect(INTERNAL_ERR), + }) + } + } + impl substreams_ethereum::Event for PoolPausedStateChanged { + const NAME: &'static str = "PoolPausedStateChanged"; + 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 PoolRecoveryModeStateChanged { + pub pool: Vec, + pub recovery_mode: bool, + } + impl PoolRecoveryModeStateChanged { + const TOPIC_ID: [u8; 32] = [ + 194u8, + 53u8, + 76u8, + 194u8, + 247u8, + 142u8, + 165u8, + 119u8, + 119u8, + 229u8, + 93u8, + 221u8, + 67u8, + 167u8, + 242u8, + 43u8, + 17u8, + 44u8, + 233u8, + 136u8, + 104u8, + 89u8, + 104u8, + 128u8, + 237u8, + 174u8, + 178u8, + 43u8, + 79u8, + 156u8, + 115u8, + 169u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 2usize { + 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 { + 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(), + recovery_mode: values + .pop() + .expect(INTERNAL_ERR) + .into_bool() + .expect(INTERNAL_ERR), + }) + } + } + impl substreams_ethereum::Event for PoolRecoveryModeStateChanged { + const NAME: &'static str = "PoolRecoveryModeStateChanged"; + 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: Vec, + pub factory: Vec, + pub token_config: Vec<(Vec, substreams::scalar::BigInt, Vec, bool)>, + pub swap_fee_percentage: substreams::scalar::BigInt, + pub pause_window_end_time: substreams::scalar::BigInt, + pub role_accounts: (Vec, Vec, Vec), + pub hooks_config: ( + bool, + bool, + bool, + bool, + bool, + bool, + bool, + bool, + bool, + bool, + Vec, + ), + pub liquidity_management: (bool, bool, bool, bool), + } + impl PoolRegistered { + const TOPIC_ID: [u8; 32] = [ + 188u8, + 21u8, + 97u8, + 238u8, + 171u8, + 159u8, + 64u8, + 150u8, + 46u8, + 47u8, + 184u8, + 39u8, + 167u8, + 255u8, + 156u8, + 124u8, + 219u8, + 71u8, + 169u8, + 215u8, + 200u8, + 76u8, + 174u8, + 239u8, + 164u8, + 237u8, + 144u8, + 224u8, + 67u8, + 132u8, + 45u8, + 173u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 3usize { + return false; + } + if log.data.len() < 704usize { + 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::Tuple( + vec![ + ethabi::ParamType::Address, ethabi::ParamType::Uint(8usize), + ethabi::ParamType::Address, ethabi::ParamType::Bool + ], + ), + ), + ), + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(32usize), + ethabi::ParamType::Tuple( + vec![ + ethabi::ParamType::Address, ethabi::ParamType::Address, + ethabi::ParamType::Address + ], + ), + ethabi::ParamType::Tuple( + vec![ + ethabi::ParamType::Bool, ethabi::ParamType::Bool, + ethabi::ParamType::Bool, ethabi::ParamType::Bool, + ethabi::ParamType::Bool, ethabi::ParamType::Bool, + ethabi::ParamType::Bool, ethabi::ParamType::Bool, + ethabi::ParamType::Bool, ethabi::ParamType::Bool, + ethabi::ParamType::Address + ], + ), + ethabi::ParamType::Tuple( + vec![ + ethabi::ParamType::Bool, ethabi::ParamType::Bool, + ethabi::ParamType::Bool, ethabi::ParamType::Bool + ], + ), + ], + log.data.as_ref(), + ) + .map_err(|e| format!("unable to decode log.data: {:?}", e))?; + values.reverse(); + 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(), + factory: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[2usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'factory' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + token_config: values + .pop() + .expect(INTERNAL_ERR) + .into_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + let tuple_elements = inner.into_tuple().expect(INTERNAL_ERR); + ( + tuple_elements[0usize] + .clone() + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + { + 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_bool() + .expect(INTERNAL_ERR), + ) + }) + .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) + }, + pause_window_end_time: { + 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) + }, + role_accounts: { + 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_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + tuple_elements[2usize] + .clone() + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + }, + hooks_config: { + let tuple_elements = values + .pop() + .expect(INTERNAL_ERR) + .into_tuple() + .expect(INTERNAL_ERR); + ( + tuple_elements[0usize].clone().into_bool().expect(INTERNAL_ERR), + tuple_elements[1usize].clone().into_bool().expect(INTERNAL_ERR), + tuple_elements[2usize].clone().into_bool().expect(INTERNAL_ERR), + tuple_elements[3usize].clone().into_bool().expect(INTERNAL_ERR), + tuple_elements[4usize].clone().into_bool().expect(INTERNAL_ERR), + tuple_elements[5usize].clone().into_bool().expect(INTERNAL_ERR), + tuple_elements[6usize].clone().into_bool().expect(INTERNAL_ERR), + tuple_elements[7usize].clone().into_bool().expect(INTERNAL_ERR), + tuple_elements[8usize].clone().into_bool().expect(INTERNAL_ERR), + tuple_elements[9usize].clone().into_bool().expect(INTERNAL_ERR), + tuple_elements[10usize] + .clone() + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + }, + liquidity_management: { + let tuple_elements = values + .pop() + .expect(INTERNAL_ERR) + .into_tuple() + .expect(INTERNAL_ERR); + ( + tuple_elements[0usize].clone().into_bool().expect(INTERNAL_ERR), + tuple_elements[1usize].clone().into_bool().expect(INTERNAL_ERR), + tuple_elements[2usize].clone().into_bool().expect(INTERNAL_ERR), + tuple_elements[3usize].clone().into_bool().expect(INTERNAL_ERR), + ) + }, + }) + } + } + 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 ProtocolFeeControllerChanged { + pub new_protocol_fee_controller: Vec, + } + impl ProtocolFeeControllerChanged { + const TOPIC_ID: [u8; 32] = [ + 40u8, + 10u8, + 96u8, + 177u8, + 230u8, + 60u8, + 23u8, + 116u8, + 211u8, + 151u8, + 211u8, + 92u8, + 206u8, + 128u8, + 235u8, + 128u8, + 229u8, + 20u8, + 8u8, + 234u8, + 215u8, + 85u8, + 251u8, + 68u8, + 110u8, + 111u8, + 116u8, + 76u8, + 233u8, + 142u8, + 93u8, + 240u8, + ]; + 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_protocol_fee_controller: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[1usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'new_protocol_fee_controller' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + }) + } + } + impl substreams_ethereum::Event for ProtocolFeeControllerChanged { + const NAME: &'static str = "ProtocolFeeControllerChanged"; + 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: Vec, + pub token_in: Vec, + pub token_out: Vec, + pub amount_in: substreams::scalar::BigInt, + pub amount_out: substreams::scalar::BigInt, + pub swap_fee_percentage: substreams::scalar::BigInt, + pub swap_fee_amount: substreams::scalar::BigInt, + } + impl Swap { + const TOPIC_ID: [u8; 32] = [ + 8u8, + 116u8, + 178u8, + 213u8, + 69u8, + 203u8, + 39u8, + 28u8, + 219u8, + 218u8, + 78u8, + 9u8, + 48u8, + 32u8, + 196u8, + 82u8, + 50u8, + 139u8, + 36u8, + 175u8, + 18u8, + 56u8, + 46u8, + 214u8, + 44u8, + 77u8, + 0u8, + 245u8, + 194u8, + 103u8, + 9u8, + 219u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 4usize { + 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::Uint(256usize), + ethabi::ParamType::Uint(256usize), + 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: 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(), + 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) + }, + 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) + }, + swap_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 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 SwapFeePercentageChanged { + pub pool: Vec, + pub swap_fee_percentage: substreams::scalar::BigInt, + } + impl SwapFeePercentageChanged { + const TOPIC_ID: [u8; 32] = [ + 137u8, + 212u8, + 21u8, + 34u8, + 52u8, + 47u8, + 171u8, + 172u8, + 20u8, + 113u8, + 202u8, + 96u8, + 115u8, + 165u8, + 98u8, + 62u8, + 92u8, + 175u8, + 54u8, + 123u8, + 3u8, + 202u8, + 110u8, + 154u8, + 0u8, + 20u8, + 120u8, + 208u8, + 207u8, + 139u8, + 228u8, + 161u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 2usize { + 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(256usize)], + log.data.as_ref(), + ) + .map_err(|e| format!("unable to decode log.data: {:?}", e))?; + values.reverse(); + 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(), + 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) + }, + }) + } + } + impl substreams_ethereum::Event for SwapFeePercentageChanged { + const NAME: &'static str = "SwapFeePercentageChanged"; + 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 Transfer { + pub pool: Vec, + pub from: Vec, + pub to: Vec, + pub value: substreams::scalar::BigInt, + } + impl Transfer { + const TOPIC_ID: [u8; 32] = [ + 209u8, + 57u8, + 139u8, + 238u8, + 25u8, + 49u8, + 61u8, + 107u8, + 246u8, + 114u8, + 204u8, + 177u8, + 22u8, + 229u8, + 31u8, + 74u8, + 26u8, + 148u8, + 126u8, + 145u8, + 199u8, + 87u8, + 144u8, + 127u8, + 81u8, + 251u8, + 181u8, + 181u8, + 229u8, + 108u8, + 105u8, + 143u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 4usize { + 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(256usize)], + log.data.as_ref(), + ) + .map_err(|e| format!("unable to decode log.data: {:?}", e))?; + values.reverse(); + 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(), + from: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[2usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'from' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + to: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[3usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'to' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + value: { + 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 Transfer { + const NAME: &'static str = "Transfer"; + 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 Unwrap { + pub wrapped_token: Vec, + pub burned_shares: substreams::scalar::BigInt, + pub withdrawn_underlying: substreams::scalar::BigInt, + pub buffer_balances: [u8; 32usize], + } + impl Unwrap { + const TOPIC_ID: [u8; 32] = [ + 238u8, + 183u8, + 64u8, + 201u8, + 11u8, + 242u8, + 177u8, + 140u8, + 149u8, + 50u8, + 235u8, + 125u8, + 71u8, + 49u8, + 55u8, + 118u8, + 112u8, + 54u8, + 216u8, + 147u8, + 223u8, + 243u8, + 224u8, + 9u8, + 243u8, + 39u8, + 24u8, + 248u8, + 33u8, + 178u8, + 164u8, + 192u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 2usize { + return false; + } + if log.data.len() != 96usize { + 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), + ethabi::ParamType::FixedBytes(32usize), + ], + log.data.as_ref(), + ) + .map_err(|e| format!("unable to decode log.data: {:?}", e))?; + values.reverse(); + Ok(Self { + wrapped_token: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[1usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'wrapped_token' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + burned_shares: { + 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) + }, + withdrawn_underlying: { + 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) + }, + buffer_balances: { + let mut result = [0u8; 32]; + let v = values + .pop() + .expect(INTERNAL_ERR) + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }, + }) + } + } + impl substreams_ethereum::Event for Unwrap { + const NAME: &'static str = "Unwrap"; + 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 VaultAuxiliary { + pub pool: Vec, + pub event_key: [u8; 32usize], + pub event_data: Vec, + } + impl VaultAuxiliary { + const TOPIC_ID: [u8; 32] = [ + 75u8, + 196u8, + 65u8, + 46u8, + 33u8, + 1u8, + 21u8, + 69u8, + 105u8, + 3u8, + 198u8, + 91u8, + 82u8, + 119u8, + 210u8, + 153u8, + 165u8, + 5u8, + 231u8, + 159u8, + 46u8, + 184u8, + 82u8, + 185u8, + 43u8, + 28u8, + 165u8, + 45u8, + 133u8, + 133u8, + 100u8, + 40u8, + ]; + 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::Bytes], + log.data.as_ref(), + ) + .map_err(|e| format!("unable to decode log.data: {:?}", e))?; + values.reverse(); + 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(), + event_key: { + let mut result = [0u8; 32]; + let v = ethabi::decode( + &[ethabi::ParamType::FixedBytes(32usize)], + log.topics[2usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'event_key' from topic of type 'bytes32': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }, + event_data: values + .pop() + .expect(INTERNAL_ERR) + .into_bytes() + .expect(INTERNAL_ERR), + }) + } + } + impl substreams_ethereum::Event for VaultAuxiliary { + const NAME: &'static str = "VaultAuxiliary"; + 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 VaultBuffersPausedStateChanged { + pub paused: bool, + } + impl VaultBuffersPausedStateChanged { + const TOPIC_ID: [u8; 32] = [ + 48u8, + 12u8, + 124u8, + 166u8, + 25u8, + 235u8, + 132u8, + 99u8, + 134u8, + 170u8, + 10u8, + 110u8, + 89u8, + 22u8, + 172u8, + 42u8, + 65u8, + 64u8, + 100u8, + 72u8, + 176u8, + 162u8, + 233u8, + 155u8, + 169u8, + 204u8, + 175u8, + 235u8, + 137u8, + 144u8, + 21u8, + 165u8, + ]; + 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 VaultBuffersPausedStateChanged { + const NAME: &'static str = "VaultBuffersPausedStateChanged"; + 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 VaultPausedStateChanged { + pub paused: bool, + } + impl VaultPausedStateChanged { + const TOPIC_ID: [u8; 32] = [ + 224u8, + 98u8, + 159u8, + 230u8, + 86u8, + 228u8, + 90u8, + 215u8, + 253u8, + 99u8, + 162u8, + 75u8, + 137u8, + 157u8, + 163u8, + 104u8, + 105u8, + 0u8, + 36u8, + 192u8, + 112u8, + 67u8, + 184u8, + 142u8, + 87u8, + 174u8, + 229u8, + 9u8, + 91u8, + 29u8, + 61u8, + 2u8, + ]; + 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 VaultPausedStateChanged { + const NAME: &'static str = "VaultPausedStateChanged"; + 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 VaultQueriesDisabled {} + impl VaultQueriesDisabled { + const TOPIC_ID: [u8; 32] = [ + 189u8, + 32u8, + 64u8, + 144u8, + 253u8, + 56u8, + 127u8, + 8u8, + 227u8, + 7u8, + 101u8, + 40u8, + 191u8, + 9u8, + 180u8, + 252u8, + 153u8, + 216u8, + 16u8, + 13u8, + 116u8, + 158u8, + 172u8, + 233u8, + 108u8, + 6u8, + 0u8, + 45u8, + 63u8, + 237u8, + 198u8, + 37u8, + ]; + 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 VaultQueriesDisabled { + const NAME: &'static str = "VaultQueriesDisabled"; + 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 VaultQueriesEnabled {} + impl VaultQueriesEnabled { + const TOPIC_ID: [u8; 32] = [ + 145u8, + 215u8, + 71u8, + 136u8, + 53u8, + 242u8, + 181u8, + 173u8, + 195u8, + 21u8, + 245u8, + 170u8, + 217u8, + 32u8, + 244u8, + 167u8, + 240u8, + 160u8, + 47u8, + 127u8, + 221u8, + 243u8, + 4u8, + 45u8, + 23u8, + 178u8, + 200u8, + 1u8, + 104u8, + 234u8, + 23u8, + 245u8, + ]; + 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 VaultQueriesEnabled { + const NAME: &'static str = "VaultQueriesEnabled"; + 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 Wrap { + pub wrapped_token: Vec, + pub deposited_underlying: substreams::scalar::BigInt, + pub minted_shares: substreams::scalar::BigInt, + pub buffer_balances: [u8; 32usize], + } + impl Wrap { + const TOPIC_ID: [u8; 32] = [ + 55u8, + 113u8, + 209u8, + 60u8, + 103u8, + 1u8, + 30u8, + 49u8, + 225u8, + 32u8, + 49u8, + 197u8, + 75u8, + 181u8, + 155u8, + 11u8, + 245u8, + 68u8, + 168u8, + 11u8, + 129u8, + 210u8, + 128u8, + 163u8, + 113u8, + 30u8, + 23u8, + 42u8, + 168u8, + 183u8, + 244u8, + 123u8, + ]; + pub fn match_log(log: &substreams_ethereum::pb::eth::v2::Log) -> bool { + if log.topics.len() != 2usize { + return false; + } + if log.data.len() != 96usize { + 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), + ethabi::ParamType::FixedBytes(32usize), + ], + log.data.as_ref(), + ) + .map_err(|e| format!("unable to decode log.data: {:?}", e))?; + values.reverse(); + Ok(Self { + wrapped_token: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[1usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'wrapped_token' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + deposited_underlying: { + 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) + }, + minted_shares: { + 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) + }, + buffer_balances: { + let mut result = [0u8; 32]; + let v = values + .pop() + .expect(INTERNAL_ERR) + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }, + }) + } + } + impl substreams_ethereum::Event for Wrap { + const NAME: &'static str = "Wrap"; + 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-v3/src/abi/weighted_pool_contract.rs b/substreams/ethereum-balancer-v3/src/abi/weighted_pool_contract.rs new file mode 100644 index 0000000..6692d0b --- /dev/null +++ b/substreams/ethereum-balancer-v3/src/abi/weighted_pool_contract.rs @@ -0,0 +1,4488 @@ +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 Allowance { + pub owner: Vec, + pub spender: Vec, + } + impl Allowance { + const METHOD_ID: [u8; 4] = [221u8, 98u8, 237u8, 62u8]; + 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 { + owner: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + spender: 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.owner)), + ethabi::Token::Address(ethabi::Address::from_slice(&self.spender)), + ], + ); + 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 Allowance { + const NAME: &'static str = "allowance"; + 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 Allowance { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct Approve { + pub spender: Vec, + pub amount: substreams::scalar::BigInt, + } + impl Approve { + const METHOD_ID: [u8; 4] = [9u8, 94u8, 167u8, 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::Address, ethabi::ParamType::Uint(256usize)], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + spender: 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) + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::Address(ethabi::Address::from_slice(&self.spender)), + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.amount.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::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 Approve { + const NAME: &'static str = "approve"; + 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 Approve { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct BalanceOf { + pub account: Vec, + } + impl BalanceOf { + const METHOD_ID: [u8; 4] = [112u8, 160u8, 130u8, 49u8]; + 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 { + account: 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.account))], + ); + 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 BalanceOf { + const NAME: &'static str = "balanceOf"; + 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 BalanceOf { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct ComputeBalance { + pub balances_live_scaled18: Vec, + pub token_in_index: substreams::scalar::BigInt, + pub invariant_ratio: substreams::scalar::BigInt, + } + impl ComputeBalance { + const METHOD_ID: [u8; 4] = [22u8, 160u8, 179u8, 224u8]; + 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::Uint(256usize)), + ), + 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 { + balances_live_scaled18: 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(), + token_in_index: { + 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) + }, + invariant_ratio: { + 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( + &[ + { + let v = self + .balances_live_scaled18 + .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.token_in_index.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.invariant_ratio.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 ComputeBalance { + const NAME: &'static str = "computeBalance"; + 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 ComputeBalance { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct ComputeInvariant { + pub balances_live_scaled18: Vec, + pub rounding: substreams::scalar::BigInt, + } + impl ComputeInvariant { + const METHOD_ID: [u8; 4] = [152u8, 77u8, 233u8, 232u8]; + 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::Uint(256usize)), + ), + ethabi::ParamType::Uint(8usize), + ], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + balances_live_scaled18: 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(), + rounding: { + 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( + &[ + { + let v = self + .balances_live_scaled18 + .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.rounding.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 ComputeInvariant { + const NAME: &'static str = "computeInvariant"; + 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 ComputeInvariant { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct Decimals {} + impl Decimals { + const METHOD_ID: [u8; 4] = [49u8, 60u8, 229u8, 103u8]; + 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::Uint(8usize)], + 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 Decimals { + const NAME: &'static str = "decimals"; + 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 Decimals { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct DomainSeparator {} + impl DomainSeparator { + const METHOD_ID: [u8; 4] = [54u8, 68u8, 229u8, 21u8]; + 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 DomainSeparator { + const NAME: &'static str = "DOMAIN_SEPARATOR"; + 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 DomainSeparator { + fn output(data: &[u8]) -> Result<[u8; 32usize], String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct Eip712Domain {} + impl Eip712Domain { + const METHOD_ID: [u8; 4] = [132u8, 176u8, 25u8, 110u8]; + 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; 1usize], + String, + String, + substreams::scalar::BigInt, + Vec, + [u8; 32usize], + Vec, + ), + String, + > { + Self::output(call.return_data.as_ref()) + } + pub fn output( + data: &[u8], + ) -> Result< + ( + [u8; 1usize], + String, + String, + substreams::scalar::BigInt, + Vec, + [u8; 32usize], + Vec, + ), + String, + > { + let mut values = ethabi::decode( + &[ + ethabi::ParamType::FixedBytes(1usize), + ethabi::ParamType::String, + ethabi::ParamType::String, + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Address, + ethabi::ParamType::FixedBytes(32usize), + ethabi::ParamType::Array( + Box::new(ethabi::ParamType::Uint(256usize)), + ), + ], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + values.reverse(); + Ok(( + { + let mut result = [0u8; 1]; + let v = values + .pop() + .expect(INTERNAL_ERR) + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }, + values.pop().expect(INTERNAL_ERR).into_string().expect(INTERNAL_ERR), + values.pop().expect(INTERNAL_ERR).into_string().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) + }, + values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + { + let mut result = [0u8; 32]; + let v = values + .pop() + .expect(INTERNAL_ERR) + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }, + 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(), + )) + } + 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; 1usize], + String, + String, + substreams::scalar::BigInt, + Vec, + [u8; 32usize], + 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 Eip712Domain { + const NAME: &'static str = "eip712Domain"; + 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; 1usize], + String, + String, + substreams::scalar::BigInt, + Vec, + [u8; 32usize], + Vec, + ), + > for Eip712Domain { + fn output( + data: &[u8], + ) -> Result< + ( + [u8; 1usize], + String, + String, + substreams::scalar::BigInt, + Vec, + [u8; 32usize], + Vec, + ), + String, + > { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct EmitApproval { + pub owner: Vec, + pub spender: Vec, + pub amount: substreams::scalar::BigInt, + } + impl EmitApproval { + const METHOD_ID: [u8; 4] = [86u8, 135u8, 242u8, 184u8]; + 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::Uint(256usize), + ], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + owner: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + spender: 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) + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::Address(ethabi::Address::from_slice(&self.owner)), + ethabi::Token::Address(ethabi::Address::from_slice(&self.spender)), + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.amount.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 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 EmitApproval { + const NAME: &'static str = "emitApproval"; + 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 EmitTransfer { + pub from: Vec, + pub to: Vec, + pub amount: substreams::scalar::BigInt, + } + impl EmitTransfer { + const METHOD_ID: [u8; 4] = [35u8, 222u8, 102u8, 81u8]; + 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::Uint(256usize), + ], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + from: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + to: 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) + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::Address(ethabi::Address::from_slice(&self.from)), + ethabi::Token::Address(ethabi::Address::from_slice(&self.to)), + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.amount.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 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 EmitTransfer { + const NAME: &'static str = "emitTransfer"; + 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 GetAggregateFeePercentages {} + impl GetAggregateFeePercentages { + const METHOD_ID: [u8; 4] = [129u8, 250u8, 128u8, 124u8]; + 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 GetAggregateFeePercentages { + const NAME: &'static str = "getAggregateFeePercentages"; + 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 GetAggregateFeePercentages { + fn output( + data: &[u8], + ) -> Result<(substreams::scalar::BigInt, substreams::scalar::BigInt), String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetCurrentLiveBalances {} + impl GetCurrentLiveBalances { + const METHOD_ID: [u8; 4] = [177u8, 86u8, 170u8, 10u8]; + 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::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 GetCurrentLiveBalances { + const NAME: &'static str = "getCurrentLiveBalances"; + 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 GetCurrentLiveBalances { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetMaximumInvariantRatio {} + impl GetMaximumInvariantRatio { + const METHOD_ID: [u8; 4] = [39u8, 60u8, 26u8, 223u8]; + 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::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 GetMaximumInvariantRatio { + const NAME: &'static str = "getMaximumInvariantRatio"; + 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 GetMaximumInvariantRatio { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetMaximumSwapFeePercentage {} + impl GetMaximumSwapFeePercentage { + const METHOD_ID: [u8; 4] = [101u8, 76u8, 241u8, 93u8]; + 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::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 GetMaximumSwapFeePercentage { + const NAME: &'static str = "getMaximumSwapFeePercentage"; + 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 GetMaximumSwapFeePercentage { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetMinimumInvariantRatio {} + impl GetMinimumInvariantRatio { + const METHOD_ID: [u8; 4] = [182u8, 119u8, 250u8, 86u8]; + 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::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 GetMinimumInvariantRatio { + const NAME: &'static str = "getMinimumInvariantRatio"; + 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 GetMinimumInvariantRatio { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetMinimumSwapFeePercentage {} + impl GetMinimumSwapFeePercentage { + const METHOD_ID: [u8; 4] = [206u8, 32u8, 236u8, 231u8]; + 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::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 GetMinimumSwapFeePercentage { + const NAME: &'static str = "getMinimumSwapFeePercentage"; + 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 GetMinimumSwapFeePercentage { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetNormalizedWeights {} + impl GetNormalizedWeights { + const METHOD_ID: [u8; 4] = [248u8, 159u8, 39u8, 237u8]; + 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::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 GetNormalizedWeights { + const NAME: &'static str = "getNormalizedWeights"; + 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 GetNormalizedWeights { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetRate {} + impl GetRate { + const METHOD_ID: [u8; 4] = [103u8, 154u8, 239u8, 206u8]; + 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::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 GetRate { + const NAME: &'static str = "getRate"; + 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 GetRate { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetStaticSwapFeePercentage {} + impl GetStaticSwapFeePercentage { + const METHOD_ID: [u8; 4] = [211u8, 53u8, 176u8, 207u8]; + 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::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 GetStaticSwapFeePercentage { + const NAME: &'static str = "getStaticSwapFeePercentage"; + 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 GetStaticSwapFeePercentage { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetTokenInfo {} + impl GetTokenInfo { + const METHOD_ID: [u8; 4] = [171u8, 177u8, 220u8, 68u8]; + 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<(substreams::scalar::BigInt, Vec, bool)>, + Vec, + Vec, + ), + String, + > { + Self::output(call.return_data.as_ref()) + } + pub fn output( + data: &[u8], + ) -> Result< + ( + Vec>, + Vec<(substreams::scalar::BigInt, Vec, bool)>, + Vec, + Vec, + ), + String, + > { + let mut values = ethabi::decode( + &[ + ethabi::ParamType::Array(Box::new(ethabi::ParamType::Address)), + ethabi::ParamType::Array( + Box::new( + ethabi::ParamType::Tuple( + vec![ + ethabi::ParamType::Uint(8usize), ethabi::ParamType::Address, + ethabi::ParamType::Bool + ], + ), + ), + ), + ethabi::ParamType::Array( + Box::new(ethabi::ParamType::Uint(256usize)), + ), + ethabi::ParamType::Array( + Box::new(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 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(), + tuple_elements[2usize] + .clone() + .into_bool() + .expect(INTERNAL_ERR), + ) + }) + .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(), + 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(), + )) + } + 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, Vec, bool)>, + 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 GetTokenInfo { + const NAME: &'static str = "getTokenInfo"; + 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, Vec, bool)>, + Vec, + Vec, + ), + > for GetTokenInfo { + fn output( + data: &[u8], + ) -> Result< + ( + Vec>, + Vec<(substreams::scalar::BigInt, Vec, bool)>, + Vec, + Vec, + ), + String, + > { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetTokens {} + impl GetTokens { + const METHOD_ID: [u8; 4] = [170u8, 108u8, 168u8, 8u8]; + 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::Array(Box::new(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_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + inner.into_address().expect(INTERNAL_ERR).as_bytes().to_vec() + }) + .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 GetTokens { + const NAME: &'static str = "getTokens"; + 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 GetTokens { + 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 GetWeightedPoolDynamicData {} + impl GetWeightedPoolDynamicData { + const METHOD_ID: [u8; 4] = [192u8, 188u8, 111u8, 51u8]; + 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, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + bool, + bool, + bool, + ), + String, + > { + Self::output(call.return_data.as_ref()) + } + pub fn output( + data: &[u8], + ) -> Result< + ( + Vec, + Vec, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + bool, + bool, + bool, + ), + String, + > { + let mut values = ethabi::decode( + &[ + ethabi::ParamType::Tuple( + vec![ + ethabi::ParamType::Array(Box::new(ethabi::ParamType::Uint(256usize))), + ethabi::ParamType::Array(Box::new(ethabi::ParamType::Uint(256usize))), + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(256usize), ethabi::ParamType::Bool, + ethabi::ParamType::Bool, ethabi::ParamType::Bool + ], + ), + ], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok({ + let tuple_elements = values + .pop() + .expect("one output data should have existed") + .into_tuple() + .expect(INTERNAL_ERR); + ( + tuple_elements[0usize] + .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[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) + }, + { + 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_bool().expect(INTERNAL_ERR), + tuple_elements[5usize].clone().into_bool().expect(INTERNAL_ERR), + tuple_elements[6usize].clone().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< + ( + Vec, + Vec, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + bool, + bool, + bool, + ), + > { + 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 GetWeightedPoolDynamicData { + const NAME: &'static str = "getWeightedPoolDynamicData"; + 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, + substreams::scalar::BigInt, + bool, + bool, + bool, + ), + > for GetWeightedPoolDynamicData { + fn output( + data: &[u8], + ) -> Result< + ( + Vec, + Vec, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + bool, + bool, + bool, + ), + String, + > { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetWeightedPoolImmutableData {} + impl GetWeightedPoolImmutableData { + const METHOD_ID: [u8; 4] = [83u8, 183u8, 155u8, 215u8]; + 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, + Vec, + ), + String, + > { + Self::output(call.return_data.as_ref()) + } + pub fn output( + data: &[u8], + ) -> Result< + ( + Vec>, + Vec, + Vec, + ), + String, + > { + let mut values = ethabi::decode( + &[ + ethabi::ParamType::Tuple( + vec![ + ethabi::ParamType::Array(Box::new(ethabi::ParamType::Address)), + ethabi::ParamType::Array(Box::new(ethabi::ParamType::Uint(256usize))), + ethabi::ParamType::Array(Box::new(ethabi::ParamType::Uint(256usize))) + ], + ), + ], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok({ + let tuple_elements = values + .pop() + .expect("one output data should have existed") + .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_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< + ( + Vec>, + 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 GetWeightedPoolImmutableData { + const NAME: &'static str = "getWeightedPoolImmutableData"; + 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, Vec), + > for GetWeightedPoolImmutableData { + fn output( + data: &[u8], + ) -> Result< + ( + Vec>, + Vec, + Vec, + ), + String, + > { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct IncrementNonce {} + impl IncrementNonce { + const METHOD_ID: [u8; 4] = [98u8, 124u8, 220u8, 185u8]; + 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 IncrementNonce { + const NAME: &'static str = "incrementNonce"; + 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 Name {} + impl Name { + const METHOD_ID: [u8; 4] = [6u8, 253u8, 222u8, 3u8]; + 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 Name { + const NAME: &'static str = "name"; + 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 Name { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct Nonces { + pub owner: Vec, + } + impl Nonces { + const METHOD_ID: [u8; 4] = [126u8, 206u8, 190u8, 0u8]; + 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 { + 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::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 { + 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 Nonces { + const NAME: &'static str = "nonces"; + 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 Nonces { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct OnSwap { + pub request: ( + substreams::scalar::BigInt, + substreams::scalar::BigInt, + Vec, + substreams::scalar::BigInt, + substreams::scalar::BigInt, + Vec, + Vec, + ), + } + impl OnSwap { + const METHOD_ID: [u8; 4] = [114u8, 201u8, 129u8, 134u8]; + 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::Uint(8usize), + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Array(Box::new(ethabi::ParamType::Uint(256usize))), + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Address, ethabi::ParamType::Bytes + ], + ), + ], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + request: { + let tuple_elements = values + .pop() + .expect(INTERNAL_ERR) + .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 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_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[3usize] + .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[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_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + tuple_elements[6usize].clone().into_bytes().expect(INTERNAL_ERR), + ) + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::Tuple( + vec![ + ethabi::Token::Uint(ethabi::Uint::from_big_endian(match self + .request.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::Uint(ethabi::Uint::from_big_endian(match self + .request.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(),),), { let v = self.request.2.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 + .request.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::Uint(ethabi::Uint::from_big_endian(match self + .request.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::Address(ethabi::Address::from_slice(& self + .request.5)), ethabi::Token::Bytes(self.request.6.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 { + 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 OnSwap { + const NAME: &'static str = "onSwap"; + 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 OnSwap { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct Permit { + pub owner: Vec, + pub spender: Vec, + pub amount: substreams::scalar::BigInt, + pub deadline: substreams::scalar::BigInt, + pub v: substreams::scalar::BigInt, + pub r: [u8; 32usize], + pub s: [u8; 32usize], + } + impl Permit { + const METHOD_ID: [u8; 4] = [213u8, 5u8, 172u8, 207u8]; + 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::Uint(256usize), + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Uint(8usize), + ethabi::ParamType::FixedBytes(32usize), + ethabi::ParamType::FixedBytes(32usize), + ], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + owner: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + spender: 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) + }, + 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) + }, + 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) + }, + r: { + let mut result = [0u8; 32]; + let v = values + .pop() + .expect(INTERNAL_ERR) + .into_fixed_bytes() + .expect(INTERNAL_ERR); + result.copy_from_slice(&v); + result + }, + s: { + 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::Address(ethabi::Address::from_slice(&self.owner)), + ethabi::Token::Address(ethabi::Address::from_slice(&self.spender)), + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.amount.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(), + ), + ), + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.v.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.r.as_ref().to_vec()), + ethabi::Token::FixedBytes(self.s.as_ref().to_vec()), + ], + ); + 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 Permit { + const NAME: &'static str = "permit"; + 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 PermitTypehash {} + impl PermitTypehash { + const METHOD_ID: [u8; 4] = [48u8, 173u8, 248u8, 31u8]; + 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 PermitTypehash { + const NAME: &'static str = "PERMIT_TYPEHASH"; + 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 PermitTypehash { + fn output(data: &[u8]) -> Result<[u8; 32usize], String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct SupportsInterface { + pub interface_id: [u8; 4usize], + } + impl SupportsInterface { + const METHOD_ID: [u8; 4] = [1u8, 255u8, 201u8, 167u8]; + 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 { + interface_id: { + 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.interface_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 { + 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 SupportsInterface { + const NAME: &'static str = "supportsInterface"; + 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 SupportsInterface { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct Symbol {} + impl Symbol { + const METHOD_ID: [u8; 4] = [149u8, 216u8, 155u8, 65u8]; + 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 Symbol { + const NAME: &'static str = "symbol"; + 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 Symbol { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct TotalSupply {} + impl TotalSupply { + const METHOD_ID: [u8; 4] = [24u8, 22u8, 13u8, 221u8]; + 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::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 TotalSupply { + const NAME: &'static str = "totalSupply"; + 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 TotalSupply { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct Transfer { + pub to: Vec, + pub amount: substreams::scalar::BigInt, + } + impl Transfer { + const METHOD_ID: [u8; 4] = [169u8, 5u8, 156u8, 187u8]; + 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::Uint(256usize)], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + to: 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) + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::Address(ethabi::Address::from_slice(&self.to)), + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.amount.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::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 Transfer { + const NAME: &'static str = "transfer"; + 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 Transfer { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct TransferFrom { + pub from: Vec, + pub to: Vec, + pub amount: substreams::scalar::BigInt, + } + impl TransferFrom { + const METHOD_ID: [u8; 4] = [35u8, 184u8, 114u8, 221u8]; + 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::Uint(256usize), + ], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + from: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + to: 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) + }, + }) + } + pub fn encode(&self) -> Vec { + let data = ethabi::encode( + &[ + ethabi::Token::Address(ethabi::Address::from_slice(&self.from)), + ethabi::Token::Address(ethabi::Address::from_slice(&self.to)), + ethabi::Token::Uint( + ethabi::Uint::from_big_endian( + match self.amount.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::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 TransferFrom { + const NAME: &'static str = "transferFrom"; + 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 TransferFrom { + 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 Approval { + pub owner: Vec, + pub spender: Vec, + pub value: substreams::scalar::BigInt, + } + impl Approval { + const TOPIC_ID: [u8; 32] = [ + 140u8, + 91u8, + 225u8, + 229u8, + 235u8, + 236u8, + 125u8, + 91u8, + 209u8, + 79u8, + 113u8, + 66u8, + 125u8, + 30u8, + 132u8, + 243u8, + 221u8, + 3u8, + 20u8, + 192u8, + 247u8, + 178u8, + 41u8, + 30u8, + 91u8, + 32u8, + 10u8, + 200u8, + 199u8, + 195u8, + 185u8, + 37u8, + ]; + 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(256usize)], + log.data.as_ref(), + ) + .map_err(|e| format!("unable to decode log.data: {:?}", e))?; + values.reverse(); + Ok(Self { + owner: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[1usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'owner' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + spender: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[2usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'spender' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + value: { + 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 Approval { + const NAME: &'static str = "Approval"; + 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 Eip712DomainChanged {} + impl Eip712DomainChanged { + const TOPIC_ID: [u8; 32] = [ + 10u8, + 99u8, + 135u8, + 201u8, + 234u8, + 54u8, + 40u8, + 184u8, + 138u8, + 99u8, + 59u8, + 180u8, + 243u8, + 177u8, + 81u8, + 119u8, + 15u8, + 112u8, + 8u8, + 81u8, + 23u8, + 161u8, + 95u8, + 155u8, + 243u8, + 120u8, + 124u8, + 218u8, + 83u8, + 241u8, + 61u8, + 49u8, + ]; + 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 Eip712DomainChanged { + const NAME: &'static str = "EIP712DomainChanged"; + 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 Transfer { + pub from: Vec, + pub to: Vec, + pub value: substreams::scalar::BigInt, + } + impl Transfer { + const TOPIC_ID: [u8; 32] = [ + 221u8, + 242u8, + 82u8, + 173u8, + 27u8, + 226u8, + 200u8, + 155u8, + 105u8, + 194u8, + 176u8, + 104u8, + 252u8, + 55u8, + 141u8, + 170u8, + 149u8, + 43u8, + 167u8, + 241u8, + 99u8, + 196u8, + 161u8, + 22u8, + 40u8, + 245u8, + 90u8, + 77u8, + 245u8, + 35u8, + 179u8, + 239u8, + ]; + 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(256usize)], + log.data.as_ref(), + ) + .map_err(|e| format!("unable to decode log.data: {:?}", e))?; + values.reverse(); + Ok(Self { + from: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[1usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'from' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + to: ethabi::decode( + &[ethabi::ParamType::Address], + log.topics[2usize].as_ref(), + ) + .map_err(|e| { + format!( + "unable to decode param 'to' from topic of type 'address': {:?}", + e + ) + })? + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + value: { + 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 Transfer { + const NAME: &'static str = "Transfer"; + 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-v3/src/abi/weighted_pool_factory_contract.rs b/substreams/ethereum-balancer-v3/src/abi/weighted_pool_factory_contract.rs new file mode 100644 index 0000000..7805014 --- /dev/null +++ b/substreams/ethereum-balancer-v3/src/abi/weighted_pool_factory_contract.rs @@ -0,0 +1,2022 @@ +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<(Vec, substreams::scalar::BigInt, Vec, bool)>, + pub normalized_weights: Vec, + pub role_accounts: (Vec, Vec, Vec), + pub swap_fee_percentage: substreams::scalar::BigInt, + pub pool_hooks_contract: Vec, + pub enable_donation: bool, + pub disable_unbalanced_liquidity: bool, + pub salt: [u8; 32usize], + } + impl Create { + const METHOD_ID: [u8; 4] = [254u8, 212u8, 205u8, 218u8]; + 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::Tuple( + vec![ + ethabi::ParamType::Address, ethabi::ParamType::Uint(8usize), + ethabi::ParamType::Address, ethabi::ParamType::Bool + ], + ), + ), + ), + ethabi::ParamType::Array( + Box::new(ethabi::ParamType::Uint(256usize)), + ), + ethabi::ParamType::Tuple( + vec![ + ethabi::ParamType::Address, ethabi::ParamType::Address, + ethabi::ParamType::Address + ], + ), + ethabi::ParamType::Uint(256usize), + ethabi::ParamType::Address, + ethabi::ParamType::Bool, + ethabi::ParamType::Bool, + 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| { + let tuple_elements = inner.into_tuple().expect(INTERNAL_ERR); + ( + tuple_elements[0usize] + .clone() + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + { + 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_bool() + .expect(INTERNAL_ERR), + ) + }) + .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(), + role_accounts: { + 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_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + tuple_elements[2usize] + .clone() + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + ) + }, + 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) + }, + pool_hooks_contract: values + .pop() + .expect(INTERNAL_ERR) + .into_address() + .expect(INTERNAL_ERR) + .as_bytes() + .to_vec(), + enable_donation: values + .pop() + .expect(INTERNAL_ERR) + .into_bool() + .expect(INTERNAL_ERR), + disable_unbalanced_liquidity: values + .pop() + .expect(INTERNAL_ERR) + .into_bool() + .expect(INTERNAL_ERR), + 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::Tuple( + vec![ + ethabi::Token::Address(ethabi::Address::from_slice(& inner + .0)), + 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::Address(ethabi::Address::from_slice(& inner + .2)), ethabi::Token::Bool(inner.3.clone()) + ], + )) + .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) + }, + ethabi::Token::Tuple( + vec![ + ethabi::Token::Address(ethabi::Address::from_slice(& self + .role_accounts.0)), + ethabi::Token::Address(ethabi::Address::from_slice(& self + .role_accounts.1)), + ethabi::Token::Address(ethabi::Address::from_slice(& self + .role_accounts.2)) + ], + ), + 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.pool_hooks_contract), + ), + ethabi::Token::Bool(self.enable_donation.clone()), + ethabi::Token::Bool(self.disable_unbalanced_liquidity.clone()), + 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 GetDefaultLiquidityManagement {} + impl GetDefaultLiquidityManagement { + const METHOD_ID: [u8; 4] = [25u8, 58u8, 213u8, 15u8]; + 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, bool, bool, bool), String> { + Self::output(call.return_data.as_ref()) + } + pub fn output(data: &[u8]) -> Result<(bool, bool, bool, bool), String> { + let mut values = ethabi::decode( + &[ + ethabi::ParamType::Tuple( + vec![ + ethabi::ParamType::Bool, ethabi::ParamType::Bool, + ethabi::ParamType::Bool, ethabi::ParamType::Bool + ], + ), + ], + data.as_ref(), + ) + .map_err(|e| format!("unable to decode output data: {:?}", e))?; + Ok({ + let tuple_elements = values + .pop() + .expect("one output data should have existed") + .into_tuple() + .expect(INTERNAL_ERR); + ( + tuple_elements[0usize].clone().into_bool().expect(INTERNAL_ERR), + tuple_elements[1usize].clone().into_bool().expect(INTERNAL_ERR), + tuple_elements[2usize].clone().into_bool().expect(INTERNAL_ERR), + tuple_elements[3usize].clone().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<(bool, bool, bool, bool)> { + 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 GetDefaultLiquidityManagement { + const NAME: &'static str = "getDefaultLiquidityManagement"; + 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, bool, bool, bool)> + for GetDefaultLiquidityManagement { + fn output(data: &[u8]) -> Result<(bool, bool, bool, bool), String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetDefaultPoolHooksContract {} + impl GetDefaultPoolHooksContract { + const METHOD_ID: [u8; 4] = [236u8, 136u8, 128u8, 97u8]; + 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 GetDefaultPoolHooksContract { + const NAME: &'static str = "getDefaultPoolHooksContract"; + 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 GetDefaultPoolHooksContract { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetDeploymentAddress { + pub constructor_args: Vec, + pub salt: [u8; 32usize], + } + impl GetDeploymentAddress { + const METHOD_ID: [u8; 4] = [68u8, 246u8, 254u8, 199u8]; + 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::Bytes, ethabi::ParamType::FixedBytes(32usize)], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + constructor_args: values + .pop() + .expect(INTERNAL_ERR) + .into_bytes() + .expect(INTERNAL_ERR), + 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::Bytes(self.constructor_args.clone()), + 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 GetDeploymentAddress { + const NAME: &'static str = "getDeploymentAddress"; + 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 GetDeploymentAddress { + fn output(data: &[u8]) -> Result, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetNewPoolPauseWindowEndTime {} + impl GetNewPoolPauseWindowEndTime { + const METHOD_ID: [u8; 4] = [219u8, 3u8, 94u8, 188u8]; + 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::Uint(32usize)], + 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 GetNewPoolPauseWindowEndTime { + const NAME: &'static str = "getNewPoolPauseWindowEndTime"; + 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 GetNewPoolPauseWindowEndTime { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetOriginalPauseWindowEndTime {} + impl GetOriginalPauseWindowEndTime { + const METHOD_ID: [u8; 4] = [233u8, 213u8, 110u8, 25u8]; + 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::Uint(32usize)], + 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 GetOriginalPauseWindowEndTime { + const NAME: &'static str = "getOriginalPauseWindowEndTime"; + 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 GetOriginalPauseWindowEndTime { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetPauseWindowDuration {} + impl GetPauseWindowDuration { + const METHOD_ID: [u8; 4] = [120u8, 218u8, 128u8, 203u8]; + 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::Uint(32usize)], + 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 GetPauseWindowDuration { + const NAME: &'static str = "getPauseWindowDuration"; + 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 GetPauseWindowDuration { + fn output(data: &[u8]) -> Result { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetPoolCount {} + impl GetPoolCount { + const METHOD_ID: [u8; 4] = [142u8, 236u8, 93u8, 112u8]; + 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::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 GetPoolCount { + const NAME: &'static str = "getPoolCount"; + 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 GetPoolCount { + fn output(data: &[u8]) -> Result { + 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 GetPools {} + impl GetPools { + const METHOD_ID: [u8; 4] = [103u8, 58u8, 42u8, 31u8]; + 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::Array(Box::new(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_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + inner.into_address().expect(INTERNAL_ERR).as_bytes().to_vec() + }) + .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 GetPools { + const NAME: &'static str = "getPools"; + 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 GetPools { + fn output(data: &[u8]) -> Result>, String> { + Self::output(data) + } + } + #[derive(Debug, Clone, PartialEq)] + pub struct GetPoolsInRange { + pub start: substreams::scalar::BigInt, + pub count: substreams::scalar::BigInt, + } + impl GetPoolsInRange { + const METHOD_ID: [u8; 4] = [83u8, 167u8, 47u8, 126u8]; + 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(256usize), + ethabi::ParamType::Uint(256usize), + ], + maybe_data.unwrap(), + ) + .map_err(|e| format!("unable to decode call.input: {:?}", e))?; + values.reverse(); + Ok(Self { + start: { + 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) + }, + count: { + 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.start.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.count.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::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_array() + .expect(INTERNAL_ERR) + .into_iter() + .map(|inner| { + inner.into_address().expect(INTERNAL_ERR).as_bytes().to_vec() + }) + .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 GetPoolsInRange { + const NAME: &'static str = "getPoolsInRange"; + 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 GetPoolsInRange { + 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-v3/src/lib.rs b/substreams/ethereum-balancer-v3/src/lib.rs new file mode 100644 index 0000000..27bd15a --- /dev/null +++ b/substreams/ethereum-balancer-v3/src/lib.rs @@ -0,0 +1,3 @@ +mod abi; +mod modules; +mod pool_factories; diff --git a/substreams/ethereum-balancer-v3/src/modules.rs b/substreams/ethereum-balancer-v3/src/modules.rs new file mode 100644 index 0000000..42361ec --- /dev/null +++ b/substreams/ethereum-balancer-v3/src/modules.rs @@ -0,0 +1,541 @@ +use crate::{ + abi::vault_contract::{ + events::{LiquidityAdded, LiquidityRemoved, PoolPausedStateChanged, Swap}, + functions::{Erc4626BufferWrapOrUnwrap, SendTo, Settle}, + }, + pool_factories, +}; +use anyhow::Result; +use itertools::Itertools; +use keccak_hash::keccak; +use std::collections::HashMap; +use substreams::{ + hex, log, + pb::substreams::StoreDeltas, + store::{ + StoreAddBigInt, StoreGet, StoreGetInt64, StoreGetProto, StoreNew, StoreSetIfNotExists, + StoreSetIfNotExistsInt64, StoreSetIfNotExistsProto, + }, +}; +use substreams_ethereum::{ + pb::eth::{self, v2::StorageChange}, + Event, Function, +}; +use tycho_substreams::{ + attributes::json_deserialize_address_list, balances::aggregate_balances_changes, + block_storage::get_block_storage_changes, contract::extract_contract_changes_builder, + entrypoint::create_entrypoint, models::entry_point_params::TraceData, prelude::*, +}; + +pub const VAULT_ADDRESS: &[u8] = &hex!("bA1333333333a1BA1108E8412f11850A5C319bA9"); +pub const VAULT_EXTENSION_ADDRESS: &[u8; 20] = &hex!("0E8B07657D719B86e06bF0806D6729e3D528C9A9"); +pub const BATCH_ROUTER_ADDRESS: &[u8; 20] = &hex!("136f1efcc3f8f88516b9e94110d56fdbfb1778d1"); +pub const PERMIT_2_ADDRESS: &[u8; 20] = &hex!("000000000022D473030F116dDEE9F6B43aC78BA3"); + +#[substreams::handlers::map] +pub fn map_components(block: eth::v2::Block) -> Result { + let mut tx_components = Vec::new(); + for tx in block.transactions() { + let mut components = Vec::new(); + for (log, call) in tx.logs_with_calls() { + if let Some(component) = + pool_factories::address_map(log.address.as_slice(), log, call.call) + { + components.push(component); + } + } + if !components.is_empty() { + tx_components.push(TransactionProtocolComponents { tx: Some(tx.into()), components }); + } + } + Ok(BlockTransactionProtocolComponents { tx_components }) +} + +/// Simply stores the `ProtocolComponent`s with the pool address as the key and the pool id as value +#[substreams::handlers::store] +pub fn store_components( + map: BlockTransactionProtocolComponents, + store: StoreSetIfNotExistsProto, +) { + map.tx_components + .into_iter() + .for_each(|tx_pc| { + tx_pc + .components + .into_iter() + .for_each(|pc| store.set_if_not_exists(0, format!("pool:{0}", &pc.id), &pc)) + }); +} + +/// Set of token that are used by BalancerV3. This is used to filter out account balances updates +/// for unknown tokens. +#[substreams::handlers::store] +pub fn store_token_set(map: BlockTransactionProtocolComponents, store: StoreSetIfNotExistsInt64) { + map.tx_components + .into_iter() + .for_each(|tx_pc| { + tx_pc + .components + .into_iter() + .for_each(|pc| { + pc.tokens + .into_iter() + .for_each(|token| store.set_if_not_exists(0, hex::encode(token), &1)) + }) + }); +} + +#[substreams::handlers::map] +pub fn map_relative_balances( + block: eth::v2::Block, + store: StoreGetProto, +) -> Result { + let balance_deltas = block + .logs() + .filter(|log| log.address() == VAULT_ADDRESS) + .flat_map(|vault_log| { + let mut deltas = Vec::new(); + + if let Some(Swap { pool, token_in, token_out, amount_in, amount_out, .. }) = + Swap::match_and_decode(vault_log.log) + { + let component_id = format!("0x{}", hex::encode(pool)); + log::info!( + "swap at component id: {:?} with key: {:?}", + component_id, + format!("pool:{}", &component_id) + ); + + if store + .get_last(format!("pool:{}", &component_id)) + .is_some() + { + deltas.extend_from_slice(&[ + BalanceDelta { + ord: vault_log.ordinal(), + tx: Some(vault_log.receipt.transaction.into()), + token: token_in.to_vec(), + delta: amount_in.to_signed_bytes_be(), + component_id: component_id.as_bytes().to_vec(), + }, + BalanceDelta { + ord: vault_log.ordinal(), + tx: Some(vault_log.receipt.transaction.into()), + token: token_out.to_vec(), + delta: amount_out.neg().to_signed_bytes_be(), + component_id: component_id.as_bytes().to_vec(), + }, + ]); + } + } + if let Some(LiquidityAdded { pool, amounts_added_raw, .. }) = + LiquidityAdded::match_and_decode(vault_log.log) + { + let component_id = format!("0x{}", hex::encode(pool)); + if let Some(component) = store.get_last(format!("pool:{}", &component_id)) { + if component.tokens.len() != amounts_added_raw.len() { + panic!( + "liquidity added to pool with different number of tokens than expected" + ); + } + log::info!( + "liquidity added at component id: {:?} with key: {:?} with tokens: {:?}", + component_id, + format!("pool:{}", &component_id), + component.tokens + ); + let deltas_from_added_liquidity = amounts_added_raw + .into_iter() + .zip(component.tokens.iter()) + .map(|(amount, token)| BalanceDelta { + ord: vault_log.ordinal(), + tx: Some(vault_log.receipt.transaction.into()), + token: token.to_vec(), + delta: amount.to_signed_bytes_be(), + component_id: component_id.as_bytes().to_vec(), + }) + .collect::>(); + deltas.extend_from_slice(&deltas_from_added_liquidity); + } + } + if let Some(LiquidityRemoved { pool, amounts_removed_raw, .. }) = + LiquidityRemoved::match_and_decode(vault_log.log) + { + let component_id = format!("0x{}", hex::encode(pool)); + log::info!( + "liquidity removed at component id: {:?} with key: {:?}", + component_id, + format!("pool:{}", &component_id) + ); + if let Some(component) = store.get_last(format!("pool:{}", &component_id)) { + if component.tokens.len() != amounts_removed_raw.len() { + panic!( + "liquidity removed from pool with different number of tokens than expected" + ); + } + let deltas_from_removed_liquidity = amounts_removed_raw + .into_iter() + .zip(component.tokens.iter()) + .map(|(amount, token)| BalanceDelta { + ord: vault_log.ordinal(), + tx: Some(vault_log.receipt.transaction.into()), + token: token.to_vec(), + delta: amount.neg().to_signed_bytes_be(), + component_id: component_id.as_bytes().to_vec(), + }) + .collect::>(); + deltas.extend_from_slice(&deltas_from_removed_liquidity); + } + } + + 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_changes` +/// map. Each block of code will extend the `TransactionChanges` 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 +/// `BlockChanges` is ordered by transactions properly. +#[substreams::handlers::map] +pub fn map_protocol_changes( + block: eth::v2::Block, + grouped_components: BlockTransactionProtocolComponents, + deltas: BlockBalanceDeltas, + components_store: StoreGetProto, + tokens_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_changes: HashMap<_, TransactionChangesBuilder> = HashMap::new(); + + // Handle pool pause state changes + block + .logs() + .filter(|log| log.address() == VAULT_ADDRESS) + .for_each(|log| { + if let Some(PoolPausedStateChanged { pool, paused }) = + PoolPausedStateChanged::match_and_decode(log) + { + let component_id = format!("0x{}", hex::encode(&pool)); + let tx: Transaction = log.receipt.transaction.into(); + if components_store + .get_last(format!("pool:{}", &component_id)) + .is_some() + { + let builder = transaction_changes + .entry(tx.index) + .or_insert_with(|| TransactionChangesBuilder::new(&tx)); + + let entity_change = EntityChanges { + component_id, + attributes: vec![Attribute { + name: "paused".to_string(), + value: vec![1u8], + change: if paused { + ChangeType::Creation.into() + } else { + ChangeType::Deletion.into() + }, + }], + }; + builder.add_entity_change(&entity_change); + } + } + }); + + // `ProtocolComponents` are gathered from `map_pools_created` which just need a bit of work to + // convert into `TransactionChanges` + let default_attributes = vec![ + Attribute { + // TODO: remove this and track account_balances instead + name: "balance_owner".to_string(), + value: VAULT_ADDRESS.to_vec(), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "stateless_contract_addr_0".into(), + value: address_to_bytes_with_0x(VAULT_EXTENSION_ADDRESS), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "stateless_contract_addr_1".into(), + value: address_to_bytes_with_0x(BATCH_ROUTER_ADDRESS), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "stateless_contract_addr_2".into(), + value: address_to_bytes_with_0x(PERMIT_2_ADDRESS), + change: ChangeType::Creation.into(), + }, + Attribute { + name: "update_marker".to_string(), + value: vec![1u8], + change: ChangeType::Creation.into(), + }, + ]; + grouped_components + .tx_components + .iter() + .for_each(|tx_component| { + // initialise builder if not yet present for this tx + let tx = tx_component.tx.as_ref().unwrap(); + let builder = transaction_changes + .entry(tx.index) + .or_insert_with(|| TransactionChangesBuilder::new(tx)); + + // iterate over individual components created within this tx + tx_component + .components + .iter() + .for_each(|component| { + let rate_providers = component + .static_att + .iter() + .find(|att| att.name == "rate_providers") + .map(|att| json_deserialize_address_list(&att.value)); + + if let Some(rate_providers) = rate_providers { + for rate_provider in rate_providers { + let trace_data = TraceData::Rpc(RpcTraceData { + caller: None, + calldata: hex::decode("679aefce").unwrap(), // getRate() + }); + let (entrypoint, entrypoint_params) = create_entrypoint( + rate_provider, + "getRate()".to_string(), + component.id.clone(), + trace_data, + ); + builder.add_entrypoint(&entrypoint); + builder.add_entrypoint_params(&entrypoint_params); + } + } + + builder.add_protocol_component(component); + let entity_change = EntityChanges { + component_id: component.id.clone(), + attributes: default_attributes.clone(), + }; + builder.add_entity_change(&entity_change) + }); + }); + + // 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) + .iter() + .for_each(|(_, (tx, balances))| { + let builder = transaction_changes + .entry(tx.index) + .or_insert_with(|| TransactionChangesBuilder::new(tx)); + + balances + .values() + .for_each(|token_bc_map| { + token_bc_map.values().for_each(|bc| { + builder.add_balance_change(bc); + }) + }); + }); + + // Extract and insert any storage changes that happened for any of the components. + extract_contract_changes_builder( + &block, + |addr| { + components_store + .get_last(format!("pool:0x{0}", hex::encode(addr))) + .is_some() || + addr.eq(VAULT_ADDRESS) + }, + &mut transaction_changes, + ); + + // Extract token balances for balancer v3 vault + block + .transaction_traces + .iter() + .for_each(|tx| { + let vault_balance_change_per_tx = + get_vault_reserves(tx, &components_store, &tokens_store); + + if !vault_balance_change_per_tx.is_empty() { + let tycho_tx = Transaction::from(tx); + let builder = transaction_changes + .entry(tx.index.into()) + .or_insert_with(|| TransactionChangesBuilder::new(&tycho_tx)); + + let mut vault_contract_tlv_changes = + InterimContractChange::new(VAULT_ADDRESS, false); + for (token_addr, reserve_value) in vault_balance_change_per_tx { + vault_contract_tlv_changes.upsert_token_balance( + token_addr.as_slice(), + reserve_value.value.as_slice(), + ); + } + builder.add_contract_changes(&vault_contract_tlv_changes); + } + }); + + transaction_changes + .iter_mut() + .for_each(|(_, change)| { + // this indirection is necessary due to borrowing rules. + let addresses = change + .changed_contracts() + .map(|e| e.to_vec()) + .collect::>(); + + addresses + .into_iter() + .for_each(|address| { + if address != VAULT_ADDRESS { + // We reconstruct the component_id from the address here + let id = components_store + .get_last(format!("pool:0x{}", hex::encode(address))) + .map(|c| c.id) + .unwrap(); // Shouldn't happen because we filter by known components + // in `extract_contract_changes_builder` + change.mark_component_as_updated(&id); + } + }) + }); + + let block_storage_changes = get_block_storage_changes(&block); + + // Process all `transaction_changes` for final output in the `BlockChanges`, + // sorted by transaction index (the key). + Ok(BlockChanges { + block: Some((&block).into()), + changes: transaction_changes + .drain() + .sorted_unstable_by_key(|(index, _)| *index) + .filter_map(|(_, builder)| builder.build()) + .collect::>(), + storage_changes: block_storage_changes, + }) +} + +/// Converts address bytes into a Vec containing a leading `0x`. +fn address_to_bytes_with_0x(address: &[u8; 20]) -> Vec { + address_to_string_with_0x(address).into_bytes() +} + +/// Converts address bytes into a string containing a leading `0x`. +fn address_to_string_with_0x(address: &[u8]) -> String { + format!("0x{}", hex::encode(address)) +} + +// function needed to match reservesOf in vault storage, which by definition +// they should always be equal to the `token.balanceOf(this)` except during unlock +fn get_vault_reserves( + transaction: ð::v2::TransactionTrace, + store: &StoreGetProto, + token_store: &StoreGetInt64, +) -> HashMap, ReserveValue> { + // reservesOf mapping for the current block Address -> Balance + let mut reserves_of = HashMap::new(); + transaction + .calls + .iter() + .filter(|call| !call.state_reverted) + .filter(|call| call.address == VAULT_ADDRESS) + .for_each(|call| { + if let Some(Settle { token, .. }) = Settle::match_and_decode(call) { + for change in &call.storage_changes { + add_change_if_accounted( + &mut reserves_of, + change, + token.as_slice(), + token_store, + ); + } + } + if let Some(SendTo { token, .. }) = SendTo::match_and_decode(call) { + for change in &call.storage_changes { + add_change_if_accounted( + &mut reserves_of, + change, + token.as_slice(), + token_store, + ); + } + } + if let Some(Erc4626BufferWrapOrUnwrap { params }) = + Erc4626BufferWrapOrUnwrap::match_and_decode(call) + { + for change in &call.storage_changes { + let wrapped_token = params.2.clone(); + let component_id = format!("0x{}", hex::encode(&wrapped_token)); + if let Some(component) = store.get_last(component_id) { + let underlying_token = component.tokens[1].clone(); + add_change_if_accounted( + &mut reserves_of, + change, + wrapped_token.as_slice(), + token_store, + ); + add_change_if_accounted( + &mut reserves_of, + change, + underlying_token.as_slice(), + token_store, + ); + } + } + } + }); + reserves_of +} + +struct ReserveValue { + ordinal: u64, + value: Vec, +} + +fn add_change_if_accounted( + reserves_of: &mut HashMap, ReserveValue>, + change: &StorageChange, + token_address: &[u8], + token_store: &StoreGetInt64, +) { + let slot_key = get_storage_key_for_token(token_address); + // record changes happening on vault contract at reserves_of storage key + if change.key == slot_key && token_store.has_last(hex::encode(token_address)) { + reserves_of + .entry(token_address.to_vec()) + .and_modify(|v| { + if v.ordinal < change.ordinal { + v.value = change.new_value.clone(); + v.ordinal = change.ordinal; + } + }) + .or_insert(ReserveValue { value: change.new_value.clone(), ordinal: change.ordinal }); + } +} + +// token_addr -> keccak256(abi.encode(token_address, 8)) as 8 is the order in which reserves of are +// declared +fn get_storage_key_for_token(token_address: &[u8]) -> Vec { + let mut input = [0u8; 64]; + input[12..32].copy_from_slice(token_address); + input[63] = 8u8; + let result = keccak(input.as_slice()) + .as_bytes() + .to_vec(); + result +} diff --git a/substreams/ethereum-balancer-v3/src/pool_factories.rs b/substreams/ethereum-balancer-v3/src/pool_factories.rs new file mode 100644 index 0000000..d5bc340 --- /dev/null +++ b/substreams/ethereum-balancer-v3/src/pool_factories.rs @@ -0,0 +1,119 @@ +use crate::{abi, modules::VAULT_ADDRESS}; +use abi::{ + stable_pool_factory_contract::{ + events::PoolCreated as StablePoolCreated, functions::Create as StablePoolCreate, + }, + weighted_pool_factory_contract::{ + events::PoolCreated as WeightedPoolCreated, functions::Create as WeightedPoolCreate, + }, +}; +use substreams::{hex, scalar::BigInt}; +use substreams_ethereum::{ + pb::eth::v2::{Call, Log}, + Event, Function, +}; +use tycho_substreams::{ + attributes::{json_serialize_address_list, json_serialize_bigint_list}, + prelude::*, +}; + +// Token config: (token_address, rate, rate_provider_address, is_exempt_from_yield_fees) +type TokenConfig = Vec<(Vec, substreams::scalar::BigInt, Vec, bool)>; + +pub fn collect_rate_providers(tokens: &TokenConfig) -> Vec> { + tokens + .iter() + .filter(|token| token.1 == BigInt::from(1)) // WITH_RATE == 1 + .map(|token| token.2.clone()) + .collect::>() +} + +pub fn address_map( + pool_factory_address: &[u8], + log: &Log, + call: &Call, +) -> Option { + match *pool_factory_address { + hex!("201efd508c8DfE9DE1a13c2452863A78CB2a86Cc") => { + let WeightedPoolCreate { + tokens: token_config, + normalized_weights, + swap_fee_percentage, + .. + } = WeightedPoolCreate::match_and_decode(call)?; + let WeightedPoolCreated { pool } = WeightedPoolCreated::match_and_decode(log)?; + let rate_providers = collect_rate_providers(&token_config); + + // TODO: to add "buffers" support for boosted pools, we need to add the unwrapped + // version of all ERC4626 tokens to the pool tokens list. Skipped for now - we need + // to test that the adapter supports it correctly and ERC4626 overwrites are handled + // correctly in simulation. + let tokens = token_config + .into_iter() + .map(|t| t.0) + .collect::>(); + + let normalized_weights_bytes = + json_serialize_bigint_list(normalized_weights.as_slice()); + let fee_bytes = swap_fee_percentage.to_signed_bytes_be(); + let rate_providers_bytes = json_serialize_address_list(rate_providers.as_slice()); + + let mut attributes = vec![ + ("pool_type", "WeightedPoolFactory".as_bytes()), + ("normalized_weights", &normalized_weights_bytes), + ("fee", &fee_bytes), + ("manual_updates", &[1u8]), + ]; + + if !rate_providers.is_empty() { + attributes.push(("rate_providers", &rate_providers_bytes)); + } + + Some( + ProtocolComponent::new(&format!("0x{}", hex::encode(&pool))) + .with_contracts(&[pool, VAULT_ADDRESS.to_vec()]) + .with_tokens(tokens.as_slice()) + .with_attributes(&attributes) + .as_swap_type("balancer_v3_pool", ImplementationType::Vm), + ) + } + hex!("B9d01CA61b9C181dA1051bFDd28e1097e920AB14") => { + let StablePoolCreate { tokens: token_config, swap_fee_percentage, .. } = + StablePoolCreate::match_and_decode(call)?; + let StablePoolCreated { pool } = StablePoolCreated::match_and_decode(log)?; + let rate_providers = collect_rate_providers(&token_config); + + // TODO: to add "buffers" support for boosted pools, we need to add the unwrapped + // version of all ERC4626 tokens to the pool tokens list. Skipped for now - we need + // to test that the adapter supports it correctly and ERC4626 overwrites are handled + // correctly in simulation. + let tokens = token_config + .into_iter() + .map(|t| t.0) + .collect::>(); + + let fee_bytes = swap_fee_percentage.to_signed_bytes_be(); + let rate_providers_bytes = json_serialize_address_list(rate_providers.as_slice()); + + let mut attributes = vec![ + ("pool_type", "StablePoolFactory".as_bytes()), + ("bpt", &pool), + ("fee", &fee_bytes), + ("manual_updates", &[1u8]), + ]; + + if !rate_providers.is_empty() { + attributes.push(("rate_providers", &rate_providers_bytes)); + } + + Some( + ProtocolComponent::new(&format!("0x{}", hex::encode(&pool))) + .with_contracts(&[pool.to_owned(), VAULT_ADDRESS.to_vec()]) + .with_tokens(tokens.as_slice()) + .with_attributes(&attributes) + .as_swap_type("balancer_v3_pool", ImplementationType::Vm), + ) + } + _ => None, + } +} diff --git a/substreams/ethereum-balancer-v3/substreams.yaml b/substreams/ethereum-balancer-v3/substreams.yaml new file mode 100644 index 0000000..b771e35 --- /dev/null +++ b/substreams/ethereum-balancer-v3/substreams.yaml @@ -0,0 +1,78 @@ +specVersion: v0.1.0 +package: + name: "ethereum_balancer_v3" + version: v0.4.0 + +protobuf: + files: + - tycho/evm/v1/vm.proto + - tycho/evm/v1/common.proto + - tycho/evm/v1/utils.proto + importPaths: + - ../../proto + excludePaths: + - sf/substreams + - google + +binaries: + default: + type: wasm/rust-v1 + file: ../target/wasm32-unknown-unknown/release/ethereum_balancer_v3.wasm + +modules: + - name: map_components + kind: map + initialBlock: 21332121 + inputs: + - source: sf.ethereum.type.v2.Block + output: + type: proto:tycho.evm.v1.BlockTransactionProtocolComponents + + - name: store_components + kind: store + initialBlock: 21332121 + updatePolicy: set_if_not_exists + valueType: proto:tycho.evm.v1.ProtocolComponents + inputs: + - map: map_components + + - name: store_token_set + kind: store + initialBlock: 21332121 + updatePolicy: set_if_not_exists + valueType: int64 + inputs: + - map: map_components + + - name: map_relative_balances + kind: map + initialBlock: 21332121 + inputs: + - source: sf.ethereum.type.v2.Block + - store: store_components + output: + type: proto:tycho.evm.v1.BlockBalanceDeltas + + - name: store_balances + kind: store + initialBlock: 21332121 + updatePolicy: add + valueType: bigint + inputs: + - map: map_relative_balances + + - name: map_protocol_changes + kind: map + initialBlock: 21332121 + inputs: + - source: sf.ethereum.type.v2.Block + - map: map_components + - map: map_relative_balances + - store: store_components + - store: store_token_set + - store: store_balances + mode: deltas # This is the key property that simplifies `BalanceChange` handling + output: + type: proto:tycho.evm.v1.BlockChanges + +network: mainnet diff --git a/substreams/rustfmt.toml b/substreams/rustfmt.toml index ef494bd..ec7b174 100644 --- a/substreams/rustfmt.toml +++ b/substreams/rustfmt.toml @@ -21,4 +21,5 @@ ignore = [ "ethereum-pancakeswap-v3/src/abi", "ethereum-uniswap-v4/src/abi", "ethereum-maverick-v2/src/abi", -] + "ethereum-balancer-v3/src/abi" +] \ No newline at end of file diff --git a/testing/src/runner/tycho.py b/testing/src/runner/tycho.py index a6cd2a1..8ba25e5 100644 --- a/testing/src/runner/tycho.py +++ b/testing/src/runner/tycho.py @@ -85,6 +85,8 @@ class TychoRunner: "--stop-block", # +2 is to make up for the cache in the index side. str(end_block + 2), + "--dci-plugin", + "rpc", ] + ( [