diff --git a/evm/foundry.toml b/evm/foundry.toml index 23cb8a0fe..fb0dfb5dd 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 000000000..8535a204c --- /dev/null +++ b/evm/src/balancer-v3/BalancerV3SwapAdapter.sol @@ -0,0 +1,157 @@ +// 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) { + 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 000000000..add59f642 --- /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 000000000..bcfb1c3ca --- /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 000000000..fa64fe90a --- /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 000000000..40eaaffa3 --- /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 000000000..3c9e33fa2 --- /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 000000000..bdcce0fe6 --- /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 000000000..521f2397a --- /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 000000000..fc30b238c --- /dev/null +++ b/evm/src/balancer-v3/manifest.yaml @@ -0,0 +1,35 @@ +# 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 + +# 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 000000000..c8328c700 --- /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 000000000..48c1a2594 --- /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 000000000..4eb5920ef --- /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 000000000..dbf027a9e --- /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 000000000..8556f476e --- /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 000000000..1d6886b0f --- /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 5ff1bbe15..c90f0e7df 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]] @@ -239,6 +239,29 @@ dependencies = [ "tycho-substreams 0.2.0 (git+https://github.com/propeller-heads/tycho-protocol-sdk.git?rev=b8aeaa3)", ] +[[package]] +name = "ethereum-balancer-v3" +version = "0.3.2" +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.0", +] + [[package]] name = "ethereum-curve" version = "0.3.2" @@ -346,7 +369,7 @@ dependencies = [ "impl-rlp", "impl-serde 0.3.2", "primitive-types 0.11.1", - "uint", + "uint 0.9.5", ] [[package]] @@ -360,7 +383,7 @@ dependencies = [ "impl-rlp", "impl-serde 0.4.0", "primitive-types 0.12.2", - "uint", + "uint 0.9.5", ] [[package]] @@ -676,6 +699,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" @@ -883,7 +916,7 @@ dependencies = [ "impl-codec", "impl-rlp", "impl-serde 0.3.2", - "uint", + "uint 0.9.5", ] [[package]] @@ -896,7 +929,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]] @@ -1638,6 +1681,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 c0e3e9725..6517e0581 100644 --- a/substreams/Cargo.toml +++ b/substreams/Cargo.toml @@ -13,6 +13,7 @@ members = [ "ethereum-template-factory", "ethereum-template-singleton", "ethereum-uniswap-v4", + "ethereum-balancer-v3", ] resolver = "2" diff --git a/substreams/crates/tycho-substreams/src/contract.rs b/substreams/crates/tycho-substreams/src/contract.rs index 599665696..f3abd21dc 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/crates/tycho-substreams/src/models.rs b/substreams/crates/tycho-substreams/src/models.rs index e41cfeb65..a99949c4e 100644 --- a/substreams/crates/tycho-substreams/src/models.rs +++ b/substreams/crates/tycho-substreams/src/models.rs @@ -52,6 +52,9 @@ impl TransactionChangesBuilder { if !change.code.is_empty() { c.set_code(&change.code) } + if !change.token_balances.is_empty() { + c.upsert_token_balances(&change.token_balances) + } }) .or_insert_with(|| { let mut c = InterimContractChange::new( @@ -61,6 +64,7 @@ impl TransactionChangesBuilder { c.upsert_slots(&change.slots); c.set_code(&change.code); c.set_balance(&change.balance); + c.upsert_token_balances(&change.token_balances); c }); } diff --git a/substreams/ethereum-balancer-v3/Cargo.lock b/substreams/ethereum-balancer-v3/Cargo.lock new file mode 100644 index 000000000..46d30eb8d --- /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 000000000..ce87be5df --- /dev/null +++ b/substreams/ethereum-balancer-v3/Cargo.toml @@ -0,0 +1,34 @@ +[package] +name = "ethereum-balancer-v3" +version = "0.3.2" +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 = { path = "../crates/tycho-substreams" } +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 000000000..0f1de6db4 --- /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** +- _weigthed_pool_factory_ at **0x201efd508c8dfe9de1a13c2452863a78cb2a86cc** +- stable_pool contracts created from _stable_pool_factory_ +- weighted_pool contracts created from _weigthed_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 000000000..437802892 --- /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 000000000..2616433b0 --- /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 000000000..558877d48 --- /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 000000000..d389d91c8 --- /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/weigthed_pool_factory_contract.abi.json b/substreams/ethereum-balancer-v3/abi/weigthed_pool_factory_contract.abi.json new file mode 100644 index 000000000..d2b849a78 --- /dev/null +++ b/substreams/ethereum-balancer-v3/abi/weigthed_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 000000000..6a1c3efa4 --- /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 000000000..3c779f659 --- /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/weigthed_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/weigthed_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 000000000..5daddd3d9 --- /dev/null +++ b/substreams/ethereum-balancer-v3/integration_test.tycho.yaml @@ -0,0 +1,118 @@ +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 + +# vault address for v3 needed for the router contract +initialized_accounts: + - "0xbA1333333333a1BA1108E8412f11850A5C319bA9" + - "0x0E8B07657D719B86e06bF0806D6729e3D528C9A9" + - "0x136f1EFcC3f8f88516B9E94110D56FDBfB1778d1" + +tests: + - name: test_stable_pool_creation + start_block: 21374757 + stop_block: 21374767 + expected_components: + - id: "0xc4ce391d82d164c166df9c8336ddf84206b2f812" + tokens: + - "0x0FE906e030a44eF24CA8c7dC7B7c53A6C4F00ce9" + - "0x775F661b0bD1739349b9A2A3EF60be277c5d2D29" + static_attributes: + manual_updates: "0x01" + pool_type: "0x537461626c65506f6f6c466163746f7279" + bpt: "0xc4ce391d82d164c166df9c8336ddf84206b2f812" + erc4626: "0x01" + fee: "0x5af3107a4000" + skip_simulation: true + 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" + erc4626: "0x00" + normalized_weights: "0x5b22307830623161326263326563353030303030222c22307830326336386166306262313430303030225d" + fee: "0x038d7ea4c68000" + pool_type: "0x5765696768746564506f6f6c466163746f7279" + skip_simulation: true + creation_tx: "0xaf0f8da4b7b148f156605673c6ac56657f67c47001aadd5b3b64d6cb787daad4" + + - name: test_erc4626_pool_creation + start_block: 21375196 + stop_block: 21375206 + expected_components: + - id: "0x89BB794097234E5E930446C0CeC0ea66b35D7570" + tokens: + - "0x7bc3485026ac48b6cf9baf0a377477fff5703af8" + - "0xd4fa2d31b7968e448877f69a96de69f5de8cd23e" + static_attributes: + manual_updates: "0x01" + pool_type: "0x537461626c65506f6f6c466163746f7279" + bpt: "0x89bb794097234e5e930446c0cec0ea66b35d7570" + erc4626: "0x01" + fee: "0x2d79883d2000" + skip_simulation: true + creation_tx: "0x536baa8f18a5f9e32b08f695593f47d996a509edc886ccab6f89b001f2d2b4e4" + + - name: test_swap_g_usdc + start_block: 21389576 + stop_block: 21389676 + expected_components: + - id: "0xf91c11BA4220b7a72E1dc5E92f2b48D3fdF62726" + tokens: + - "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" + - "0x440017A1b021006d556d7fc06A54c32E42Eb745B" + static_attributes: + pool_type: "0x5765696768746564506f6f6c466163746f7279" + erc4626: "0x00" + manual_updates: "0x01" + normalized_weights: "0x5b22307830366630356235396433623230303030222c22307830366630356235396433623230303030225d" + fee: "0x0aa87bee538000" + skip_simulation: false + creation_tx: "0x50a58ca41af90029a67bc7f4305cceb1e85800246f9c559fa74d8625ddfe14ed" + + - name: test_obs_weth + start_block: 21420490 + stop_block: 21420516 + expected_components: + - id: "0x4403a2721A9A9956584dc19F553720CEf0Df35b0" + tokens: + - "0xafd9268fdfebee905f7439b12c943bc18ad293c2" + - "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2" + static_attributes: + pool_type: "0x5765696768746564506f6f6c466163746f7279" + erc4626: "0x00" + 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" + erc4626: "0x00" + 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 000000000..607444c62 --- /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 weigthed_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 000000000..053a24787 --- /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 000000000..f02c9ae7d --- /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 000000000..2c1524d13 --- /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 000000000..6692d0b80 --- /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/weigthed_pool_factory_contract.rs b/substreams/ethereum-balancer-v3/src/abi/weigthed_pool_factory_contract.rs new file mode 100644 index 000000000..7805014c1 --- /dev/null +++ b/substreams/ethereum-balancer-v3/src/abi/weigthed_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 000000000..27bd15a6f --- /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 000000000..ca54e5bc7 --- /dev/null +++ b/substreams/ethereum-balancer-v3/src/modules.rs @@ -0,0 +1,525 @@ +use crate::{ + abi::vault_contract::{ + events::{ + LiquidityAdded, LiquidityAddedToBuffer, LiquidityRemoved, LiquidityRemovedFromBuffer, + Swap, Unwrap, Wrap, + }, + 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, StoreGetProto, StoreNew, StoreSetIfNotExists, + StoreSetIfNotExistsProto, + }, +}; +use substreams_ethereum::{ + pb::eth::{self, v2::StorageChange}, + Event, Function, +}; +use tycho_substreams::{ + balances::aggregate_balances_changes, contract::extract_contract_changes_builder, 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 let Some(buffer_component) = pool_factories::buffer_map(log, tx) { + components.push(buffer_component); + } + } + 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)) + }); +} + +#[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); + } + } + if let Some(LiquidityAddedToBuffer { wrapped_token, amount_underlying, amount_wrapped, .. }) = + LiquidityAddedToBuffer::match_and_decode(vault_log.log) + { + let component_id = format!("0x{}", hex::encode(&wrapped_token)); + if let Some(ProtocolComponent{ tokens,..}) = store.get_last(format!("pool:{}", &component_id)) { + let underlying_token = tokens[1].to_owned(); + deltas.extend_from_slice(&[BalanceDelta { + ord: vault_log.ordinal(), + tx: Some(vault_log.receipt.transaction.into()), + token: wrapped_token.to_vec(), + delta: amount_wrapped.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: underlying_token.to_vec(), + delta: amount_underlying.to_signed_bytes_be(), + component_id: component_id.as_bytes().to_vec(), + }, + ]); + } + } + if let Some(LiquidityRemovedFromBuffer { wrapped_token, amount_underlying, amount_wrapped, .. }) = + LiquidityRemovedFromBuffer::match_and_decode(vault_log.log) + { + let component_id = format!("0x{}", hex::encode(&wrapped_token)); + if let Some(ProtocolComponent{ tokens,..}) = store.get_last(format!("pool:{}", &component_id)) { + let underlying_token = tokens[1].to_owned(); + deltas.extend_from_slice(&[BalanceDelta { + ord: vault_log.ordinal(), + tx: Some(vault_log.receipt.transaction.into()), + token: wrapped_token.to_vec(), + delta: amount_wrapped.neg().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: underlying_token.to_vec(), + delta: amount_underlying.neg().to_signed_bytes_be(), + component_id: component_id.as_bytes().to_vec(), + }, + ]); + } + } + if let Some(Wrap { wrapped_token, deposited_underlying, minted_shares, .. }) = Wrap::match_and_decode(vault_log.log) { + let component_id = format!("0x{}", hex::encode(&wrapped_token)); + if let Some(ProtocolComponent{ tokens,..}) = store.get_last(format!("pool:{}", &component_id)) { + let underlying_token = tokens[1].to_owned(); + deltas.extend_from_slice(&[BalanceDelta { + ord: vault_log.ordinal(), + tx: Some(vault_log.receipt.transaction.into()), + token: underlying_token.to_vec(), + delta: deposited_underlying.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: wrapped_token.to_vec(), + delta: minted_shares.to_signed_bytes_be(), + component_id: component_id.as_bytes().to_vec(), + }, + ]); + } + } + if let Some(Unwrap { wrapped_token, burned_shares, withdrawn_underlying, .. }) = Unwrap::match_and_decode(vault_log.log) { + let component_id = format!("0x{}", hex::encode(&wrapped_token)); + if let Some(ProtocolComponent{ tokens,..}) = store.get_last(format!("pool:{}", &component_id)) { + let underlying_token = tokens[1].to_owned(); + deltas.extend_from_slice(&[BalanceDelta { + ord: vault_log.ordinal(), + tx: Some(vault_log.receipt.transaction.into()), + token: underlying_token.to_vec(), + delta: withdrawn_underlying.neg().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: wrapped_token.to_vec(), + delta: burned_shares.neg().to_signed_bytes_be(), + component_id: component_id.as_bytes().to_vec(), + }, + ]); + } + } + + 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, + 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(); + + // `ProtocolComponents` are gathered from `map_pools_created` which just need a bit of work to + // convert into `TransactionChanges` + let default_attributes = vec![ + Attribute { + 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| { + 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 token balances for balancer v3 vault + block + .transaction_traces + .iter() + .for_each(|tx| { + let mut vault_contract_tlv_changes = InterimContractChange::new(VAULT_ADDRESS, false); + let tycho_tx = Transaction::from(tx); + let builder = transaction_changes + .entry(tx.index.into()) + .or_insert_with(|| TransactionChangesBuilder::new(&tycho_tx)); + let vault_balance_change_per_tx = get_vault_reserves(tx, &components_store); + 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); + }); + + // 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, + ); + + 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); + } + }) + }); + + // 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::>(), + }) +} + +/// 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, +) -> HashMap, ReserveValue> { + // reservesOf mapping for the current block Address -> Balance + let mut reserves_of = HashMap::new(); + transaction + .calls + .iter() + .filter(|call| !call.state_reverted) + .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()); + } + } + 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()); + } + } + 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()); + add_change_if_accounted( + &mut reserves_of, + change, + underlying_token.as_slice(), + ); + } + } + } + }); + reserves_of +} + +struct ReserveValue { + ordinal: u64, + value: Vec, +} + +fn add_change_if_accounted( + reserves_of: &mut HashMap, ReserveValue>, + change: &StorageChange, + token_address: &[u8], +) { + 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 && change.address == VAULT_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 000000000..f1a68f847 --- /dev/null +++ b/substreams/ethereum-balancer-v3/src/pool_factories.rs @@ -0,0 +1,120 @@ +use crate::{ + abi::{self, vault_contract::events::LiquidityAddedToBuffer}, + modules::VAULT_ADDRESS, +}; +use abi::{ + stable_pool_factory_contract::{ + events::PoolCreated as StablePoolCreated, functions::Create as StablePoolCreate, + }, + weigthed_pool_factory_contract::{ + events::PoolCreated as WeightedPoolCreated, functions::Create as WeightedPoolCreate, + }, +}; +use substreams::{hex, scalar::BigInt}; +use substreams_ethereum::{ + pb::eth::v2::{Call, Log, TransactionTrace}, + Event, Function, +}; +use tycho_substreams::{ + abi::erc20::events::Transfer, attributes::json_serialize_bigint_list, prelude::*, +}; + +type TokenConfig = Vec<(Vec, substreams::scalar::BigInt, Vec, bool)>; +pub fn check_erc4626(tokens: &TokenConfig) -> bool { + tokens + .iter() + .any(|token| token.1 == BigInt::from(1)) // WITH_RATE == 1 +} + +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 is_erc4626 = check_erc4626(&token_config); + let tokens = token_config + .into_iter() + .map(|t| t.0) + .collect::>(); + + Some( + ProtocolComponent::new(&format!("0x{}", hex::encode(&pool))) + .with_contracts(&[pool, VAULT_ADDRESS.to_vec()]) + .with_tokens(tokens.as_slice()) + .with_attributes(&[ + ("pool_type", "WeightedPoolFactory".as_bytes()), + ( + "normalized_weights", + &json_serialize_bigint_list(normalized_weights.as_slice()), + ), + ("fee", &swap_fee_percentage.to_signed_bytes_be()), + ("manual_updates", &[1u8]), + ("erc4626", &[is_erc4626 as u8]), + ]) + .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 is_erc4626 = check_erc4626(&token_config); + let tokens = token_config + .into_iter() + .map(|t| t.0) + .collect::>(); + Some( + ProtocolComponent::new(&format!("0x{}", hex::encode(&pool))) + .with_contracts(&[pool.to_owned(), VAULT_ADDRESS.to_vec()]) + .with_tokens(tokens.as_slice()) + .with_attributes(&[ + ("pool_type", "StablePoolFactory".as_bytes()), + ("bpt", &pool), + ("fee", &swap_fee_percentage.to_signed_bytes_be()), + ("manual_updates", &[1u8]), + ("erc4626", &[is_erc4626 as u8]), + ]) + .as_swap_type("balancer_v3_pool", ImplementationType::Vm), + ) + } + _ => None, + } +} + +fn find_underlying_token(tx: &TransactionTrace, underlying_amount: BigInt) -> Option> { + tx.receipt() + .logs() + .filter_map(|log| { + if let Some(Transfer { to, value, .. }) = Transfer::match_and_decode(log) { + if to == VAULT_ADDRESS && value == underlying_amount { + return Some(log.address().to_vec()); + } + } + None + }) + .next() +} + +// this adds a buffer protocol component, they are internal pool managed by balancer but they can be +// used as a vault-type component for swapping for instance USDT <-> waETHUSDT (aave wrapped USDT) +pub fn buffer_map(log: &Log, tx: &TransactionTrace) -> Option { + LiquidityAddedToBuffer::match_and_decode(log).map( + |LiquidityAddedToBuffer { wrapped_token, amount_underlying, .. }| { + let underlying_token = find_underlying_token(tx, amount_underlying).unwrap(); // must exist + ProtocolComponent::new(&format!("0x{}", hex::encode(&wrapped_token))) + .with_contracts(&[wrapped_token.to_vec(), VAULT_ADDRESS.to_vec()]) + .with_tokens(&[wrapped_token.as_slice(), underlying_token.as_slice()]) + .with_attributes(&[("pool_type", "buffer".as_bytes()), ("erc4626", &[1u8])]) + .as_swap_type("balancer_v3_pool", ImplementationType::Vm) + }, + ) +} diff --git a/substreams/ethereum-balancer-v3/substreams.yaml b/substreams/ethereum-balancer-v3/substreams.yaml new file mode 100644 index 000000000..c4899e49a --- /dev/null +++ b/substreams/ethereum-balancer-v3/substreams.yaml @@ -0,0 +1,69 @@ +specVersion: v0.1.0 +package: + name: "ethereum_balancer_v3" + version: v0.1.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: 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_balances + mode: deltas # This is the key property that simplifies `BalanceChange` handling + output: + type: proto:tycho.evm.v1.BlockChanges + +network: mainnet \ No newline at end of file diff --git a/substreams/rustfmt.toml b/substreams/rustfmt.toml index 42cdd4f14..c06f68483 100644 --- a/substreams/rustfmt.toml +++ b/substreams/rustfmt.toml @@ -19,4 +19,5 @@ ignore = [ "ethereum-uniswap-v3/src/abi", "ethereum-uniswap-v3-logs-only/src/abi", "ethereum-uniswap-v4/src/abi", -] + "ethereum-balancer-v3/src/abi" +] \ No newline at end of file