ETH Price: $3,395.60 (+1.52%)

Contract

0xA81b22966f1841E383E69393175E2cc65F0a8854
 
Transaction Hash
Method
Block
From
To
Join Pool212570602024-11-24 10:38:2330 days ago1732444703IN
0xA81b2296...65F0a8854
0 ETH0.00083297.45909068
Join Pool211926242024-11-15 10:52:5939 days ago1731667979IN
0xA81b2296...65F0a8854
0 ETH0.0013813712.3749008
Finalize211055782024-11-03 7:20:1151 days ago1730618411IN
0xA81b2296...65F0a8854
0 ETH0.00047372.78994398
Set Swap Fee211055742024-11-03 7:19:2351 days ago1730618363IN
0xA81b2296...65F0a8854
0 ETH0.000081232.38918372
Bind211055682024-11-03 7:18:1151 days ago1730618291IN
0xA81b2296...65F0a8854
0 ETH0.000419322.43752099
Bind211055652024-11-03 7:17:3551 days ago1730618255IN
0xA81b2296...65F0a8854
0 ETH0.000433662.36578882

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Block
From
To
211055452024-11-03 7:13:3551 days ago1730618015  Contract Creation0 ETH
Loading...
Loading

Similar Match Source Code
This contract matches the deployed Bytecode of the Source Code for Contract 0xcB53b8c3...E0E3DE6B9
The constructor portion of the code might be different and could alter the actual behaviour of the contract

Contract Name:
BCoWPool

Compiler Version
v0.8.25+commit.b61c2a91

Optimization Enabled:
Yes with 500 runs

Other Settings:
cancun EvmVersion
File 1 of 27 : BCoWPool.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.25;

/*

Coded for Balancer and CoW Swap with ♥ by

░██╗░░░░░░░██╗░█████╗░███╗░░██╗██████╗░███████╗██████╗░██╗░░░░░░█████╗░███╗░░██╗██████╗░
░██║░░██╗░░██║██╔══██╗████╗░██║██╔══██╗██╔════╝██╔══██╗██║░░░░░██╔══██╗████╗░██║██╔══██╗
░╚██╗████╗██╔╝██║░░██║██╔██╗██║██║░░██║█████╗░░██████╔╝██║░░░░░███████║██╔██╗██║██║░░██║
░░████╔═████║░██║░░██║██║╚████║██║░░██║██╔══╝░░██╔══██╗██║░░░░░██╔══██║██║╚████║██║░░██║
░░╚██╔╝░╚██╔╝░╚█████╔╝██║░╚███║██████╔╝███████╗██║░░██║███████╗██║░░██║██║░╚███║██████╔╝
░░░╚═╝░░░╚═╝░░░╚════╝░╚═╝░░╚══╝╚═════╝░╚══════╝╚═╝░░╚═╝╚══════╝╚═╝░░╚═╝╚═╝░░╚══╝╚═════╝░

https://defi.sucks

*/

import {BCoWConst} from './BCoWConst.sol';
import {BPool} from './BPool.sol';
import {GPv2Order} from '@cowprotocol/libraries/GPv2Order.sol';
import {IERC1271} from '@openzeppelin/contracts/interfaces/IERC1271.sol';
import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import {SafeERC20} from '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';

import {IBCoWFactory} from 'interfaces/IBCoWFactory.sol';
import {IBCoWPool} from 'interfaces/IBCoWPool.sol';
import {ISettlement} from 'interfaces/ISettlement.sol';

/**
 * @title BCoWPool
 * @notice Pool contract that holds tokens, allows to swap, add and remove liquidity.
 * @dev Inherits BPool contract functionalities, and can trade on CoW Swap Protocol.
 */
contract BCoWPool is IERC1271, IBCoWPool, BPool, BCoWConst {
  using GPv2Order for GPv2Order.Data;
  using SafeERC20 for IERC20;

  /// @inheritdoc IBCoWPool
  address public immutable VAULT_RELAYER;

  /// @inheritdoc IBCoWPool
  bytes32 public immutable SOLUTION_SETTLER_DOMAIN_SEPARATOR;

  /// @inheritdoc IBCoWPool
  ISettlement public immutable SOLUTION_SETTLER;

  /// @inheritdoc IBCoWPool
  bytes32 public immutable APP_DATA;

  constructor(
    address cowSolutionSettler,
    bytes32 appData,
    // solhint-disable-next-line no-unused-vars
    string memory name,
    // solhint-disable-next-line no-unused-vars
    string memory symbol
  ) BPool(name, symbol) {
    SOLUTION_SETTLER = ISettlement(cowSolutionSettler);
    SOLUTION_SETTLER_DOMAIN_SEPARATOR = ISettlement(cowSolutionSettler).domainSeparator();
    VAULT_RELAYER = ISettlement(cowSolutionSettler).vaultRelayer();
    APP_DATA = appData;
  }

  /// @inheritdoc IBCoWPool
  function commit(bytes32 orderHash) external _viewlock_ {
    if (msg.sender != address(SOLUTION_SETTLER)) {
      revert CommitOutsideOfSettlement();
    }
    _setLock(orderHash);
  }

  /**
   * @inheritdoc IERC1271
   * @dev this function reverts if the order hash does not match the current commitment
   */
  function isValidSignature(bytes32 orderHash, bytes memory signature) external view returns (bytes4 magicValue) {
    (GPv2Order.Data memory order) = abi.decode(signature, (GPv2Order.Data));

    if (order.appData != APP_DATA) {
      revert AppDataDoesNotMatch();
    }

    bytes32 orderHash_ = order.hash(SOLUTION_SETTLER_DOMAIN_SEPARATOR);
    if (orderHash_ != orderHash) {
      revert OrderDoesNotMatchMessageHash();
    }

    if (orderHash_ != _getLock()) {
      revert OrderDoesNotMatchCommitmentHash();
    }

    verify(order);

    // A signature is valid according to EIP-1271 if this function returns
    // its selector as the so-called "magic value".
    magicValue = this.isValidSignature.selector;
  }

  /// @inheritdoc IBCoWPool
  function verify(GPv2Order.Data memory order) public view virtual {
    Record memory inRecord = _records[address(order.buyToken)];
    Record memory outRecord = _records[address(order.sellToken)];

    if (!inRecord.bound || !outRecord.bound) {
      revert BPool_TokenNotBound();
    }
    if (order.receiver != GPv2Order.RECEIVER_SAME_AS_OWNER) {
      revert BCoWPool_ReceiverIsNotBCoWPool();
    }
    if (order.validTo > block.timestamp + MAX_ORDER_DURATION) {
      revert BCoWPool_OrderValidityTooLong();
    }
    if (order.feeAmount != 0) {
      revert BCoWPool_FeeMustBeZero();
    }
    if (order.kind != GPv2Order.KIND_SELL) {
      revert BCoWPool_InvalidOperation();
    }
    if (order.buyTokenBalance != GPv2Order.BALANCE_ERC20 || order.sellTokenBalance != GPv2Order.BALANCE_ERC20) {
      revert BCoWPool_InvalidBalanceMarker();
    }

    uint256 buyTokenBalance = order.buyToken.balanceOf(address(this));
    if (order.buyAmount > bmul(buyTokenBalance, MAX_IN_RATIO)) {
      revert BPool_TokenAmountInAboveMaxRatio();
    }

    uint256 tokenAmountOut = calcOutGivenIn({
      tokenBalanceIn: buyTokenBalance,
      tokenWeightIn: inRecord.denorm,
      tokenBalanceOut: order.sellToken.balanceOf(address(this)),
      tokenWeightOut: outRecord.denorm,
      tokenAmountIn: order.buyAmount,
      swapFee: 0
    });

    if (tokenAmountOut < order.sellAmount) {
      revert BPool_TokenAmountOutBelowMinOut();
    }
  }

  /**
   * @inheritdoc BPool
   * @dev Grants infinite approval to the vault relayer for all tokens in the
   * pool after the finalization of the setup. Also emits COWAMMPoolCreated() event.
   */
  function _afterFinalize() internal override {
    uint256 tokensLength = _tokens.length;
    for (uint256 i; i < tokensLength; i++) {
      IERC20(_tokens[i]).forceApprove(VAULT_RELAYER, type(uint256).max);
    }

    // Make the factory emit the event, to be easily indexed by off-chain agents
    // If this pool was not deployed using a bCoWFactory, this will revert and catch
    // And the event will be emitted by this contract instead
    // solhint-disable-next-line no-empty-blocks
    try IBCoWFactory(FACTORY).logBCoWPool() {}
    catch {
      emit IBCoWFactory.COWAMMPoolCreated(address(this));
    }
  }
}

File 2 of 27 : BCoWConst.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.25;

/**
 * @title BCoWConst
 * @notice Constants used in the scope of the BCoWPool contract.
 */
contract BCoWConst {
  /**
   * @notice The largest possible duration of any AMM order, starting from the
   * current block timestamp.
   * @return _maxOrderDuration The maximum order duration.
   */
  uint32 public constant MAX_ORDER_DURATION = 5 minutes;
}

File 3 of 27 : BPool.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.25;

import {BMath} from './BMath.sol';
import {BToken} from './BToken.sol';
import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
import {SafeERC20} from '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';
import {IBPool} from 'interfaces/IBPool.sol';

/**
 * @title BPool
 * @notice Pool contract that holds tokens, allows to swap, add and remove liquidity.
 */
contract BPool is BToken, BMath, IBPool {
  using SafeERC20 for IERC20;
  /// @dev BFactory address to push token exitFee to

  /// @inheritdoc IBPool
  address public immutable FACTORY;
  /// @dev Has CONTROL role
  address internal _controller;
  /// @dev Fee for swapping
  uint256 internal _swapFee;
  /// @dev Status of the pool. True if finalized, False otherwise
  bool internal _finalized;
  /// @dev Array of bound tokens
  address[] internal _tokens;
  /// @dev Metadata for each bound token
  mapping(address => Record) internal _records;
  /// @dev Sum of all token weights
  uint256 internal _totalWeight;

  /// @dev Logs the call data
  modifier _logs_() {
    emit LOG_CALL(msg.sig, msg.sender, msg.data);
    _;
  }

  /// @dev Prevents reentrancy in non-view functions
  modifier _lock_() {
    if (_getLock() != _MUTEX_FREE) {
      revert BPool_Reentrancy();
    }
    _setLock(_MUTEX_TAKEN);
    _;
    _setLock(_MUTEX_FREE);
  }

  /// @dev Throws an error when the reentrancy mutex is taken. Doesn't modify it.
  modifier _viewlock_() {
    if (_getLock() != _MUTEX_FREE) {
      revert BPool_Reentrancy();
    }
    _;
  }

  /// @dev Throws an error if pool is not finalized
  modifier _finalized_() {
    if (!_finalized) {
      revert BPool_PoolNotFinalized();
    }
    _;
  }

  /// @dev Throws an error if pool is finalized
  modifier _notFinalized_() {
    if (_finalized) {
      revert BPool_PoolIsFinalized();
    }
    _;
  }

  /**
   * @notice Throws an error if caller is not controller
   */
  modifier _controller_() {
    if (msg.sender != _controller) {
      revert BPool_CallerIsNotController();
    }
    _;
  }

  // solhint-disable-next-line no-unused-vars
  constructor(string memory name, string memory symbol) BToken(name, symbol) {
    _controller = msg.sender;
    FACTORY = msg.sender;
    _swapFee = MIN_FEE;
    _finalized = false;
  }

  /// @inheritdoc IBPool
  function setSwapFee(uint256 swapFee) external _logs_ _lock_ _controller_ _notFinalized_ {
    if (swapFee < MIN_FEE) {
      revert BPool_FeeBelowMinimum();
    }
    if (swapFee > MAX_FEE) {
      revert BPool_FeeAboveMaximum();
    }
    _swapFee = swapFee;
  }

  /// @inheritdoc IBPool
  function setController(address newController) external _logs_ _lock_ _controller_ {
    if (newController == address(0)) {
      revert BPool_AddressZero();
    }

    _controller = newController;
  }

  /// @inheritdoc IBPool
  function finalize() external _logs_ _lock_ _controller_ _notFinalized_ {
    if (_tokens.length < MIN_BOUND_TOKENS) {
      revert BPool_TokensBelowMinimum();
    }

    _finalized = true;

    _mintPoolShare(INIT_POOL_SUPPLY);
    _pushPoolShare(msg.sender, INIT_POOL_SUPPLY);
    _afterFinalize();
  }

  /// @inheritdoc IBPool
  function bind(address token, uint256 balance, uint256 denorm) external _logs_ _lock_ _controller_ _notFinalized_ {
    if (_records[token].bound) {
      revert BPool_TokenAlreadyBound();
    }
    if (_tokens.length >= MAX_BOUND_TOKENS) {
      revert BPool_TokensAboveMaximum();
    }
    if (denorm < MIN_WEIGHT) {
      revert BPool_WeightBelowMinimum();
    }
    if (denorm > MAX_WEIGHT) {
      revert BPool_WeightAboveMaximum();
    }
    if (balance < MIN_BALANCE) {
      revert BPool_BalanceBelowMinimum();
    }

    _totalWeight = badd(_totalWeight, denorm);
    if (_totalWeight > MAX_TOTAL_WEIGHT) {
      revert BPool_TotalWeightAboveMaximum();
    }

    _records[token] = Record({bound: true, index: _tokens.length, denorm: denorm});
    _tokens.push(token);

    _pullUnderlying(token, msg.sender, balance);
  }

  /// @inheritdoc IBPool
  function unbind(address token) external _logs_ _lock_ _controller_ _notFinalized_ {
    if (!_records[token].bound) {
      revert BPool_TokenNotBound();
    }

    _totalWeight = bsub(_totalWeight, _records[token].denorm);

    // Swap the token-to-unbind with the last token,
    // then delete the last token
    uint256 index = _records[token].index;
    uint256 last = _tokens.length - 1;
    _tokens[index] = _tokens[last];
    _records[_tokens[index]].index = index;
    _tokens.pop();
    _records[token] = Record({bound: false, index: 0, denorm: 0});

    _pushUnderlying(token, msg.sender, IERC20(token).balanceOf(address(this)));
  }

  /// @inheritdoc IBPool
  function joinPool(uint256 poolAmountOut, uint256[] calldata maxAmountsIn) external _logs_ _lock_ _finalized_ {
    uint256 poolTotal = totalSupply();
    uint256 ratio = bdiv(poolAmountOut, poolTotal);
    if (ratio == 0) {
      revert BPool_InvalidPoolRatio();
    }

    uint256 tokensLength = _tokens.length;
    for (uint256 i = 0; i < tokensLength; i++) {
      address t = _tokens[i];
      uint256 bal = IERC20(t).balanceOf(address(this));
      uint256 tokenAmountIn = bmul(ratio, bal);
      if (tokenAmountIn == 0) {
        revert BPool_InvalidTokenAmountIn();
      }
      if (tokenAmountIn > maxAmountsIn[i]) {
        revert BPool_TokenAmountInAboveMaxAmountIn();
      }
      emit LOG_JOIN(msg.sender, t, tokenAmountIn);
      _pullUnderlying(t, msg.sender, tokenAmountIn);
    }
    _mintPoolShare(poolAmountOut);
    _pushPoolShare(msg.sender, poolAmountOut);
  }

  /// @inheritdoc IBPool
  function exitPool(uint256 poolAmountIn, uint256[] calldata minAmountsOut) external _logs_ _lock_ _finalized_ {
    uint256 poolTotal = totalSupply();
    uint256 exitFee = bmul(poolAmountIn, EXIT_FEE);
    uint256 pAiAfterExitFee = bsub(poolAmountIn, exitFee);
    uint256 ratio = bdiv(pAiAfterExitFee, poolTotal);
    if (ratio == 0) {
      revert BPool_InvalidPoolRatio();
    }

    _pullPoolShare(msg.sender, poolAmountIn);
    _pushPoolShare(FACTORY, exitFee);
    _burnPoolShare(pAiAfterExitFee);

    uint256 tokensLength = _tokens.length;
    for (uint256 i = 0; i < tokensLength; i++) {
      address t = _tokens[i];
      uint256 bal = IERC20(t).balanceOf(address(this));
      uint256 tokenAmountOut = bmul(ratio, bal);
      if (tokenAmountOut == 0) {
        revert BPool_InvalidTokenAmountOut();
      }
      if (tokenAmountOut < minAmountsOut[i]) {
        revert BPool_TokenAmountOutBelowMinAmountOut();
      }
      emit LOG_EXIT(msg.sender, t, tokenAmountOut);
      _pushUnderlying(t, msg.sender, tokenAmountOut);
    }
  }

  /// @inheritdoc IBPool
  function swapExactAmountIn(
    address tokenIn,
    uint256 tokenAmountIn,
    address tokenOut,
    uint256 minAmountOut,
    uint256 maxPrice
  ) external _logs_ _lock_ _finalized_ returns (uint256 tokenAmountOut, uint256 spotPriceAfter) {
    if (!_records[tokenIn].bound) {
      revert BPool_TokenNotBound();
    }
    if (!_records[tokenOut].bound) {
      revert BPool_TokenNotBound();
    }

    Record storage inRecord = _records[address(tokenIn)];
    Record storage outRecord = _records[address(tokenOut)];

    uint256 tokenInBalance = IERC20(tokenIn).balanceOf(address(this));
    uint256 tokenOutBalance = IERC20(tokenOut).balanceOf(address(this));

    if (tokenAmountIn > bmul(tokenInBalance, MAX_IN_RATIO)) {
      revert BPool_TokenAmountInAboveMaxRatio();
    }

    uint256 spotPriceBefore =
      calcSpotPrice(tokenInBalance, inRecord.denorm, tokenOutBalance, outRecord.denorm, _swapFee);
    if (spotPriceBefore > maxPrice) {
      revert BPool_SpotPriceAboveMaxPrice();
    }

    tokenAmountOut =
      calcOutGivenIn(tokenInBalance, inRecord.denorm, tokenOutBalance, outRecord.denorm, tokenAmountIn, _swapFee);
    if (tokenAmountOut < minAmountOut) {
      revert BPool_TokenAmountOutBelowMinOut();
    }

    tokenInBalance = badd(tokenInBalance, tokenAmountIn);
    tokenOutBalance = bsub(tokenOutBalance, tokenAmountOut);

    spotPriceAfter = calcSpotPrice(tokenInBalance, inRecord.denorm, tokenOutBalance, outRecord.denorm, _swapFee);
    if (spotPriceAfter < spotPriceBefore) {
      revert BPool_SpotPriceAfterBelowSpotPriceBefore();
    }
    if (spotPriceAfter > maxPrice) {
      revert BPool_SpotPriceAboveMaxPrice();
    }
    if (spotPriceBefore > bdiv(tokenAmountIn, tokenAmountOut)) {
      revert BPool_SpotPriceBeforeAboveTokenRatio();
    }

    emit LOG_SWAP(msg.sender, tokenIn, tokenOut, tokenAmountIn, tokenAmountOut);

    _pullUnderlying(tokenIn, msg.sender, tokenAmountIn);
    _pushUnderlying(tokenOut, msg.sender, tokenAmountOut);
  }

  /// @inheritdoc IBPool
  function swapExactAmountOut(
    address tokenIn,
    uint256 maxAmountIn,
    address tokenOut,
    uint256 tokenAmountOut,
    uint256 maxPrice
  ) external _logs_ _lock_ _finalized_ returns (uint256 tokenAmountIn, uint256 spotPriceAfter) {
    if (!_records[tokenIn].bound) {
      revert BPool_TokenNotBound();
    }
    if (!_records[tokenOut].bound) {
      revert BPool_TokenNotBound();
    }

    Record storage inRecord = _records[address(tokenIn)];
    Record storage outRecord = _records[address(tokenOut)];

    uint256 tokenInBalance = IERC20(tokenIn).balanceOf(address(this));
    uint256 tokenOutBalance = IERC20(tokenOut).balanceOf(address(this));

    if (tokenAmountOut > bmul(tokenOutBalance, MAX_OUT_RATIO)) {
      revert BPool_TokenAmountOutAboveMaxOut();
    }

    uint256 spotPriceBefore =
      calcSpotPrice(tokenInBalance, inRecord.denorm, tokenOutBalance, outRecord.denorm, _swapFee);
    if (spotPriceBefore > maxPrice) {
      revert BPool_SpotPriceAboveMaxPrice();
    }

    tokenAmountIn =
      calcInGivenOut(tokenInBalance, inRecord.denorm, tokenOutBalance, outRecord.denorm, tokenAmountOut, _swapFee);
    if (tokenAmountIn > maxAmountIn) {
      revert BPool_TokenAmountInAboveMaxAmountIn();
    }

    tokenInBalance = badd(tokenInBalance, tokenAmountIn);
    tokenOutBalance = bsub(tokenOutBalance, tokenAmountOut);

    spotPriceAfter = calcSpotPrice(tokenInBalance, inRecord.denorm, tokenOutBalance, outRecord.denorm, _swapFee);
    if (spotPriceAfter < spotPriceBefore) {
      revert BPool_SpotPriceAfterBelowSpotPriceBefore();
    }
    if (spotPriceAfter > maxPrice) {
      revert BPool_SpotPriceAboveMaxPrice();
    }
    if (spotPriceBefore > bdiv(tokenAmountIn, tokenAmountOut)) {
      revert BPool_SpotPriceBeforeAboveTokenRatio();
    }

    emit LOG_SWAP(msg.sender, tokenIn, tokenOut, tokenAmountIn, tokenAmountOut);

    _pullUnderlying(tokenIn, msg.sender, tokenAmountIn);
    _pushUnderlying(tokenOut, msg.sender, tokenAmountOut);
  }

  /// @inheritdoc IBPool
  function getSpotPrice(address tokenIn, address tokenOut) external view _viewlock_ returns (uint256) {
    if (!_records[tokenIn].bound) {
      revert BPool_TokenNotBound();
    }
    if (!_records[tokenOut].bound) {
      revert BPool_TokenNotBound();
    }
    Record storage inRecord = _records[tokenIn];
    Record storage outRecord = _records[tokenOut];

    return calcSpotPrice(
      IERC20(tokenIn).balanceOf(address(this)),
      inRecord.denorm,
      IERC20(tokenOut).balanceOf(address(this)),
      outRecord.denorm,
      _swapFee
    );
  }

  /// @inheritdoc IBPool
  function getSpotPriceSansFee(address tokenIn, address tokenOut) external view _viewlock_ returns (uint256) {
    if (!_records[tokenIn].bound) {
      revert BPool_TokenNotBound();
    }
    if (!_records[tokenOut].bound) {
      revert BPool_TokenNotBound();
    }
    Record storage inRecord = _records[tokenIn];
    Record storage outRecord = _records[tokenOut];

    return calcSpotPrice(
      IERC20(tokenIn).balanceOf(address(this)),
      inRecord.denorm,
      IERC20(tokenOut).balanceOf(address(this)),
      outRecord.denorm,
      0
    );
  }

  /// @inheritdoc IBPool
  function isFinalized() external view returns (bool) {
    return _finalized;
  }

  /// @inheritdoc IBPool
  function isBound(address token) external view returns (bool) {
    return _records[token].bound;
  }

  /// @inheritdoc IBPool
  function getNumTokens() external view returns (uint256) {
    return _tokens.length;
  }

  /// @inheritdoc IBPool
  function getCurrentTokens() external view _viewlock_ returns (address[] memory) {
    return _tokens;
  }

  /// @inheritdoc IBPool
  function getFinalTokens() external view _viewlock_ _finalized_ returns (address[] memory) {
    return _tokens;
  }

  /// @inheritdoc IBPool
  function getDenormalizedWeight(address token) external view _viewlock_ returns (uint256) {
    if (!_records[token].bound) {
      revert BPool_TokenNotBound();
    }
    return _records[token].denorm;
  }

  /// @inheritdoc IBPool
  function getTotalDenormalizedWeight() external view _viewlock_ returns (uint256) {
    return _totalWeight;
  }

  /// @inheritdoc IBPool
  function getNormalizedWeight(address token) external view _viewlock_ returns (uint256) {
    if (!_records[token].bound) {
      revert BPool_TokenNotBound();
    }
    uint256 denorm = _records[token].denorm;
    return bdiv(denorm, _totalWeight);
  }

  /// @inheritdoc IBPool
  function getBalance(address token) external view _viewlock_ returns (uint256) {
    if (!_records[token].bound) {
      revert BPool_TokenNotBound();
    }
    return IERC20(token).balanceOf(address(this));
  }

  /// @inheritdoc IBPool
  function getSwapFee() external view _viewlock_ returns (uint256) {
    return _swapFee;
  }

  /// @inheritdoc IBPool
  function getController() external view _viewlock_ returns (address) {
    return _controller;
  }

  /**
   * @notice Sets the value of the transient storage slot used for reentrancy locks
   * @param value The value of the transient storage slot used for reentrancy locks.
   * @dev Should be set to _MUTEX_FREE after a call, any other value will
   * be interpreted as locked
   */
  function _setLock(bytes32 value) internal virtual {
    assembly ("memory-safe") {
      tstore(_MUTEX_TRANSIENT_STORAGE_SLOT, value)
    }
  }

  /**
   * @dev Pulls tokens from the sender. Tokens needs to be approved first. Calls are not locked.
   * @param token The address of the token to pull
   * @param from The address to pull the tokens from
   * @param amount The amount of tokens to pull
   */
  function _pullUnderlying(address token, address from, uint256 amount) internal virtual {
    IERC20(token).safeTransferFrom(from, address(this), amount);
  }

  /**
   * @dev Pushes tokens to the receiver. Calls are not locked.
   * @param token The address of the token to push
   * @param to The address to push the tokens to
   * @param amount The amount of tokens to push
   */
  function _pushUnderlying(address token, address to, uint256 amount) internal virtual {
    IERC20(token).safeTransfer(to, amount);
  }

  /**
   * @dev Hook for extensions to execute custom logic when a pool is finalized,
   * e.g. Setting infinite allowance on BCoWPool
   */
  // solhint-disable-next-line no-empty-blocks
  function _afterFinalize() internal virtual {}

  /**
   * @dev Pulls pool tokens from the sender.
   * @param from The address to pull the pool tokens from
   * @param amount The amount of pool tokens to pull
   */
  function _pullPoolShare(address from, uint256 amount) internal virtual {
    _pull(from, amount);
  }

  /**
   * @dev Pushes pool tokens to the receiver.
   * @param to The address to push the pool tokens to
   * @param amount The amount of pool tokens to push
   */
  function _pushPoolShare(address to, uint256 amount) internal virtual {
    _push(to, amount);
  }

  /**
   * @dev Mints an amount of pool tokens.
   * @param amount The amount of pool tokens to mint
   */
  function _mintPoolShare(uint256 amount) internal virtual {
    _mint(address(this), amount);
  }

  /**
   * @dev Burns an amount of pool tokens.
   * @param amount The amount of pool tokens to burn
   */
  function _burnPoolShare(uint256 amount) internal virtual {
    _burn(address(this), amount);
  }

  /**
   * @notice Gets the value of the transient storage slot used for reentrancy locks
   * @return value Contents of transient storage slot used for reentrancy locks.
   * @dev Should only be compared against _MUTEX_FREE for the purposes of
   * allowing calls
   */
  function _getLock() internal view virtual returns (bytes32 value) {
    assembly ("memory-safe") {
      value := tload(_MUTEX_TRANSIENT_STORAGE_SLOT)
    }
  }
}

File 4 of 27 : GPv2Order.sol
// SPDX-License-Identifier: LGPL-3.0-or-later
pragma solidity >=0.7.6 <0.9.0;

import "../interfaces/IERC20.sol";

/// @title Gnosis Protocol v2 Order Library
/// @author Gnosis Developers
library GPv2Order {
    /// @dev The complete data for a Gnosis Protocol order. This struct contains
    /// all order parameters that are signed for submitting to GP.
    struct Data {
        IERC20 sellToken;
        IERC20 buyToken;
        address receiver;
        uint256 sellAmount;
        uint256 buyAmount;
        uint32 validTo;
        bytes32 appData;
        uint256 feeAmount;
        bytes32 kind;
        bool partiallyFillable;
        bytes32 sellTokenBalance;
        bytes32 buyTokenBalance;
    }

    /// @dev The order EIP-712 type hash for the [`GPv2Order.Data`] struct.
    ///
    /// This value is pre-computed from the following expression:
    /// ```
    /// keccak256(
    ///     "Order(" +
    ///         "address sellToken," +
    ///         "address buyToken," +
    ///         "address receiver," +
    ///         "uint256 sellAmount," +
    ///         "uint256 buyAmount," +
    ///         "uint32 validTo," +
    ///         "bytes32 appData," +
    ///         "uint256 feeAmount," +
    ///         "string kind," +
    ///         "bool partiallyFillable," +
    ///         "string sellTokenBalance," +
    ///         "string buyTokenBalance" +
    ///     ")"
    /// )
    /// ```
    bytes32 internal constant TYPE_HASH =
        hex"d5a25ba2e97094ad7d83dc28a6572da797d6b3e7fc6663bd93efb789fc17e489";

    /// @dev The marker value for a sell order for computing the order struct
    /// hash. This allows the EIP-712 compatible wallets to display a
    /// descriptive string for the order kind (instead of 0 or 1).
    ///
    /// This value is pre-computed from the following expression:
    /// ```
    /// keccak256("sell")
    /// ```
    bytes32 internal constant KIND_SELL =
        hex"f3b277728b3fee749481eb3e0b3b48980dbbab78658fc419025cb16eee346775";

    /// @dev The OrderKind marker value for a buy order for computing the order
    /// struct hash.
    ///
    /// This value is pre-computed from the following expression:
    /// ```
    /// keccak256("buy")
    /// ```
    bytes32 internal constant KIND_BUY =
        hex"6ed88e868af0a1983e3886d5f3e95a2fafbd6c3450bc229e27342283dc429ccc";

    /// @dev The TokenBalance marker value for using direct ERC20 balances for
    /// computing the order struct hash.
    ///
    /// This value is pre-computed from the following expression:
    /// ```
    /// keccak256("erc20")
    /// ```
    bytes32 internal constant BALANCE_ERC20 =
        hex"5a28e9363bb942b639270062aa6bb295f434bcdfc42c97267bf003f272060dc9";

    /// @dev The TokenBalance marker value for using Balancer Vault external
    /// balances (in order to re-use Vault ERC20 approvals) for computing the
    /// order struct hash.
    ///
    /// This value is pre-computed from the following expression:
    /// ```
    /// keccak256("external")
    /// ```
    bytes32 internal constant BALANCE_EXTERNAL =
        hex"abee3b73373acd583a130924aad6dc38cfdc44ba0555ba94ce2ff63980ea0632";

    /// @dev The TokenBalance marker value for using Balancer Vault internal
    /// balances for computing the order struct hash.
    ///
    /// This value is pre-computed from the following expression:
    /// ```
    /// keccak256("internal")
    /// ```
    bytes32 internal constant BALANCE_INTERNAL =
        hex"4ac99ace14ee0a5ef932dc609df0943ab7ac16b7583634612f8dc35a4289a6ce";

    /// @dev Marker address used to indicate that the receiver of the trade
    /// proceeds should the owner of the order.
    ///
    /// This is chosen to be `address(0)` for gas efficiency as it is expected
    /// to be the most common case.
    address internal constant RECEIVER_SAME_AS_OWNER = address(0);

    /// @dev The byte length of an order unique identifier.
    uint256 internal constant UID_LENGTH = 56;

    /// @dev Returns the actual receiver for an order. This function checks
    /// whether or not the [`receiver`] field uses the marker value to indicate
    /// it is the same as the order owner.
    ///
    /// @return receiver The actual receiver of trade proceeds.
    function actualReceiver(
        Data memory order,
        address owner
    ) internal pure returns (address receiver) {
        if (order.receiver == RECEIVER_SAME_AS_OWNER) {
            receiver = owner;
        } else {
            receiver = order.receiver;
        }
    }

    /// @dev Return the EIP-712 signing hash for the specified order.
    ///
    /// @param order The order to compute the EIP-712 signing hash for.
    /// @param domainSeparator The EIP-712 domain separator to use.
    /// @return orderDigest The 32 byte EIP-712 struct hash.
    function hash(
        Data memory order,
        bytes32 domainSeparator
    ) internal pure returns (bytes32 orderDigest) {
        bytes32 structHash;

        // NOTE: Compute the EIP-712 order struct hash in place. As suggested
        // in the EIP proposal, noting that the order struct has 12 fields, and
        // prefixing the type hash `(1 + 12) * 32 = 416` bytes to hash.
        // <https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md#rationale-for-encodedata>
        // solhint-disable-next-line no-inline-assembly
        assembly {
            let dataStart := sub(order, 32)
            let temp := mload(dataStart)
            mstore(dataStart, TYPE_HASH)
            structHash := keccak256(dataStart, 416)
            mstore(dataStart, temp)
        }

        // NOTE: Now that we have the struct hash, compute the EIP-712 signing
        // hash using scratch memory past the free memory pointer. The signing
        // hash is computed from `"\x19\x01" || domainSeparator || structHash`.
        // <https://docs.soliditylang.org/en/v0.7.6/internals/layout_in_memory.html#layout-in-memory>
        // <https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md#specification>
        // solhint-disable-next-line no-inline-assembly
        assembly {
            let freeMemoryPointer := mload(0x40)
            mstore(freeMemoryPointer, "\x19\x01")
            mstore(add(freeMemoryPointer, 2), domainSeparator)
            mstore(add(freeMemoryPointer, 34), structHash)
            orderDigest := keccak256(freeMemoryPointer, 66)
        }
    }

    /// @dev Packs order UID parameters into the specified memory location. The
    /// result is equivalent to `abi.encodePacked(...)` with the difference that
    /// it allows re-using the memory for packing the order UID.
    ///
    /// This function reverts if the order UID buffer is not the correct size.
    ///
    /// @param orderUid The buffer pack the order UID parameters into.
    /// @param orderDigest The EIP-712 struct digest derived from the order
    /// parameters.
    /// @param owner The address of the user who owns this order.
    /// @param validTo The epoch time at which the order will stop being valid.
    function packOrderUidParams(
        bytes memory orderUid,
        bytes32 orderDigest,
        address owner,
        uint32 validTo
    ) internal pure {
        require(orderUid.length == UID_LENGTH, "GPv2: uid buffer overflow");

        // NOTE: Write the order UID to the allocated memory buffer. The order
        // parameters are written to memory in **reverse order** as memory
        // operations write 32-bytes at a time and we want to use a packed
        // encoding. This means, for example, that after writing the value of
        // `owner` to bytes `20:52`, writing the `orderDigest` to bytes `0:32`
        // will **overwrite** bytes `20:32`. This is desirable as addresses are
        // only 20 bytes and `20:32` should be `0`s:
        //
        //        |           1111111111222222222233333333334444444444555555
        //   byte | 01234567890123456789012345678901234567890123456789012345
        // -------+---------------------------------------------------------
        //  field | [.........orderDigest..........][......owner.......][vT]
        // -------+---------------------------------------------------------
        // mstore |                         [000000000000000000000000000.vT]
        //        |                     [00000000000.......owner.......]
        //        | [.........orderDigest..........]
        //
        // Additionally, since Solidity `bytes memory` are length prefixed,
        // 32 needs to be added to all the offsets.
        //
        // solhint-disable-next-line no-inline-assembly
        assembly {
            mstore(add(orderUid, 56), validTo)
            mstore(add(orderUid, 52), owner)
            mstore(add(orderUid, 32), orderDigest)
        }
    }

    /// @dev Extracts specific order information from the standardized unique
    /// order id of the protocol.
    ///
    /// @param orderUid The unique identifier used to represent an order in
    /// the protocol. This uid is the packed concatenation of the order digest,
    /// the validTo order parameter and the address of the user who created the
    /// order. It is used by the user to interface with the contract directly,
    /// and not by calls that are triggered by the solvers.
    /// @return orderDigest The EIP-712 signing digest derived from the order
    /// parameters.
    /// @return owner The address of the user who owns this order.
    /// @return validTo The epoch time at which the order will stop being valid.
    function extractOrderUidParams(
        bytes calldata orderUid
    )
        internal
        pure
        returns (bytes32 orderDigest, address owner, uint32 validTo)
    {
        require(orderUid.length == UID_LENGTH, "GPv2: invalid uid");

        // Use assembly to efficiently decode packed calldata.
        // solhint-disable-next-line no-inline-assembly
        assembly {
            orderDigest := calldataload(orderUid.offset)
            owner := shr(96, calldataload(add(orderUid.offset, 32)))
            validTo := shr(224, calldataload(add(orderUid.offset, 52)))
        }
    }
}

File 5 of 27 : IERC1271.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC1271.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC1271 standard signature validation method for
 * contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271].
 */
interface IERC1271 {
    /**
     * @dev Should return whether the signature provided is valid for the provided data
     * @param hash      Hash of the data to be signed
     * @param signature Signature byte array associated with _data
     */
    function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue);
}

File 6 of 27 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the value of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the value of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 value) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the
     * allowance mechanism. `value` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 value) external returns (bool);
}

File 7 of 27 : SafeERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../IERC20.sol";
import {IERC20Permit} from "../extensions/IERC20Permit.sol";
import {Address} from "../../../utils/Address.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using Address for address;

    /**
     * @dev An operation with an ERC20 token failed.
     */
    error SafeERC20FailedOperation(address token);

    /**
     * @dev Indicates a failed `decreaseAllowance` request.
     */
    error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);

    /**
     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
    }

    /**
     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
     */
    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
    }

    /**
     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 oldAllowance = token.allowance(address(this), spender);
        forceApprove(token, spender, oldAllowance + value);
    }

    /**
     * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
     * value, non-reverting calls are assumed to be successful.
     */
    function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
        unchecked {
            uint256 currentAllowance = token.allowance(address(this), spender);
            if (currentAllowance < requestedDecrease) {
                revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
            }
            forceApprove(token, spender, currentAllowance - requestedDecrease);
        }
    }

    /**
     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
     * to be set to zero before setting it to a non-zero value, such as USDT.
     */
    function forceApprove(IERC20 token, address spender, uint256 value) internal {
        bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));

        if (!_callOptionalReturnBool(token, approvalCall)) {
            _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
            _callOptionalReturn(token, approvalCall);
        }
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data);
        if (returndata.length != 0 && !abi.decode(returndata, (bool))) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     *
     * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
     */
    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
        // and not revert is the subcall reverts.

        (bool success, bytes memory returndata) = address(token).call(data);
        return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0;
    }
}

File 8 of 27 : IBCoWFactory.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.25;

import {IBFactory} from 'interfaces/IBFactory.sol';

interface IBCoWFactory is IBFactory {
  /**
   * @notice Emitted when a bCoWPool created by this factory is finalized
   * @param bCoWPool The pool just finalized
   */
  event COWAMMPoolCreated(address indexed bCoWPool);

  /**
   * @notice thrown when the caller of `logBCoWPool()` is not a bCoWPool created by this factory
   */
  error BCoWFactory_NotValidBCoWPool();

  /**
   * @notice Emits the COWAMMPoolCreated event if the caller is a bCoWPool, to be indexed by off-chain agents
   */
  function logBCoWPool() external;

  /**
   * @notice The address of the CoW Protocol settlement contract. It is the
   * only address that can set commitments.
   * @return solutionSettler The address of the solution settler.
   */
  // solhint-disable-next-line style-guide-casing
  function SOLUTION_SETTLER() external view returns (address solutionSettler);

  /**
   * @notice The identifier describing which `GPv2Order.AppData` currently
   * apply to this AMM.
   * @return appData The 32 bytes identifier of the allowed GPv2Order AppData.
   */
  // solhint-disable-next-line style-guide-casing
  function APP_DATA() external view returns (bytes32 appData);
}

File 9 of 27 : IBCoWPool.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.25;

import {GPv2Order} from '@cowprotocol/libraries/GPv2Order.sol';
import {IERC1271} from '@openzeppelin/contracts/interfaces/IERC1271.sol';
import {IBPool} from 'interfaces/IBPool.sol';
import {ISettlement} from 'interfaces/ISettlement.sol';

interface IBCoWPool is IERC1271, IBPool {
  /**
   * @notice Thrown when a CoW order has a non-zero fee
   */
  error BCoWPool_FeeMustBeZero();

  /**
   * @notice Thrown when a CoW order is executed after its deadline
   */
  error BCoWPool_OrderValidityTooLong();

  /**
   * @notice Thrown when a CoW order has an unknown type (must be GPv2Order.KIND_SELL)
   */
  error BCoWPool_InvalidOperation();

  /**
   * @notice Thrown when a CoW order has an invalid balance marker. BCoWPool
   * only supports BALANCE_ERC20, instructing to use the underlying ERC20
   * balance directly instead of balancer's internal accounting
   */
  error BCoWPool_InvalidBalanceMarker();

  /**
   * @notice The `commit` function can only be called inside a CoW Swap
   * settlement. This error is thrown when the function is called from another
   * context.
   */
  error CommitOutsideOfSettlement();

  /**
   * @notice Error thrown when a solver tries to settle an AMM order on CoW
   * Protocol whose hash doesn't match the one that has been committed to.
   */
  error OrderDoesNotMatchCommitmentHash();

  /**
   * @notice On signature verification, the hash of the order supplied as part
   * of the signature does not match the provided message hash.
   * This usually means that the verification function is being provided a
   * signature that belongs to a different order.
   */
  error OrderDoesNotMatchMessageHash();

  /**
   * @notice Thrown when AppData that was provided during signature verification
   * does not match the one stored in this contract.
   */
  error AppDataDoesNotMatch();

  /**
   * @notice Thrown when the receiver of the order is not the bCoWPool itself.
   */
  error BCoWPool_ReceiverIsNotBCoWPool();

  /**
   * @notice Restricts a specific AMM to being able to trade only the order
   * with the specified hash.
   * @dev The commitment is used to enforce that exactly one AMM order is
   * valid when a CoW Protocol batch is settled.
   * @param orderHash the order hash that will be enforced by the order
   * verification function.
   */
  function commit(bytes32 orderHash) external;

  /**
   * @notice The address that can pull funds from the AMM vault to execute an order
   * @return vaultRelayer The address of the vault relayer.
   */
  // solhint-disable-next-line style-guide-casing
  function VAULT_RELAYER() external view returns (address vaultRelayer);

  /**
   * @notice The domain separator used for hashing CoW Protocol orders.
   * @return solutionSettlerDomainSeparator The domain separator.
   */
  // solhint-disable-next-line style-guide-casing
  function SOLUTION_SETTLER_DOMAIN_SEPARATOR() external view returns (bytes32 solutionSettlerDomainSeparator);

  /**
   * @notice The address of the CoW Protocol settlement contract. It is the
   * only address that can set commitments.
   * @return solutionSettler The address of the solution settler.
   */
  // solhint-disable-next-line style-guide-casing
  function SOLUTION_SETTLER() external view returns (ISettlement solutionSettler);

  /**
   * @notice The identifier describing which `GPv2Order.AppData` currently
   * apply to this AMM.
   * @return appData The 32 bytes identifier of the allowed GPv2Order AppData.
   */
  // solhint-disable-next-line style-guide-casing
  function APP_DATA() external view returns (bytes32 appData);

  /**
   * @notice This function checks that the input order is admissible for the
   * constant-product curve for the given trading parameters.
   * @param order `GPv2Order.Data` of a discrete order to be verified.
   */
  function verify(GPv2Order.Data memory order) external view;
}

File 10 of 27 : ISettlement.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.25;

import {IERC20} from '@cowprotocol/interfaces/IERC20.sol';
import {GPv2Interaction} from '@cowprotocol/libraries/GPv2Interaction.sol';
import {GPv2Trade} from '@cowprotocol/libraries/GPv2Trade.sol';

/**
 * @title ISettlement
 * @notice External interface of CoW Protocol's SolutionSettler contract.
 */
interface ISettlement {
  /**
   * @notice Settles a batch of trades.
   * @param tokens The tokens that are traded in the batch.
   * @param clearingPrices The clearing prices of the trades.
   * @param trades The trades to settle.
   * @param interactions The interactions to execute.
   */
  function settle(
    IERC20[] calldata tokens,
    uint256[] calldata clearingPrices,
    GPv2Trade.Data[] calldata trades,
    GPv2Interaction.Data[][3] calldata interactions
  ) external;

  /**
   * @return domainSeparator The domain separator for IERC1271 signature
   * @dev Immutable value, would not change on chain forks
   */
  function domainSeparator() external view returns (bytes32 domainSeparator);

  /**
   * @return vaultRelayer The address that'll use the pool liquidity in CoWprotocol swaps
   * @dev Address that will transfer and transferFrom the pool. Has an infinite allowance.
   */
  function vaultRelayer() external view returns (address vaultRelayer);
}

File 11 of 27 : BMath.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.25;

import {BConst} from './BConst.sol';
import {BNum} from './BNum.sol';

/**
 * @title BMath
 * @notice Includes functions for calculating the BPool related math.
 */
contract BMath is BConst, BNum {
  /**
   * @notice Calculate the spot price of a token in terms of another one
   * @dev The price denomination depends on the decimals of the tokens.
   * @dev To obtain the price with 18 decimals the next formula should be applied to the result
   * @dev spotPrice = spotPrice ÷ (10^tokenInDecimals) × (10^tokenOutDecimals)
   * @param tokenBalanceIn The balance of the input token in the pool
   * @param tokenWeightIn The weight of the input token in the pool
   * @param tokenBalanceOut The balance of the output token in the pool
   * @param tokenWeightOut The weight of the output token in the pool
   * @param swapFee The swap fee of the pool
   * @return spotPrice The spot price of a token in terms of another one
   * @dev Formula:
   * sP = spotPrice
   * bI = tokenBalanceIn                ( bI / wI )         1
   * bO = tokenBalanceOut         sP =  -----------  *  ----------
   * wI = tokenWeightIn                 ( bO / wO )     ( 1 - sF )
   * wO = tokenWeightOut
   * sF = swapFee
   */
  function calcSpotPrice(
    uint256 tokenBalanceIn,
    uint256 tokenWeightIn,
    uint256 tokenBalanceOut,
    uint256 tokenWeightOut,
    uint256 swapFee
  ) public pure returns (uint256 spotPrice) {
    uint256 numer = bdiv(tokenBalanceIn, tokenWeightIn);
    uint256 denom = bdiv(tokenBalanceOut, tokenWeightOut);
    uint256 ratio = bdiv(numer, denom);
    uint256 scale = bdiv(BONE, bsub(BONE, swapFee));
    return (spotPrice = bmul(ratio, scale));
  }

  /**
   * @notice Calculate the amount of token out given the amount of token in for a swap
   * @param tokenBalanceIn The balance of the input token in the pool
   * @param tokenWeightIn The weight of the input token in the pool
   * @param tokenBalanceOut The balance of the output token in the pool
   * @param tokenWeightOut The weight of the output token in the pool
   * @param tokenAmountIn The amount of the input token
   * @param swapFee The swap fee of the pool
   * @return tokenAmountOut The amount of token out given the amount of token in for a swap
   * @dev Formula:
   * aO = tokenAmountOut
   * bO = tokenBalanceOut
   * bI = tokenBalanceIn              /      /            bI             \    (wI / wO) \
   * aI = tokenAmountIn    aO = bO * |  1 - | --------------------------  | ^            |
   * wI = tokenWeightIn               \      \ ( bI + ( aI * ( 1 - sF )) /              /
   * wO = tokenWeightOut
   * sF = swapFee
   */
  function calcOutGivenIn(
    uint256 tokenBalanceIn,
    uint256 tokenWeightIn,
    uint256 tokenBalanceOut,
    uint256 tokenWeightOut,
    uint256 tokenAmountIn,
    uint256 swapFee
  ) public pure returns (uint256 tokenAmountOut) {
    uint256 weightRatio = bdiv(tokenWeightIn, tokenWeightOut);
    uint256 adjustedIn = bsub(BONE, swapFee);
    adjustedIn = bmul(tokenAmountIn, adjustedIn);
    uint256 y = bdiv(tokenBalanceIn, badd(tokenBalanceIn, adjustedIn));
    uint256 foo = bpow(y, weightRatio);
    uint256 bar = bsub(BONE, foo);
    tokenAmountOut = bmul(tokenBalanceOut, bar);
    return tokenAmountOut;
  }

  /**
   * @notice Calculate the amount of token in given the amount of token out for a swap
   * @param tokenBalanceIn The balance of the input token in the pool
   * @param tokenWeightIn The weight of the input token in the pool
   * @param tokenBalanceOut The balance of the output token in the pool
   * @param tokenWeightOut The weight of the output token in the pool
   * @param tokenAmountOut The amount of the output token
   * @param swapFee The swap fee of the pool
   * @return tokenAmountIn The amount of token in given the amount of token out for a swap
   * @dev Formula:
   * aI = tokenAmountIn
   * bO = tokenBalanceOut               /  /     bO      \    (wO / wI)      \
   * bI = tokenBalanceIn          bI * |  | ------------  | ^            - 1  |
   * aO = tokenAmountOut    aI =        \  \ ( bO - aO ) /                   /
   * wI = tokenWeightIn           --------------------------------------------
   * wO = tokenWeightOut                          ( 1 - sF )
   * sF = swapFee
   */
  function calcInGivenOut(
    uint256 tokenBalanceIn,
    uint256 tokenWeightIn,
    uint256 tokenBalanceOut,
    uint256 tokenWeightOut,
    uint256 tokenAmountOut,
    uint256 swapFee
  ) public pure returns (uint256 tokenAmountIn) {
    uint256 weightRatio = bdiv(tokenWeightOut, tokenWeightIn);
    uint256 diff = bsub(tokenBalanceOut, tokenAmountOut);
    uint256 y = bdiv(tokenBalanceOut, diff);
    uint256 foo = bpow(y, weightRatio);
    foo = bsub(foo, BONE);
    tokenAmountIn = bsub(BONE, swapFee);
    tokenAmountIn = bdiv(bmul(tokenBalanceIn, foo), tokenAmountIn);
    return tokenAmountIn;
  }
}

File 12 of 27 : BToken.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.25;

import {ERC20} from '@openzeppelin/contracts/token/ERC20/ERC20.sol';

/**
 * @title BToken
 * @notice Balancer Pool Token base contract, providing ERC20 functionality.
 */
contract BToken is ERC20 {
  constructor(string memory name, string memory symbol) ERC20(name, symbol) {}

  /**
   * @notice Increase the allowance of the spender.
   * @param spender The address which will spend the funds.
   * @param amount The amount of tokens to increase the allowance by.
   * @return success True if the operation is successful.
   */
  function increaseApproval(address spender, uint256 amount) external returns (bool success) {
    _approve(msg.sender, spender, allowance(msg.sender, spender) + amount);
    success = true;
  }

  /**
   * @notice Decrease the allowance of the spender.
   * @param spender The address which will spend the funds.
   * @param amount The amount of tokens to decrease the allowance by.
   * @return success True if the operation is successful.
   */
  function decreaseApproval(address spender, uint256 amount) external returns (bool success) {
    uint256 oldValue = allowance(msg.sender, spender);
    if (amount > oldValue) {
      _approve(msg.sender, spender, 0);
    } else {
      _approve(msg.sender, spender, oldValue - amount);
    }
    success = true;
  }

  /**
   * @notice Transfer tokens from one this contract to another.
   * @param to The address which you want to transfer to.
   * @param amount The amount of tokens to be transferred.
   */
  function _push(address to, uint256 amount) internal virtual {
    _transfer(address(this), to, amount);
  }

  /**
   * @notice Pull tokens from another address to this contract.
   * @param from The address which you want to transfer from.
   * @param amount The amount of tokens to be transferred.
   */
  function _pull(address from, uint256 amount) internal virtual {
    _transfer(from, address(this), amount);
  }
}

File 13 of 27 : IBPool.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.25;

import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';

interface IBPool is IERC20 {
  /**
   * @dev Struct for token records.
   * @param bound If token is bound to pool.
   * @param index Internal index of token array.
   * @param denorm Denormalized weight of token.
   */
  struct Record {
    bool bound;
    uint256 index;
    uint256 denorm;
  }

  /**
   * @notice Emitted when a swap is executed
   * @param caller The caller of the swap function
   * @param tokenIn The address of the token being swapped in
   * @param tokenOut The address of the token being swapped out
   * @param tokenAmountIn The amount of tokenIn being swapped in
   * @param tokenAmountOut The amount of tokenOut being swapped out
   */
  event LOG_SWAP(
    address indexed caller,
    address indexed tokenIn,
    address indexed tokenOut,
    uint256 tokenAmountIn,
    uint256 tokenAmountOut
  );

  /**
   * @notice Emitted when a join operation is executed
   * @param caller The caller of the function
   * @param tokenIn The address of the token being sent to the pool
   * @param tokenAmountIn The balance of the token being sent to the pool
   */
  event LOG_JOIN(address indexed caller, address indexed tokenIn, uint256 tokenAmountIn);

  /**
   * @notice Emitted when a token amount is removed from the pool
   * @param caller The caller of the function
   * @param tokenOut The address of the token being removed from the pool
   * @param tokenAmountOut The amount of the token being removed from the pool
   */
  event LOG_EXIT(address indexed caller, address indexed tokenOut, uint256 tokenAmountOut);

  /**
   * @notice Emitted when a call is executed on the pool
   * @param sig The signature of the function selector being called
   * @param caller The caller of the function
   * @param data The complete data of the call
   */
  event LOG_CALL(bytes4 indexed sig, address indexed caller, bytes data) anonymous;

  /**
   * @notice Thrown when setting a variable to address zero
   */
  error BPool_AddressZero();

  /**
   * @notice Thrown when a reentrant call is made
   */
  error BPool_Reentrancy();

  /**
   * @notice Thrown when the pool is finalized
   */
  error BPool_PoolIsFinalized();

  /**
   * @notice Thrown when the caller is not the controller
   */
  error BPool_CallerIsNotController();

  /**
   * @notice Thrown when the pool is not finalized
   */
  error BPool_FeeBelowMinimum();

  /**
   * @notice Thrown when the fee to set is above the maximum
   */
  error BPool_FeeAboveMaximum();

  /**
   * @notice Thrown when the tokens array is below the minimum
   */
  error BPool_TokensBelowMinimum();

  /**
   * @notice Thrown when the token is already bound in the pool
   */
  error BPool_TokenAlreadyBound();

  /**
   * @notice Thrown when the tokens array is above the maximum
   */
  error BPool_TokensAboveMaximum();

  /**
   * @notice Thrown when the weight to set is below the minimum
   */
  error BPool_WeightBelowMinimum();

  /**
   * @notice Thrown when the weight to set is above the maximum
   */
  error BPool_WeightAboveMaximum();

  /**
   * @notice Thrown when the balance to add is below the minimum
   */
  error BPool_BalanceBelowMinimum();

  /**
   * @notice Thrown when the total weight is above the maximum
   */
  error BPool_TotalWeightAboveMaximum();

  /**
   * @notice Thrown when the ratio between the pool token amount and the total supply is zero
   */
  error BPool_InvalidPoolRatio();

  /**
   * @notice Thrown when the calculated token amount in is zero
   */
  error BPool_InvalidTokenAmountIn();

  /**
   * @notice Thrown when the token amount in is above maximum amount in allowed by the caller
   */
  error BPool_TokenAmountInAboveMaxAmountIn();

  /**
   * @notice Thrown when the calculated token amount out is zero
   */
  error BPool_InvalidTokenAmountOut();

  /**
   * @notice Thrown when the token amount out is below minimum amount out allowed by the caller
   */
  error BPool_TokenAmountOutBelowMinAmountOut();

  /**
   * @notice Thrown when the token is not bound in the pool
   */
  error BPool_TokenNotBound();

  /**
   * @notice Thrown when the pool is not finalized
   */
  error BPool_PoolNotFinalized();

  /**
   * @notice Thrown when the token amount in surpasses the maximum in ratio allowed by the pool
   */
  error BPool_TokenAmountInAboveMaxRatio();

  /**
   * @notice Thrown when the spot price before or after the swap is above the max allowed by the caller
   */
  error BPool_SpotPriceAboveMaxPrice();

  /**
   * @notice Thrown when the token amount out is below the minimum out allowed by the caller
   */
  error BPool_TokenAmountOutBelowMinOut();

  /**
   * @notice Thrown when the spot price after the swap is below the spot price before the swap
   */
  error BPool_SpotPriceAfterBelowSpotPriceBefore();

  /**
   * @notice Thrown when the spot price before the swap is above the ratio between the two tokens in the pool
   */
  error BPool_SpotPriceBeforeAboveTokenRatio();

  /**
   * @notice Thrown when the token amount out surpasses the maximum out allowed by the pool
   */
  error BPool_TokenAmountOutAboveMaxOut();

  /**
   * @notice Thrown when the pool token amount out is below the minimum pool token amount out allowed by the caller
   */
  error BPool_PoolAmountOutBelowMinPoolAmountOut();

  /**
   * @notice Thrown when the calculated pool token amount in is zero
   */
  error BPool_InvalidPoolAmountIn();

  /**
   * @notice Thrown when the pool token amount in is above the maximum amount in allowed by the caller
   */
  error BPool_PoolAmountInAboveMaxPoolAmountIn();

  /**
   * @notice Sets the new swap fee
   * @param swapFee The new swap fee
   */
  function setSwapFee(uint256 swapFee) external;

  /**
   * @notice Sets the new controller
   * @param manager The new controller
   */
  function setController(address manager) external;

  /**
   * @notice Finalize the pool, removing the restrictions on the pool
   */
  function finalize() external;

  /**
   * @notice Binds a token to the pool
   * @param token The address of the token to bind
   * @param balance The balance of the token to bind
   * @param denorm The denormalized weight of the token to bind
   */
  function bind(address token, uint256 balance, uint256 denorm) external;

  /**
   * @notice Unbinds a token from the pool
   * @param token The address of the token to unbind
   */
  function unbind(address token) external;

  /**
   * @notice Joins a pool, providing each token in the pool with a proportional amount
   * @param poolAmountOut The amount of pool tokens to mint
   * @param maxAmountsIn The maximum amount of tokens to send to the pool
   */
  function joinPool(uint256 poolAmountOut, uint256[] calldata maxAmountsIn) external;

  /**
   * @notice Exits a pool, receiving each token in the pool with a proportional amount
   * @param poolAmountIn The amount of pool tokens to burn
   * @param minAmountsOut The minimum amount of tokens to receive from the pool
   */
  function exitPool(uint256 poolAmountIn, uint256[] calldata minAmountsOut) external;

  /**
   * @notice Swaps an exact amount of tokens in for an amount of tokens out
   * @param tokenIn The address of the token to swap in
   * @param tokenAmountIn The amount of token to swap in
   * @param tokenOut The address of the token to swap out
   * @param minAmountOut The minimum amount of token to receive from the swap
   * @param maxPrice The maximum price to pay for the swap
   * @return tokenAmountOut The amount of token swapped out
   * @return spotPriceAfter The spot price after the swap
   */
  function swapExactAmountIn(
    address tokenIn,
    uint256 tokenAmountIn,
    address tokenOut,
    uint256 minAmountOut,
    uint256 maxPrice
  ) external returns (uint256 tokenAmountOut, uint256 spotPriceAfter);

  /**
   * @notice Swaps as many tokens in as needed for an exact amount of tokens out
   * @param tokenIn The address of the token to swap in
   * @param maxAmountIn The maximum amount of token to swap in
   * @param tokenOut The address of the token to swap out
   * @param tokenAmountOut The amount of token to swap out
   * @param maxPrice The maximum price to pay for the swap
   * @return tokenAmountIn The amount of token swapped in
   * @return spotPriceAfter The spot price after the swap
   */
  function swapExactAmountOut(
    address tokenIn,
    uint256 maxAmountIn,
    address tokenOut,
    uint256 tokenAmountOut,
    uint256 maxPrice
  ) external returns (uint256 tokenAmountIn, uint256 spotPriceAfter);

  /**
   * @notice Gets the spot price of tokenIn in terms of tokenOut
   * @param tokenIn The address of the token to swap in
   * @param tokenOut The address of the token to swap out
   * @return spotPrice The spot price of the swap
   */
  function getSpotPrice(address tokenIn, address tokenOut) external view returns (uint256 spotPrice);

  /**
   * @notice Gets the spot price of tokenIn in terms of tokenOut without the fee
   * @param tokenIn The address of the token to swap in
   * @param tokenOut The address of the token to swap out
   * @return spotPrice The spot price of the swap without the fee
   */
  function getSpotPriceSansFee(address tokenIn, address tokenOut) external view returns (uint256 spotPrice);

  /**
   * @notice Gets the finalized status of the pool
   * @return isFinalized True if the pool is finalized, False otherwise
   */
  function isFinalized() external view returns (bool isFinalized);

  /**
   * @notice Gets the bound status of a token
   * @param t The address of the token to check
   * @return isBound True if the token is bound, False otherwise
   */
  function isBound(address t) external view returns (bool isBound);

  /**
   * @notice Gets the number of tokens in the pool
   * @return numTokens The number of tokens in the pool
   */
  function getNumTokens() external view returns (uint256 numTokens);

  /**
   * @notice Gets the current array of tokens in the pool, while the pool is not finalized
   * @return tokens The array of tokens in the pool
   */
  function getCurrentTokens() external view returns (address[] memory tokens);

  /**
   * @notice Gets the final array of tokens in the pool, after finalization
   * @return tokens The array of tokens in the pool
   */
  function getFinalTokens() external view returns (address[] memory tokens);

  /**
   * @notice Gets the denormalized weight of a token in the pool
   * @param token The address of the token to check
   * @return denormWeight The denormalized weight of the token in the pool
   */
  function getDenormalizedWeight(address token) external view returns (uint256 denormWeight);

  /**
   * @notice Gets the total denormalized weight of the pool
   * @return totalDenormWeight The total denormalized weight of the pool
   */
  function getTotalDenormalizedWeight() external view returns (uint256 totalDenormWeight);

  /**
   * @notice Gets the normalized weight of a token in the pool
   * @param token The address of the token to check
   * @return normWeight The normalized weight of the token in the pool
   */
  function getNormalizedWeight(address token) external view returns (uint256 normWeight);

  /**
   * @notice Gets the Pool's ERC20 balance of a token
   * @param token The address of the token to check
   * @return balance The Pool's ERC20 balance of the token
   */
  function getBalance(address token) external view returns (uint256 balance);

  /**
   * @notice Gets the swap fee of the pool
   * @return swapFee The swap fee of the pool
   */
  function getSwapFee() external view returns (uint256 swapFee);

  /**
   * @notice Gets the controller of the pool
   * @return controller The controller of the pool
   */
  function getController() external view returns (address controller);

  /**
   * @notice Gets the BFactory address that deployed the pool
   * @return factory The address of the factory
   */
  // solhint-disable-next-line style-guide-casing
  function FACTORY() external view returns (address factory);
}

File 14 of 27 : IERC20.sol
// SPDX-License-Identifier: MIT

// Vendored from OpenZeppelin contracts with minor modifications:
// - Modified Solidity version
// - Formatted code
// - Added `name`, `symbol` and `decimals` function declarations
// <https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.4.0/contracts/token/ERC20/IERC20.sol>

pragma solidity >=0.7.6 <0.9.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the number of decimals the token uses.
     */
    function decimals() external view returns (uint8);

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(
        address recipient,
        uint256 amount
    ) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(
        address owner,
        address spender
    ) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(
        address indexed owner,
        address indexed spender,
        uint256 value
    );
}

File 15 of 27 : IERC20Permit.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 *
 * ==== Security Considerations
 *
 * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature
 * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
 * considered as an intention to spend the allowance in any specific way. The second is that because permits have
 * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
 * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be
 * generally recommended is:
 *
 * ```solidity
 * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
 *     try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
 *     doThing(..., value);
 * }
 *
 * function doThing(..., uint256 value) public {
 *     token.safeTransferFrom(msg.sender, address(this), value);
 *     ...
 * }
 * ```
 *
 * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
 * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also
 * {SafeERC20-safeTransferFrom}).
 *
 * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so
 * contracts should have entry points that don't rely on permit.
 */
interface IERC20Permit {
    /**
     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
     * given ``owner``'s signed approval.
     *
     * IMPORTANT: The same issues {IERC20-approve} has related to transaction
     * ordering also apply here.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `deadline` must be a timestamp in the future.
     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
     * over the EIP712-formatted function arguments.
     * - the signature must use ``owner``'s current nonce (see {nonces}).
     *
     * For more information on the signature format, see the
     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
     * section].
     *
     * CAUTION: See Security Considerations above.
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @dev Returns the current nonce for `owner`. This value must be
     * included whenever a signature is generated for {permit}.
     *
     * Every successful call to {permit} increases ``owner``'s nonce by one. This
     * prevents a signature from being used multiple times.
     */
    function nonces(address owner) external view returns (uint256);

    /**
     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view returns (bytes32);
}

File 16 of 27 : Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)

pragma solidity ^0.8.20;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev The ETH balance of the account is not enough to perform the operation.
     */
    error AddressInsufficientBalance(address account);

    /**
     * @dev There's no code at `target` (it is not a contract).
     */
    error AddressEmptyCode(address target);

    /**
     * @dev A call to an address target failed. The target may have reverted.
     */
    error FailedInnerCall();

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        if (address(this).balance < amount) {
            revert AddressInsufficientBalance(address(this));
        }

        (bool success, ) = recipient.call{value: amount}("");
        if (!success) {
            revert FailedInnerCall();
        }
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason or custom error, it is bubbled
     * up by this function (like regular Solidity function calls). However, if
     * the call reverted with no returned reason, this function reverts with a
     * {FailedInnerCall} error.
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        if (address(this).balance < value) {
            revert AddressInsufficientBalance(address(this));
        }
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
     * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an
     * unsuccessful call.
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata
    ) internal view returns (bytes memory) {
        if (!success) {
            _revert(returndata);
        } else {
            // only check if target is a contract if the call was successful and the return data is empty
            // otherwise we already know that it was a contract
            if (returndata.length == 0 && target.code.length == 0) {
                revert AddressEmptyCode(target);
            }
            return returndata;
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the
     * revert reason or with a default {FailedInnerCall} error.
     */
    function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
        if (!success) {
            _revert(returndata);
        } else {
            return returndata;
        }
    }

    /**
     * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.
     */
    function _revert(bytes memory returndata) private pure {
        // Look for revert reason and bubble it up if present
        if (returndata.length > 0) {
            // The easiest way to bubble the revert reason is using memory via assembly
            /// @solidity memory-safe-assembly
            assembly {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert FailedInnerCall();
        }
    }
}

File 17 of 27 : IBFactory.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.25;

import {IBPool} from 'interfaces/IBPool.sol';

interface IBFactory {
  /**
   * @notice Emitted when creating a new pool
   * @param caller The caller of the function that will be set as the controller
   * @param bPool The address of the new pool
   */
  event LOG_NEW_POOL(address indexed caller, address indexed bPool);

  /**
   * @notice Emitted when setting the BDao address
   * @param caller The caller of the set BDao function
   * @param bDao The address of the new BDao
   */
  event LOG_BDAO(address indexed caller, address indexed bDao);

  /**
   * @notice Thrown when setting a variable to address zero
   */
  error BFactory_AddressZero();

  /**
   * @notice Thrown when caller is not BDao address
   */
  error BFactory_NotBDao();

  /**
   * @notice Creates a new BPool, assigning the caller as the pool controller
   * @param name The name of the Pool ERC20 token
   * @param symbol The symbol of the Pool ERC20 token
   * @return bPool The new BPool
   */
  function newBPool(string memory name, string memory symbol) external returns (IBPool bPool);

  /**
   * @notice Sets the BDao address in the factory
   * @param bDao The new BDao address
   */
  function setBDao(address bDao) external;

  /**
   * @notice Collects the fees of a pool and transfers it to BDao address
   * @param bPool The address of the pool to collect fees from
   */
  function collect(IBPool bPool) external;

  /**
   * @notice Checks if an address is a BPool created from this factory
   * @param bPool The address to check
   * @return isBPool True if the address is a BPool, False otherwise
   */
  function isBPool(address bPool) external view returns (bool isBPool);

  /**
   * @notice Gets the BDao address
   * @return bDao The address of the BDao
   */
  function getBDao() external view returns (address bDao);
}

File 18 of 27 : GPv2Interaction.sol
// SPDX-License-Identifier: LGPL-3.0-or-later
pragma solidity >=0.7.6 <0.9.0;

/// @title Gnosis Protocol v2 Interaction Library
/// @author Gnosis Developers
library GPv2Interaction {
    /// @dev Interaction data for performing arbitrary contract interactions.
    /// Submitted to [`GPv2Settlement.settle`] for code execution.
    struct Data {
        address target;
        uint256 value;
        bytes callData;
    }

    /// @dev Execute an arbitrary contract interaction.
    ///
    /// @param interaction Interaction data.
    function execute(Data calldata interaction) internal {
        address target = interaction.target;
        uint256 value = interaction.value;
        bytes calldata callData = interaction.callData;

        // NOTE: Use assembly to call the interaction instead of a low level
        // call for two reasons:
        // - We don't want to copy the return data, since we discard it for
        // interactions.
        // - Solidity will under certain conditions generate code to copy input
        // calldata twice to memory (the second being a "memcopy loop").
        // <https://github.com/gnosis/gp-v2-contracts/pull/417#issuecomment-775091258>
        // solhint-disable-next-line no-inline-assembly
        assembly {
            let freeMemoryPointer := mload(0x40)
            calldatacopy(freeMemoryPointer, callData.offset, callData.length)
            if iszero(
                call(
                    gas(),
                    target,
                    value,
                    freeMemoryPointer,
                    callData.length,
                    0,
                    0
                )
            ) {
                returndatacopy(0, 0, returndatasize())
                revert(0, returndatasize())
            }
        }
    }

    /// @dev Extracts the Solidity ABI selector for the specified interaction.
    ///
    /// @param interaction Interaction data.
    /// @return result The 4 byte function selector of the call encoded in
    /// this interaction.
    function selector(
        Data calldata interaction
    ) internal pure returns (bytes4 result) {
        bytes calldata callData = interaction.callData;
        if (callData.length >= 4) {
            // NOTE: Read the first word of the interaction's calldata. The
            // value does not need to be shifted since `bytesN` values are left
            // aligned, and the value does not need to be masked since masking
            // occurs when the value is accessed and not stored:
            // <https://docs.soliditylang.org/en/v0.7.6/abi-spec.html#encoding-of-indexed-event-parameters>
            // <https://docs.soliditylang.org/en/v0.7.6/assembly.html#access-to-external-variables-functions-and-libraries>
            // solhint-disable-next-line no-inline-assembly
            assembly {
                result := calldataload(callData.offset)
            }
        }
    }
}

File 19 of 27 : GPv2Trade.sol
// SPDX-License-Identifier: LGPL-3.0-or-later
pragma solidity >=0.7.6 <0.9.0;

import "../interfaces/IERC20.sol";
import "../mixins/GPv2Signing.sol";
import "./GPv2Order.sol";

/// @title Gnosis Protocol v2 Trade Library.
/// @author Gnosis Developers
library GPv2Trade {
    using GPv2Order for GPv2Order.Data;
    using GPv2Order for bytes;

    /// @dev A struct representing a trade to be executed as part a batch
    /// settlement.
    struct Data {
        uint256 sellTokenIndex;
        uint256 buyTokenIndex;
        address receiver;
        uint256 sellAmount;
        uint256 buyAmount;
        uint32 validTo;
        bytes32 appData;
        uint256 feeAmount;
        uint256 flags;
        uint256 executedAmount;
        bytes signature;
    }

    /// @dev Extracts the order data and signing scheme for the specified trade.
    ///
    /// @param trade The trade.
    /// @param tokens The list of tokens included in the settlement. The token
    /// indices in the trade parameters map to tokens in this array.
    /// @param order The memory location to extract the order data to.
    function extractOrder(
        Data calldata trade,
        IERC20[] calldata tokens,
        GPv2Order.Data memory order
    ) internal pure returns (GPv2Signing.Scheme signingScheme) {
        order.sellToken = tokens[trade.sellTokenIndex];
        order.buyToken = tokens[trade.buyTokenIndex];
        order.receiver = trade.receiver;
        order.sellAmount = trade.sellAmount;
        order.buyAmount = trade.buyAmount;
        order.validTo = trade.validTo;
        order.appData = trade.appData;
        order.feeAmount = trade.feeAmount;
        (
            order.kind,
            order.partiallyFillable,
            order.sellTokenBalance,
            order.buyTokenBalance,
            signingScheme
        ) = extractFlags(trade.flags);
    }

    /// @dev Decodes trade flags.
    ///
    /// Trade flags are used to tightly encode information on how to decode
    /// an order. Examples that directly affect the structure of an order are
    /// the kind of order (either a sell or a buy order) as well as whether the
    /// order is partially fillable or if it is a "fill-or-kill" order. It also
    /// encodes the signature scheme used to validate the order. As the most
    /// likely values are fill-or-kill sell orders by an externally owned
    /// account, the flags are chosen such that `0x00` represents this kind of
    /// order. The flags byte uses the following format:
    ///
    /// ```
    /// bit | 31 ...   | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
    /// ----+----------+-------+---+-------+---+---+
    ///     | reserved | *   * | * | *   * | * | * |
    ///                  |   |   |   |   |   |   |
    ///                  |   |   |   |   |   |   +---- order kind bit, 0 for a sell order
    ///                  |   |   |   |   |   |         and 1 for a buy order
    ///                  |   |   |   |   |   |
    ///                  |   |   |   |   |   +-------- order fill bit, 0 for fill-or-kill
    ///                  |   |   |   |   |             and 1 for a partially fillable order
    ///                  |   |   |   |   |
    ///                  |   |   |   +---+------------ use internal sell token balance bit:
    ///                  |   |   |                     0x: ERC20 token balance
    ///                  |   |   |                     10: external Balancer Vault balance
    ///                  |   |   |                     11: internal Balancer Vault balance
    ///                  |   |   |
    ///                  |   |   +-------------------- use buy token balance bit
    ///                  |   |                         0: ERC20 token balance
    ///                  |   |                         1: internal Balancer Vault balance
    ///                  |   |
    ///                  +---+------------------------ signature scheme bits:
    ///                                                00: EIP-712
    ///                                                01: eth_sign
    ///                                                10: EIP-1271
    ///                                                11: pre_sign
    /// ```
    function extractFlags(
        uint256 flags
    )
        internal
        pure
        returns (
            bytes32 kind,
            bool partiallyFillable,
            bytes32 sellTokenBalance,
            bytes32 buyTokenBalance,
            GPv2Signing.Scheme signingScheme
        )
    {
        if (flags & 0x01 == 0) {
            kind = GPv2Order.KIND_SELL;
        } else {
            kind = GPv2Order.KIND_BUY;
        }
        partiallyFillable = flags & 0x02 != 0;
        if (flags & 0x08 == 0) {
            sellTokenBalance = GPv2Order.BALANCE_ERC20;
        } else if (flags & 0x04 == 0) {
            sellTokenBalance = GPv2Order.BALANCE_EXTERNAL;
        } else {
            sellTokenBalance = GPv2Order.BALANCE_INTERNAL;
        }
        if (flags & 0x10 == 0) {
            buyTokenBalance = GPv2Order.BALANCE_ERC20;
        } else {
            buyTokenBalance = GPv2Order.BALANCE_INTERNAL;
        }

        // NOTE: Take advantage of the fact that Solidity will revert if the
        // following expression does not produce a valid enum value. This means
        // we check here that the leading reserved bits must be 0.
        signingScheme = GPv2Signing.Scheme(flags >> 5);
    }
}

File 20 of 27 : BConst.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.25;

/**
 * @title BConst
 * @notice Constants used in the scope of the BPool contract.
 */
contract BConst {
  /// @notice The unit of precision used in the calculations.
  uint256 public constant BONE = 10 ** 18;

  /// @notice The minimum number of bound tokens in a pool.
  uint256 public constant MIN_BOUND_TOKENS = 2;
  /// @notice The maximum number of bound tokens in a pool.
  uint256 public constant MAX_BOUND_TOKENS = 8;

  /// @notice The minimum swap fee that can be set.
  uint256 public constant MIN_FEE = BONE / 10 ** 6;
  /// @notice The maximum swap fee that can be set.
  uint256 public constant MAX_FEE = BONE - MIN_FEE;
  /// @notice The immutable exit fee percentage
  uint256 public constant EXIT_FEE = 0;

  /// @notice The minimum weight that a token can have.
  uint256 public constant MIN_WEIGHT = BONE;
  /// @notice The maximum weight that a token can have.
  uint256 public constant MAX_WEIGHT = BONE * 50;
  /// @notice The maximum sum of weights of all tokens in a pool.
  uint256 public constant MAX_TOTAL_WEIGHT = BONE * 50;
  /// @notice The minimum balance that a token must have.
  uint256 public constant MIN_BALANCE = BONE / 10 ** 12;

  /// @notice The initial total supply of the pool tokens (minted to the pool creator).
  uint256 public constant INIT_POOL_SUPPLY = BONE * 100;

  /// @notice The minimum base value for the bpow calculation.
  uint256 public constant MIN_BPOW_BASE = 1 wei;
  /// @notice The maximum base value for the bpow calculation.
  uint256 public constant MAX_BPOW_BASE = (2 * BONE) - 1 wei;
  /// @notice The precision of the bpow calculation.
  uint256 public constant BPOW_PRECISION = BONE / 10 ** 10;

  /// @notice The maximum ratio of input tokens vs the current pool balance.
  uint256 public constant MAX_IN_RATIO = BONE >> 1;
  /// @notice The maximum ratio of output tokens vs the current pool balance.
  uint256 public constant MAX_OUT_RATIO = (BONE / 3) + 1 wei;

  /**
   * @notice The storage slot used to write transient data.
   * @dev Using an arbitrary storage slot to prevent possible future
   * transient variables defined by solidity from overriding it.
   * @dev Value is: uint256(keccak256('BPool.transientStorageLock')) - 1;
   */
  uint256 internal constant _MUTEX_TRANSIENT_STORAGE_SLOT =
    0x3f8f4c536ce1b925b469af1b09a44da237dab5bbc584585648c12be1ca25a8c4;
  /// @notice The value representing an unlocked state of the mutex.
  bytes32 internal constant _MUTEX_FREE = bytes32(uint256(0));
  /// @notice The value representing a locked state of the mutex.
  bytes32 internal constant _MUTEX_TAKEN = bytes32(uint256(1));
}

File 21 of 27 : BNum.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.25;

import {BConst} from './BConst.sol';

/**
 * @title BNum
 * @notice Includes functions for arithmetic operations with fixed-point numbers.
 * @dev The arithmetic operations are implemented with a precision of BONE.
 */
// solhint-disable private-vars-leading-underscore
// solhint-disable named-return-values
contract BNum is BConst {
  /**
   * @notice Thrown when an overflow is encountered inside the add function
   */
  error BNum_AddOverflow();

  /**
   * @notice Thrown when an underflow is encountered inside the sub function
   */
  error BNum_SubUnderflow();

  /**
   * @notice Thrown when an overflow is encountered inside the mul function
   */
  error BNum_MulOverflow();

  /**
   * @notice Thrown when attempting to divide by zero
   */
  error BNum_DivZero();

  /**
   * @notice Thrown when an internal error occurs inside div function
   */
  error BNum_DivInternal();

  /**
   * @notice Thrown when the base is too low in the bpow function
   */
  error BNum_BPowBaseTooLow();

  /**
   * @notice Thrown when the base is too high in the bpow function
   */
  error BNum_BPowBaseTooHigh();

  function btoi(uint256 a) internal pure returns (uint256) {
    unchecked {
      return a / BONE;
    }
  }

  function bfloor(uint256 a) internal pure returns (uint256) {
    unchecked {
      return btoi(a) * BONE;
    }
  }

  function badd(uint256 a, uint256 b) internal pure returns (uint256) {
    unchecked {
      uint256 c = a + b;
      if (c < a) {
        revert BNum_AddOverflow();
      }
      return c;
    }
  }

  function bsub(uint256 a, uint256 b) internal pure returns (uint256) {
    unchecked {
      (uint256 c, bool flag) = bsubSign(a, b);
      if (flag) {
        revert BNum_SubUnderflow();
      }
      return c;
    }
  }

  function bsubSign(uint256 a, uint256 b) internal pure returns (uint256, bool) {
    unchecked {
      if (a >= b) {
        return (a - b, false);
      } else {
        return (b - a, true);
      }
    }
  }

  function bmul(uint256 a, uint256 b) internal pure returns (uint256) {
    unchecked {
      uint256 c0 = a * b;
      if (a != 0 && c0 / a != b) {
        revert BNum_MulOverflow();
      }
      // NOTE: using >> 1 instead of / 2
      uint256 c1 = c0 + (BONE >> 1);
      if (c1 < c0) {
        revert BNum_MulOverflow();
      }
      uint256 c2 = c1 / BONE;
      return c2;
    }
  }

  function bdiv(uint256 a, uint256 b) internal pure returns (uint256) {
    unchecked {
      if (b == 0) {
        revert BNum_DivZero();
      }
      uint256 c0 = a * BONE;
      if (a != 0 && c0 / a != BONE) {
        revert BNum_DivInternal(); // bmul overflow
      }
      // NOTE: using >> 1 instead of / 2
      uint256 c1 = c0 + (b >> 1);
      if (c1 < c0) {
        revert BNum_DivInternal(); //  badd require
      }
      uint256 c2 = c1 / b;
      return c2;
    }
  }

  // DSMath.wpow
  function bpowi(uint256 a, uint256 n) internal pure returns (uint256) {
    unchecked {
      uint256 z = n % 2 != 0 ? a : BONE;

      for (n /= 2; n != 0; n /= 2) {
        a = bmul(a, a);

        if (n % 2 != 0) {
          z = bmul(z, a);
        }
      }
      return z;
    }
  }

  // Compute b^(e.w) by splitting it into (b^e)*(b^0.w).
  // Use `bpowi` for `b^e` and `bpowK` for k iterations
  // of approximation of b^0.w
  function bpow(uint256 base, uint256 exp) internal pure returns (uint256) {
    unchecked {
      if (base < MIN_BPOW_BASE) {
        revert BNum_BPowBaseTooLow();
      }
      if (base > MAX_BPOW_BASE) {
        revert BNum_BPowBaseTooHigh();
      }

      uint256 whole = bfloor(exp);
      uint256 remain = bsub(exp, whole);

      uint256 wholePow = bpowi(base, btoi(whole));

      if (remain == 0) {
        return wholePow;
      }

      uint256 partialResult = bpowApprox(base, remain, BPOW_PRECISION);
      return bmul(wholePow, partialResult);
    }
  }

  function bpowApprox(uint256 base, uint256 exp, uint256 precision) internal pure returns (uint256) {
    unchecked {
      // term 0:
      uint256 a = exp;
      (uint256 x, bool xneg) = bsubSign(base, BONE);
      uint256 term = BONE;
      uint256 sum = term;
      bool negative = false;

      // term(k) = numer / denom
      //         = (product(a - i - 1, i=1-->k) * x^k) / (k!)
      // each iteration, multiply previous term by (a-(k-1)) * x / k
      // continue until term is less than precision
      for (uint256 i = 1; term >= precision; i++) {
        uint256 bigK = i * BONE;
        (uint256 c, bool cneg) = bsubSign(a, bsub(bigK, BONE));
        term = bmul(term, bmul(c, x));
        term = bdiv(term, bigK);
        if (term == 0) break;

        if (xneg) negative = !negative;
        if (cneg) negative = !negative;
        if (negative) {
          sum = bsub(sum, term);
        } else {
          sum = badd(sum, term);
        }
      }

      return sum;
    }
  }
}

File 22 of 27 : ERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/ERC20.sol)

pragma solidity ^0.8.20;

import {IERC20} from "./IERC20.sol";
import {IERC20Metadata} from "./extensions/IERC20Metadata.sol";
import {Context} from "../../utils/Context.sol";
import {IERC20Errors} from "../../interfaces/draft-IERC6093.sol";

/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * The default value of {decimals} is 18. To change this, you should override
 * this function so it returns a different value.
 *
 * We have followed general OpenZeppelin Contracts guidelines: functions revert
 * instead returning `false` on failure. This behavior is nonetheless
 * conventional and does not conflict with the expectations of ERC20
 * applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 */
abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {
    mapping(address account => uint256) private _balances;

    mapping(address account => mapping(address spender => uint256)) private _allowances;

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * All two of these values are immutable: they can only be set once during
     * construction.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @dev Returns the name of the token.
     */
    function name() public view virtual returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5.05` (`505 / 10 ** 2`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the default value returned by this function, unless
     * it's overridden.
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view virtual returns (uint8) {
        return 18;
    }

    /**
     * @dev See {IERC20-totalSupply}.
     */
    function totalSupply() public view virtual returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view virtual returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - the caller must have a balance of at least `value`.
     */
    function transfer(address to, uint256 value) public virtual returns (bool) {
        address owner = _msgSender();
        _transfer(owner, to, value);
        return true;
    }

    /**
     * @dev See {IERC20-allowance}.
     */
    function allowance(address owner, address spender) public view virtual returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on
     * `transferFrom`. This is semantically equivalent to an infinite approval.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 value) public virtual returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, value);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20}.
     *
     * NOTE: Does not update the allowance if the current allowance
     * is the maximum `uint256`.
     *
     * Requirements:
     *
     * - `from` and `to` cannot be the zero address.
     * - `from` must have a balance of at least `value`.
     * - the caller must have allowance for ``from``'s tokens of at least
     * `value`.
     */
    function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {
        address spender = _msgSender();
        _spendAllowance(from, spender, value);
        _transfer(from, to, value);
        return true;
    }

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to`.
     *
     * This internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead.
     */
    function _transfer(address from, address to, uint256 value) internal {
        if (from == address(0)) {
            revert ERC20InvalidSender(address(0));
        }
        if (to == address(0)) {
            revert ERC20InvalidReceiver(address(0));
        }
        _update(from, to, value);
    }

    /**
     * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`
     * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding
     * this function.
     *
     * Emits a {Transfer} event.
     */
    function _update(address from, address to, uint256 value) internal virtual {
        if (from == address(0)) {
            // Overflow check required: The rest of the code assumes that totalSupply never overflows
            _totalSupply += value;
        } else {
            uint256 fromBalance = _balances[from];
            if (fromBalance < value) {
                revert ERC20InsufficientBalance(from, fromBalance, value);
            }
            unchecked {
                // Overflow not possible: value <= fromBalance <= totalSupply.
                _balances[from] = fromBalance - value;
            }
        }

        if (to == address(0)) {
            unchecked {
                // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply.
                _totalSupply -= value;
            }
        } else {
            unchecked {
                // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256.
                _balances[to] += value;
            }
        }

        emit Transfer(from, to, value);
    }

    /**
     * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).
     * Relies on the `_update` mechanism
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead.
     */
    function _mint(address account, uint256 value) internal {
        if (account == address(0)) {
            revert ERC20InvalidReceiver(address(0));
        }
        _update(address(0), account, value);
    }

    /**
     * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply.
     * Relies on the `_update` mechanism.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead
     */
    function _burn(address account, uint256 value) internal {
        if (account == address(0)) {
            revert ERC20InvalidSender(address(0));
        }
        _update(account, address(0), value);
    }

    /**
     * @dev Sets `value` as the allowance of `spender` over the `owner` s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     *
     * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.
     */
    function _approve(address owner, address spender, uint256 value) internal {
        _approve(owner, spender, value, true);
    }

    /**
     * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event.
     *
     * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by
     * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any
     * `Approval` event during `transferFrom` operations.
     *
     * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to
     * true using the following override:
     * ```
     * function _approve(address owner, address spender, uint256 value, bool) internal virtual override {
     *     super._approve(owner, spender, value, true);
     * }
     * ```
     *
     * Requirements are the same as {_approve}.
     */
    function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual {
        if (owner == address(0)) {
            revert ERC20InvalidApprover(address(0));
        }
        if (spender == address(0)) {
            revert ERC20InvalidSpender(address(0));
        }
        _allowances[owner][spender] = value;
        if (emitEvent) {
            emit Approval(owner, spender, value);
        }
    }

    /**
     * @dev Updates `owner` s allowance for `spender` based on spent `value`.
     *
     * Does not update the allowance value in case of infinite allowance.
     * Revert if not enough allowance is available.
     *
     * Does not emit an {Approval} event.
     */
    function _spendAllowance(address owner, address spender, uint256 value) internal virtual {
        uint256 currentAllowance = allowance(owner, spender);
        if (currentAllowance != type(uint256).max) {
            if (currentAllowance < value) {
                revert ERC20InsufficientAllowance(spender, currentAllowance, value);
            }
            unchecked {
                _approve(owner, spender, currentAllowance - value, false);
            }
        }
    }
}

File 23 of 27 : GPv2Signing.sol
// SPDX-License-Identifier: LGPL-3.0-or-later
pragma solidity >=0.7.6 <0.9.0;

import "../interfaces/GPv2EIP1271.sol";
import "../libraries/GPv2Order.sol";
import "../libraries/GPv2Trade.sol";

/// @title Gnosis Protocol v2 Signing Library.
/// @author Gnosis Developers
abstract contract GPv2Signing {
    using GPv2Order for GPv2Order.Data;
    using GPv2Order for bytes;

    /// @dev Recovered trade data containing the extracted order and the
    /// recovered owner address.
    struct RecoveredOrder {
        GPv2Order.Data data;
        bytes uid;
        address owner;
        address receiver;
    }

    /// @dev Signing scheme used for recovery.
    enum Scheme {
        Eip712,
        EthSign,
        Eip1271,
        PreSign
    }

    /// @dev The EIP-712 domain type hash used for computing the domain
    /// separator.
    bytes32 private constant DOMAIN_TYPE_HASH =
        keccak256(
            "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
        );

    /// @dev The EIP-712 domain name used for computing the domain separator.
    bytes32 private constant DOMAIN_NAME = keccak256("Gnosis Protocol");

    /// @dev The EIP-712 domain version used for computing the domain separator.
    bytes32 private constant DOMAIN_VERSION = keccak256("v2");

    /// @dev Marker value indicating an order is pre-signed.
    uint256 private constant PRE_SIGNED =
        uint256(keccak256("GPv2Signing.Scheme.PreSign"));

    /// @dev The domain separator used for signing orders that gets mixed in
    /// making signatures for different domains incompatible. This domain
    /// separator is computed following the EIP-712 standard and has replay
    /// protection mixed in so that signed orders are only valid for specific
    /// GPv2 contracts.
    bytes32 public immutable domainSeparator;

    /// @dev Storage indicating whether or not an order has been signed by a
    /// particular address.
    mapping(bytes => uint256) public preSignature;

    /// @dev Event that is emitted when an account either pre-signs an order or
    /// revokes an existing pre-signature.
    event PreSignature(address indexed owner, bytes orderUid, bool signed);

    constructor() {
        // NOTE: Currently, the only way to get the chain ID in solidity is
        // using assembly.
        uint256 chainId;
        // solhint-disable-next-line no-inline-assembly
        assembly {
            chainId := chainid()
        }

        domainSeparator = keccak256(
            abi.encode(
                DOMAIN_TYPE_HASH,
                DOMAIN_NAME,
                DOMAIN_VERSION,
                chainId,
                address(this)
            )
        );
    }

    /// @dev Sets a presignature for the specified order UID.
    ///
    /// @param orderUid The unique identifier of the order to pre-sign.
    /// @param signed True to set the order as tradable with pre-sign, false to
    /// false to unset it.
    function setPreSignature(bytes calldata orderUid, bool signed) external {
        (, address owner, ) = orderUid.extractOrderUidParams();
        require(owner == msg.sender, "GPv2: cannot presign order");
        if (signed) {
            preSignature[orderUid] = PRE_SIGNED;
        } else {
            preSignature[orderUid] = 0;
        }
        emit PreSignature(owner, orderUid, signed);
    }

    /// @dev Returns an empty recovered order with a pre-allocated buffer for
    /// packing the unique identifier.
    ///
    /// @return recoveredOrder The empty recovered order data.
    function allocateRecoveredOrder()
        internal
        pure
        returns (RecoveredOrder memory recoveredOrder)
    {
        recoveredOrder.uid = new bytes(GPv2Order.UID_LENGTH);
    }

    /// @dev Extracts order data and recovers the signer from the specified
    /// trade.
    ///
    /// @param recoveredOrder Memory location used for writing the recovered order data.
    /// @param tokens The list of tokens included in the settlement. The token
    /// indices in the trade parameters map to tokens in this array.
    /// @param trade The trade data to recover the order data from.
    function recoverOrderFromTrade(
        RecoveredOrder memory recoveredOrder,
        IERC20[] calldata tokens,
        GPv2Trade.Data calldata trade
    ) internal view {
        GPv2Order.Data memory order = recoveredOrder.data;

        Scheme signingScheme = GPv2Trade.extractOrder(trade, tokens, order);
        (bytes32 orderDigest, address owner) = recoverOrderSigner(
            order,
            signingScheme,
            trade.signature
        );

        recoveredOrder.uid.packOrderUidParams(
            orderDigest,
            owner,
            order.validTo
        );
        recoveredOrder.owner = owner;
        recoveredOrder.receiver = order.actualReceiver(owner);
    }

    /// @dev The length of any signature from an externally owned account.
    uint256 private constant ECDSA_SIGNATURE_LENGTH = 65;

    /// @dev Recovers an order's signer from the specified order and signature.
    ///
    /// @param order The order to recover a signature for.
    /// @param signingScheme The signing scheme.
    /// @param signature The signature bytes.
    /// @return orderDigest The computed order hash.
    /// @return owner The recovered address from the specified signature.
    function recoverOrderSigner(
        GPv2Order.Data memory order,
        Scheme signingScheme,
        bytes calldata signature
    ) internal view returns (bytes32 orderDigest, address owner) {
        orderDigest = order.hash(domainSeparator);
        if (signingScheme == Scheme.Eip712) {
            owner = recoverEip712Signer(orderDigest, signature);
        } else if (signingScheme == Scheme.EthSign) {
            owner = recoverEthsignSigner(orderDigest, signature);
        } else if (signingScheme == Scheme.Eip1271) {
            owner = recoverEip1271Signer(orderDigest, signature);
        } else {
            // signingScheme == Scheme.PreSign
            owner = recoverPreSigner(orderDigest, signature, order.validTo);
        }
    }

    /// @dev Perform an ECDSA recover for the specified message and calldata
    /// signature.
    ///
    /// The signature is encoded by tighyly packing the following struct:
    /// ```
    /// struct EncodedSignature {
    ///     bytes32 r;
    ///     bytes32 s;
    ///     uint8 v;
    /// }
    /// ```
    ///
    /// @param message The signed message.
    /// @param encodedSignature The encoded signature.
    function ecdsaRecover(
        bytes32 message,
        bytes calldata encodedSignature
    ) internal pure returns (address signer) {
        require(
            encodedSignature.length == ECDSA_SIGNATURE_LENGTH,
            "GPv2: malformed ecdsa signature"
        );

        bytes32 r;
        bytes32 s;
        uint8 v;

        // NOTE: Use assembly to efficiently decode signature data.
        // solhint-disable-next-line no-inline-assembly
        assembly {
            // r = uint256(encodedSignature[0:32])
            r := calldataload(encodedSignature.offset)
            // s = uint256(encodedSignature[32:64])
            s := calldataload(add(encodedSignature.offset, 32))
            // v = uint8(encodedSignature[64])
            v := shr(248, calldataload(add(encodedSignature.offset, 64)))
        }

        signer = ecrecover(message, v, r, s);
        require(signer != address(0), "GPv2: invalid ecdsa signature");
    }

    /// @dev Decodes signature bytes originating from an EIP-712-encoded
    /// signature.
    ///
    /// EIP-712 signs typed data. The specifications are described in the
    /// related EIP (<https://eips.ethereum.org/EIPS/eip-712>).
    ///
    /// EIP-712 signatures are encoded as standard ECDSA signatures as described
    /// in the corresponding decoding function [`ecdsaRecover`].
    ///
    /// @param orderDigest The EIP-712 signing digest derived from the order
    /// parameters.
    /// @param encodedSignature Calldata pointing to tightly packed signature
    /// bytes.
    /// @return owner The address of the signer.
    function recoverEip712Signer(
        bytes32 orderDigest,
        bytes calldata encodedSignature
    ) internal pure returns (address owner) {
        owner = ecdsaRecover(orderDigest, encodedSignature);
    }

    /// @dev Decodes signature bytes originating from the output of the eth_sign
    /// RPC call.
    ///
    /// The specifications are described in the Ethereum documentation
    /// (<https://eth.wiki/json-rpc/API#eth_sign>).
    ///
    /// eth_sign signatures are encoded as standard ECDSA signatures as
    /// described in the corresponding decoding function
    /// [`ecdsaRecover`].
    ///
    /// @param orderDigest The EIP-712 signing digest derived from the order
    /// parameters.
    /// @param encodedSignature Calldata pointing to tightly packed signature
    /// bytes.
    /// @return owner The address of the signer.
    function recoverEthsignSigner(
        bytes32 orderDigest,
        bytes calldata encodedSignature
    ) internal pure returns (address owner) {
        // The signed message is encoded as:
        // `"\x19Ethereum Signed Message:\n" || length || data`, where
        // the length is a constant (32 bytes) and the data is defined as:
        // `orderDigest`.
        bytes32 ethsignDigest = keccak256(
            abi.encodePacked("\x19Ethereum Signed Message:\n32", orderDigest)
        );

        owner = ecdsaRecover(ethsignDigest, encodedSignature);
    }

    /// @dev Verifies the input calldata as an EIP-1271 contract signature and
    /// returns the address of the signer.
    ///
    /// The encoded signature tightly packs the following struct:
    ///
    /// ```
    /// struct EncodedEip1271Signature {
    ///     address owner;
    ///     bytes signature;
    /// }
    /// ```
    ///
    /// This function enforces that the encoded data stores enough bytes to
    /// cover the full length of the decoded signature.
    ///
    /// @param encodedSignature The encoded EIP-1271 signature.
    /// @param orderDigest The EIP-712 signing digest derived from the order
    /// parameters.
    /// @return owner The address of the signer.
    function recoverEip1271Signer(
        bytes32 orderDigest,
        bytes calldata encodedSignature
    ) internal view returns (address owner) {
        // NOTE: Use assembly to read the verifier address from the encoded
        // signature bytes.
        // solhint-disable-next-line no-inline-assembly
        assembly {
            // owner = address(encodedSignature[0:20])
            owner := shr(96, calldataload(encodedSignature.offset))
        }

        // NOTE: Configure prettier to ignore the following line as it causes
        // a panic in the Solidity plugin.
        // prettier-ignore
        bytes calldata signature = encodedSignature[20:];

        require(
            EIP1271Verifier(owner).isValidSignature(orderDigest, signature) ==
                GPv2EIP1271.MAGICVALUE,
            "GPv2: invalid eip1271 signature"
        );
    }

    /// @dev Verifies the order has been pre-signed. The signature is the
    /// address of the signer of the order.
    ///
    /// @param orderDigest The EIP-712 signing digest derived from the order
    /// parameters.
    /// @param encodedSignature The pre-sign signature reprenting the order UID.
    /// @param validTo The order expiry timestamp.
    /// @return owner The address of the signer.
    function recoverPreSigner(
        bytes32 orderDigest,
        bytes calldata encodedSignature,
        uint32 validTo
    ) internal view returns (address owner) {
        require(encodedSignature.length == 20, "GPv2: malformed presignature");
        // NOTE: Use assembly to read the owner address from the encoded
        // signature bytes.
        // solhint-disable-next-line no-inline-assembly
        assembly {
            // owner = address(encodedSignature[0:20])
            owner := shr(96, calldataload(encodedSignature.offset))
        }

        bytes memory orderUid = new bytes(GPv2Order.UID_LENGTH);
        orderUid.packOrderUidParams(orderDigest, owner, validTo);

        require(
            preSignature[orderUid] == PRE_SIGNED,
            "GPv2: order not presigned"
        );
    }
}

File 24 of 27 : IERC20Metadata.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../IERC20.sol";

/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}

File 25 of 27 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}

File 26 of 27 : draft-IERC6093.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol)
pragma solidity ^0.8.20;

/**
 * @dev Standard ERC20 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 tokens.
 */
interface IERC20Errors {
    /**
     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param balance Current balance for the interacting account.
     * @param needed Minimum amount required to perform a transfer.
     */
    error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC20InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC20InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.
     * @param spender Address that may be allowed to operate on tokens without being their owner.
     * @param allowance Amount of tokens a `spender` is allowed to operate with.
     * @param needed Minimum amount required to perform a transfer.
     */
    error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC20InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `spender` to be approved. Used in approvals.
     * @param spender Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC20InvalidSpender(address spender);
}

/**
 * @dev Standard ERC721 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens.
 */
interface IERC721Errors {
    /**
     * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-20.
     * Used in balance queries.
     * @param owner Address of the current owner of a token.
     */
    error ERC721InvalidOwner(address owner);

    /**
     * @dev Indicates a `tokenId` whose `owner` is the zero address.
     * @param tokenId Identifier number of a token.
     */
    error ERC721NonexistentToken(uint256 tokenId);

    /**
     * @dev Indicates an error related to the ownership over a particular token. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param tokenId Identifier number of a token.
     * @param owner Address of the current owner of a token.
     */
    error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC721InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC721InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     * @param tokenId Identifier number of a token.
     */
    error ERC721InsufficientApproval(address operator, uint256 tokenId);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC721InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC721InvalidOperator(address operator);
}

/**
 * @dev Standard ERC1155 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 tokens.
 */
interface IERC1155Errors {
    /**
     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param balance Current balance for the interacting account.
     * @param needed Minimum amount required to perform a transfer.
     * @param tokenId Identifier number of a token.
     */
    error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC1155InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC1155InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     * @param owner Address of the current owner of a token.
     */
    error ERC1155MissingApprovalForAll(address operator, address owner);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC1155InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC1155InvalidOperator(address operator);

    /**
     * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.
     * Used in batch transfers.
     * @param idsLength Length of the array of token identifiers
     * @param valuesLength Length of the array of token amounts
     */
    error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
}

File 27 of 27 : GPv2EIP1271.sol
// SPDX-License-Identifier: LGPL-3.0-or-later
pragma solidity >=0.7.6 <0.9.0;

library GPv2EIP1271 {
    /// @dev Value returned by a call to `isValidSignature` if the signature
    /// was verified successfully. The value is defined in EIP-1271 as:
    /// bytes4(keccak256("isValidSignature(bytes32,bytes)"))
    bytes4 internal constant MAGICVALUE = 0x1626ba7e;
}

/// @title EIP1271 Interface
/// @dev Standardized interface for an implementation of smart contract
/// signatures as described in EIP-1271. The code that follows is identical to
/// the code in the standard with the exception of formatting and syntax
/// changes to adapt the code to our Solidity version.
interface EIP1271Verifier {
    /// @dev Should return whether the signature provided is valid for the
    /// provided data
    /// @param _hash      Hash of the data to be signed
    /// @param _signature Signature byte array associated with _data
    ///
    /// MUST return the bytes4 magic value 0x1626ba7e when function passes.
    /// MUST NOT modify state (using STATICCALL for solc < 0.5, view modifier for
    /// solc > 0.5)
    /// MUST allow external calls
    ///
    function isValidSignature(
        bytes32 _hash,
        bytes memory _signature
    ) external view returns (bytes4 magicValue);
}

Settings
{
  "remappings": [
    "ds-test/=node_modules/ds-test/src/",
    "forge-std/=node_modules/forge-std/src/",
    "forge-gas-snapshot/=node_modules/forge-gas-snapshot/src/",
    "solmate/=node_modules/solmate/src/",
    "@cowprotocol/=node_modules/@cowprotocol/contracts/src/contracts/",
    "cowprotocol/=node_modules/@cowprotocol/contracts/src/",
    "@composable-cow/=node_modules/composable-cow/",
    "@cow-amm/=node_modules/cow-amm/src/",
    "lib/openzeppelin/=node_modules/@openzeppelin/",
    "contracts/=src/contracts/",
    "interfaces/=src/interfaces/",
    "libraries/=src/libraries/",
    "@openzeppelin/=node_modules/@openzeppelin/",
    "composable-cow/=node_modules/composable-cow/",
    "cow-amm/=node_modules/cow-amm/",
    "erc4626-tests/=node_modules/composable-cow/lib/@openzeppelin/lib/erc4626-tests/",
    "murky/=node_modules/composable-cow/lib/murky/src/",
    "openzeppelin-contracts/=node_modules/composable-cow/lib/murky/lib/openzeppelin-contracts/",
    "safe/=node_modules/composable-cow/lib/safe/contracts/",
    "lib/composable-cow:@openzeppelin/=node_modules/cow-amm/lib/openzeppelin/contracts/",
    "lib/composable-cow:@openzeppelin/contracts/=node_modules/cow-amm/lib/openzeppelin/contracts/",
    "lib/composable-cow:cowprotocol/=node_modules/cow-amm/lib/composable-cow/lib/cowprotocol/src/",
    "lib/composable-cow:safe/=node_modules/cow-amm/lib/composable-cow/lib/safe/contracts/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 500
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "cancun",
  "viaIR": false,
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"cowSolutionSettler","type":"address"},{"internalType":"bytes32","name":"appData","type":"bytes32"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"}],"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":"AppDataDoesNotMatch","type":"error"},{"inputs":[],"name":"BCoWPool_FeeMustBeZero","type":"error"},{"inputs":[],"name":"BCoWPool_InvalidBalanceMarker","type":"error"},{"inputs":[],"name":"BCoWPool_InvalidOperation","type":"error"},{"inputs":[],"name":"BCoWPool_OrderValidityTooLong","type":"error"},{"inputs":[],"name":"BCoWPool_ReceiverIsNotBCoWPool","type":"error"},{"inputs":[],"name":"BNum_AddOverflow","type":"error"},{"inputs":[],"name":"BNum_BPowBaseTooHigh","type":"error"},{"inputs":[],"name":"BNum_BPowBaseTooLow","type":"error"},{"inputs":[],"name":"BNum_DivInternal","type":"error"},{"inputs":[],"name":"BNum_DivZero","type":"error"},{"inputs":[],"name":"BNum_MulOverflow","type":"error"},{"inputs":[],"name":"BNum_SubUnderflow","type":"error"},{"inputs":[],"name":"BPool_AddressZero","type":"error"},{"inputs":[],"name":"BPool_BalanceBelowMinimum","type":"error"},{"inputs":[],"name":"BPool_CallerIsNotController","type":"error"},{"inputs":[],"name":"BPool_FeeAboveMaximum","type":"error"},{"inputs":[],"name":"BPool_FeeBelowMinimum","type":"error"},{"inputs":[],"name":"BPool_InvalidPoolAmountIn","type":"error"},{"inputs":[],"name":"BPool_InvalidPoolRatio","type":"error"},{"inputs":[],"name":"BPool_InvalidTokenAmountIn","type":"error"},{"inputs":[],"name":"BPool_InvalidTokenAmountOut","type":"error"},{"inputs":[],"name":"BPool_PoolAmountInAboveMaxPoolAmountIn","type":"error"},{"inputs":[],"name":"BPool_PoolAmountOutBelowMinPoolAmountOut","type":"error"},{"inputs":[],"name":"BPool_PoolIsFinalized","type":"error"},{"inputs":[],"name":"BPool_PoolNotFinalized","type":"error"},{"inputs":[],"name":"BPool_Reentrancy","type":"error"},{"inputs":[],"name":"BPool_SpotPriceAboveMaxPrice","type":"error"},{"inputs":[],"name":"BPool_SpotPriceAfterBelowSpotPriceBefore","type":"error"},{"inputs":[],"name":"BPool_SpotPriceBeforeAboveTokenRatio","type":"error"},{"inputs":[],"name":"BPool_TokenAlreadyBound","type":"error"},{"inputs":[],"name":"BPool_TokenAmountInAboveMaxAmountIn","type":"error"},{"inputs":[],"name":"BPool_TokenAmountInAboveMaxRatio","type":"error"},{"inputs":[],"name":"BPool_TokenAmountOutAboveMaxOut","type":"error"},{"inputs":[],"name":"BPool_TokenAmountOutBelowMinAmountOut","type":"error"},{"inputs":[],"name":"BPool_TokenAmountOutBelowMinOut","type":"error"},{"inputs":[],"name":"BPool_TokenNotBound","type":"error"},{"inputs":[],"name":"BPool_TokensAboveMaximum","type":"error"},{"inputs":[],"name":"BPool_TokensBelowMinimum","type":"error"},{"inputs":[],"name":"BPool_TotalWeightAboveMaximum","type":"error"},{"inputs":[],"name":"BPool_WeightAboveMaximum","type":"error"},{"inputs":[],"name":"BPool_WeightBelowMinimum","type":"error"},{"inputs":[],"name":"CommitOutsideOfSettlement","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":"OrderDoesNotMatchCommitmentHash","type":"error"},{"inputs":[],"name":"OrderDoesNotMatchMessageHash","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","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":[{"indexed":true,"internalType":"address","name":"bCoWPool","type":"address"}],"name":"COWAMMPoolCreated","type":"event"},{"anonymous":true,"inputs":[{"indexed":true,"internalType":"bytes4","name":"sig","type":"bytes4"},{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"LOG_CALL","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"tokenOut","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenAmountOut","type":"uint256"}],"name":"LOG_EXIT","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"tokenIn","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenAmountIn","type":"uint256"}],"name":"LOG_JOIN","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"tokenIn","type":"address"},{"indexed":true,"internalType":"address","name":"tokenOut","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenAmountIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokenAmountOut","type":"uint256"}],"name":"LOG_SWAP","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":"APP_DATA","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BONE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BPOW_PRECISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EXIT_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FACTORY","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"INIT_POOL_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_BOUND_TOKENS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_BPOW_BASE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_IN_RATIO","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_ORDER_DURATION","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_OUT_RATIO","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_TOTAL_WEIGHT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_WEIGHT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_BALANCE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_BOUND_TOKENS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_BPOW_BASE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_WEIGHT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SOLUTION_SETTLER","outputs":[{"internalType":"contract ISettlement","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SOLUTION_SETTLER_DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VAULT_RELAYER","outputs":[{"internalType":"address","name":"","type":"address"}],"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":"value","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":"address","name":"token","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"denorm","type":"uint256"}],"name":"bind","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenBalanceIn","type":"uint256"},{"internalType":"uint256","name":"tokenWeightIn","type":"uint256"},{"internalType":"uint256","name":"tokenBalanceOut","type":"uint256"},{"internalType":"uint256","name":"tokenWeightOut","type":"uint256"},{"internalType":"uint256","name":"tokenAmountOut","type":"uint256"},{"internalType":"uint256","name":"swapFee","type":"uint256"}],"name":"calcInGivenOut","outputs":[{"internalType":"uint256","name":"tokenAmountIn","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenBalanceIn","type":"uint256"},{"internalType":"uint256","name":"tokenWeightIn","type":"uint256"},{"internalType":"uint256","name":"tokenBalanceOut","type":"uint256"},{"internalType":"uint256","name":"tokenWeightOut","type":"uint256"},{"internalType":"uint256","name":"tokenAmountIn","type":"uint256"},{"internalType":"uint256","name":"swapFee","type":"uint256"}],"name":"calcOutGivenIn","outputs":[{"internalType":"uint256","name":"tokenAmountOut","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenBalanceIn","type":"uint256"},{"internalType":"uint256","name":"tokenWeightIn","type":"uint256"},{"internalType":"uint256","name":"tokenBalanceOut","type":"uint256"},{"internalType":"uint256","name":"tokenWeightOut","type":"uint256"},{"internalType":"uint256","name":"swapFee","type":"uint256"}],"name":"calcSpotPrice","outputs":[{"internalType":"uint256","name":"spotPrice","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"name":"commit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"decreaseApproval","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"poolAmountIn","type":"uint256"},{"internalType":"uint256[]","name":"minAmountsOut","type":"uint256[]"}],"name":"exitPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"finalize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"getBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getController","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentTokens","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"getDenormalizedWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFinalTokens","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"getNormalizedWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNumTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"}],"name":"getSpotPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"}],"name":"getSpotPriceSansFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSwapFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalDenormalizedWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"increaseApproval","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"isBound","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isFinalized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"orderHash","type":"bytes32"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"isValidSignature","outputs":[{"internalType":"bytes4","name":"magicValue","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"poolAmountOut","type":"uint256"},{"internalType":"uint256[]","name":"maxAmountsIn","type":"uint256[]"}],"name":"joinPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newController","type":"address"}],"name":"setController","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"swapFee","type":"uint256"}],"name":"setSwapFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"uint256","name":"tokenAmountIn","type":"uint256"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"minAmountOut","type":"uint256"},{"internalType":"uint256","name":"maxPrice","type":"uint256"}],"name":"swapExactAmountIn","outputs":[{"internalType":"uint256","name":"tokenAmountOut","type":"uint256"},{"internalType":"uint256","name":"spotPriceAfter","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"uint256","name":"maxAmountIn","type":"uint256"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"tokenAmountOut","type":"uint256"},{"internalType":"uint256","name":"maxPrice","type":"uint256"}],"name":"swapExactAmountOut","outputs":[{"internalType":"uint256","name":"tokenAmountIn","type":"uint256"},{"internalType":"uint256","name":"spotPriceAfter","type":"uint256"}],"stateMutability":"nonpayable","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":"value","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":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"unbind","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"sellToken","type":"address"},{"internalType":"contract IERC20","name":"buyToken","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"sellAmount","type":"uint256"},{"internalType":"uint256","name":"buyAmount","type":"uint256"},{"internalType":"uint32","name":"validTo","type":"uint32"},{"internalType":"bytes32","name":"appData","type":"bytes32"},{"internalType":"uint256","name":"feeAmount","type":"uint256"},{"internalType":"bytes32","name":"kind","type":"bytes32"},{"internalType":"bool","name":"partiallyFillable","type":"bool"},{"internalType":"bytes32","name":"sellTokenBalance","type":"bytes32"},{"internalType":"bytes32","name":"buyTokenBalance","type":"bytes32"}],"internalType":"struct GPv2Order.Data","name":"order","type":"tuple"}],"name":"verify","outputs":[],"stateMutability":"view","type":"function"}]

Deployed Bytecode

0x608060405234801561000f575f80fd5b506004361061039e575f3560e01c80639381cd2b116101ea578063c36596a611610114578063dd62ed3e116100a9578063f14fcbc811610079578063f14fcbc8146107fa578063f1b8a9b71461080d578063f8b2cb4f14610820578063f8d6aed414610833575f80fd5b8063dd62ed3e146107a0578063e4a28a52146103e3578063e4e1e538146107d8578063ec093021146107eb575f80fd5b8063cf5e7bd3116100e4578063cf5e7bd31461074b578063d4cadf681461075e578063d73dd62314610766578063da08c4dc14610779575f80fd5b8063c36596a61461045b578063c6580d1214610734578063cc77828d1461073b578063cd2ed8fb14610743575f80fd5b8063b02f0b731161018a578063ba9530a61161015a578063ba9530a6146106fc578063bc063e1a1461070f578063bc694ea214610717578063be3bbd2e1461071f575f80fd5b8063b02f0b73146106d1578063b0e0d136146106e4578063b7b800a4146106ec578063ba019dab146106f4575f80fd5b8063981a160b116101c5578063981a160b14610685578063992e2a92146106a3578063a221ee49146106ab578063a9059cbb146106be575f80fd5b80639381cd2b14610662578063948d8ce61461066a57806395d89b411461067d575f80fd5b8063313ce567116102cb57806376c7a3c71161026b5780638b54ab1f1161023b5780638b54ab1f146106155780638d4e40831461063c57806392eefe9b14610647578063936c34771461065a575f80fd5b806376c7a3c7146105ca5780637c5e9ea4146105d25780638201aa3f146105fa578063867378c51461060d575f80fd5b80634f69c0d4116102a65780634f69c0d41461055557806366188463146105685780636dbc88131461057b57806370a08231146105a2575f80fd5b8063313ce5671461052b57806334e199071461053a5780634bb278f31461054d575f80fd5b8063189d00ca1161034157806328bd64431161031157806328bd6443146104bc5780632dd31000146104d15780632f37b624146104f85780633018205f14610523575f80fd5b8063189d00ca14610453578063218b53821461045b57806323b872dd1461046a5780632626f2941461047d575f80fd5b80631446a7ff1161037c5780631446a7ff146103f957806315e84af91461040c5780631626ba7e1461041f57806318160ddd1461044b575f80fd5b806306fdde03146103a2578063095ea7b3146103c057806309a3bbe4146103e3575b5f80fd5b6103aa610846565b6040516103b791906137f9565b60405180910390f35b6103d36103ce36600461384d565b6108d6565b60405190151581526020016103b7565b6103eb6108ef565b6040519081526020016103b7565b6103eb610407366004613877565b610905565b6103eb61041a366004613877565b610aa4565b61043261042d36600461391d565b610c3c565b6040516001600160e01b031990911681526020016103b7565b6002546103eb565b6103eb610d6e565b6103eb670de0b6b3a764000081565b6103d36104783660046139b6565b610d85565b6104a47f000000000000000000000000c92e8bdf79f0507f65a392b0ab4667716bfe011081565b6040516001600160a01b0390911681526020016103b7565b6104cf6104ca366004613a28565b610daa565b005b6104a47f000000000000000000000000f76c421bab7df8548604e60deccce50477c1046281565b6103d3610506366004613ae4565b6001600160a01b03165f9081526009602052604090205460ff1690565b6104a46110e9565b604051601281526020016103b7565b6104cf610548366004613aff565b611127565b6104cf611272565b6104cf610563366004613b16565b6113ab565b6103d361057636600461384d565b6115f0565b6103eb7f362e5182440b52aa8fffe70a251550fbbcbca424740fe5a14f59bf0c1b06fe1d81565b6103eb6105b0366004613ae4565b6001600160a01b03165f9081526020819052604090205490565b6103eb61163f565b6105e56105e0366004613b8e565b611654565b604080519283526020830191909152016103b7565b6105e5610608366004613b8e565b611a09565b6103eb611d8f565b6104a47f0000000000000000000000009008d19f58aabd9ed0d60971565aa8510560ab4181565b60075460ff166103d3565b6104cf610655366004613ae4565b611da6565b6103eb611e8b565b6103eb611ec0565b6103eb610678366004613ae4565b611ed3565b6103aa611f5b565b61068e61012c81565b60405163ffffffff90911681526020016103b7565b6103eb611f6a565b6103eb6106b9366004613bdc565b611f88565b6103d36106cc36600461384d565b611fee565b6104cf6106df366004613b16565b611ffb565b6103eb600881565b6103eb600281565b6103eb600181565b6103eb61070a366004613c13565b612281565b6103eb6122fd565b6103eb612324565b610727612343565b6040516103b79190613c52565b6103eb5f81565b6107276123f2565b6008546103eb565b6104cf610759366004613ae4565b612421565b6103eb61270e565b6103d361077436600461384d565b612743565b6103eb7fc078f884a2676e1345748b1feace7b0abee5d00ecadb6e574dcdd109a63e894381565b6103eb6107ae366004613877565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205490565b6104cf6107e6366004613c9e565b612782565b6103eb6706f05b59d3b2000081565b6104cf610808366004613aff565b612a19565b6103eb61081b366004613ae4565b612a98565b6103eb61082e366004613ae4565b612b27565b6103eb610841366004613c13565b612bf3565b60606003805461085590613cd0565b80601f016020809104026020016040519081016040528092919081815260200182805461088190613cd0565b80156108cc5780601f106108a3576101008083540402835291602001916108cc565b820191905f5260205f20905b8154815290600101906020018083116108af57829003601f168201915b5050505050905090565b5f336108e3818585612c72565b60019150505b92915050565b610902670de0b6b3a76400006032613d1c565b81565b5f5f80516020613f088339815191525c156109335760405163d56a08b560e01b815260040160405180910390fd5b6001600160a01b0383165f9081526009602052604090205460ff1661096b57604051634b16fc2d60e11b815260040160405180910390fd5b6001600160a01b0382165f9081526009602052604090205460ff166109a357604051634b16fc2d60e11b815260040160405180910390fd5b6001600160a01b038381165f8181526009602052604080822093861682529081902090516370a0823160e01b81523060048201529091610a9b916370a0823190602401602060405180830381865afa158015610a01573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a259190613d33565b60028401546040516370a0823160e01b81523060048201526001600160a01b038816906370a0823190602401602060405180830381865afa158015610a6c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a909190613d33565b84600201545f611f88565b95945050505050565b5f5f80516020613f088339815191525c15610ad25760405163d56a08b560e01b815260040160405180910390fd5b6001600160a01b0383165f9081526009602052604090205460ff16610b0a57604051634b16fc2d60e11b815260040160405180910390fd5b6001600160a01b0382165f9081526009602052604090205460ff16610b4257604051634b16fc2d60e11b815260040160405180910390fd5b6001600160a01b038381165f8181526009602052604080822093861682529081902090516370a0823160e01b81523060048201529091610a9b916370a0823190602401602060405180830381865afa158015610ba0573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bc49190613d33565b60028401546040516370a0823160e01b81523060048201526001600160a01b038816906370a0823190602401602060405180830381865afa158015610c0b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c2f9190613d33565b8460020154600654611f88565b5f8082806020019051810190610c529190613d6b565b90507f362e5182440b52aa8fffe70a251550fbbcbca424740fe5a14f59bf0c1b06fe1d8160c0015114610c9857604051630e1a1b6360e41b815260040160405180910390fd5b601f19810180517fd5a25ba2e97094ad7d83dc28a6572da797d6b3e7fc6663bd93efb789fc17e48982526101a08220915260405161190160f01b81527fc078f884a2676e1345748b1feace7b0abee5d00ecadb6e574dcdd109a63e89436002820152602281019190915260429020848114610d265760405163593fcacd60e01b815260040160405180910390fd5b5f80516020613f088339815191525c8114610d545760405163dafbdd1f60e01b815260040160405180910390fd5b610d5d82610daa565b50630b135d3f60e11b949350505050565b6109026402540be400670de0b6b3a7640000613e3b565b5f33610d92858285612c7f565b610d9d858585612cff565b60019150505b9392505050565b6020808201516001600160a01b039081165f90815260098084526040808320815160608082018452825460ff90811615158352600180850154848b0152600294850154848701528a519098168752948852948390208351958601845280549094161515855294830154958401959095529301549281019290925280519091901580610e3457508051155b15610e5257604051634b16fc2d60e11b815260040160405180910390fd5b60408301516001600160a01b031615610e7d57604051623c9da560e61b815260040160405180910390fd5b610e8961012c42613e5a565b8360a0015163ffffffff161115610eb35760405163326389f960e11b815260040160405180910390fd5b60e083015115610ed557604051620e5bdf60e41b815260040160405180910390fd5b7ff3b277728b3fee749481eb3e0b3b48980dbbab78658fc419025cb16eee34677583610100015114610f1a57604051632c9634af60e01b815260040160405180910390fd5b7f5a28e9363bb942b639270062aa6bb295f434bcdfc42c97267bf003f272060dc9836101600151141580610f7357507f5a28e9363bb942b639270062aa6bb295f434bcdfc42c97267bf003f272060dc983610140015114155b15610f91576040516397a2328160e01b815260040160405180910390fd5b60208301516040516370a0823160e01b81523060048201525f916001600160a01b0316906370a0823190602401602060405180830381865afa158015610fd9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ffd9190613d33565b9050611011816706f05b59d3b20000612d5c565b846080015111156110355760405163558fcd9160e11b815260040160405180910390fd5b604080840151855191516370a0823160e01b81523060048201525f926110bb92859290916001600160a01b0316906370a0823190602401602060405180830381865afa158015611087573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110ab9190613d33565b866040015189608001515f612281565b905084606001518110156110e25760405163d6ac339560e01b815260040160405180910390fd5b5050505050565b5f5f80516020613f088339815191525c156111175760405163d56a08b560e01b815260040160405180910390fd5b506005546001600160a01b031690565b336001600160a01b03165f356001600160e01b0319166001600160e01b0319165f36604051611157929190613e6d565b60405180910390a25f80516020613f088339815191525c1561118c5760405163d56a08b560e01b815260040160405180910390fd5b6111966001612ddf565b6005546001600160a01b031633146111c157604051634f0f549960e11b815260040160405180910390fd5b60075460ff16156111e55760405163056f633d60e21b815260040160405180910390fd5b6111fa620f4240670de0b6b3a7640000613e3b565b81101561121a57604051633b46575d60e01b815260040160405180910390fd5b61122f620f4240670de0b6b3a7640000613e3b565b61124190670de0b6b3a7640000613e9b565b81111561126157604051630f71fbbf60e11b815260040160405180910390fd5b600681905561126f5f612ddf565b50565b336001600160a01b03165f356001600160e01b0319166001600160e01b0319165f366040516112a2929190613e6d565b60405180910390a25f80516020613f088339815191525c156112d75760405163d56a08b560e01b815260040160405180910390fd5b6112e16001612ddf565b6005546001600160a01b0316331461130c57604051634f0f549960e11b815260040160405180910390fd5b60075460ff16156113305760405163056f633d60e21b815260040160405180910390fd5b600854600211156113545760405163af785ec560e01b815260040160405180910390fd5b6007805460ff1916600117905561137c611377670de0b6b3a76400006064613d1c565b612df2565b61139833611393670de0b6b3a76400006064613d1c565b612dfc565b6113a0612e0a565b6113a95f612ddf565b565b336001600160a01b03165f356001600160e01b0319166001600160e01b0319165f366040516113db929190613e6d565b60405180910390a25f80516020613f088339815191525c156114105760405163d56a08b560e01b815260040160405180910390fd5b61141a6001612ddf565b60075460ff1661143d57604051632e41ba2d60e01b815260040160405180910390fd5b5f61144760025490565b90505f6114548583612f0e565b9050805f0361147657604051630c499f4760e01b815260040160405180910390fd5b6008545f5b818110156115c9575f6008828154811061149757611497613eae565b5f9182526020822001546040516370a0823160e01b81523060048201526001600160a01b03909116925082906370a0823190602401602060405180830381865afa1580156114e7573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061150b9190613d33565b90505f6115188683612d5c565b9050805f0361153a57604051635b00df6960e11b815260040160405180910390fd5b88888581811061154c5761154c613eae565b9050602002013581111561157357604051630451d9ed60e31b815260040160405180910390fd5b6040518181526001600160a01b0384169033907f63982df10efd8dfaaaa0fcc7f50b2d93b7cba26ccc48adee2873220d485dc39a9060200160405180910390a36115be833383612fb6565b50505060010161147b565b506115d386612df2565b6115dd3387612dfc565b5050506115eb5f801b612ddf565b505050565b335f9081526001602090815260408083206001600160a01b03861684529091528120548083111561162b5761162633855f612c72565b6108e3565b6108e3338561163a8685613e9b565b612c72565b610902620f4240670de0b6b3a7640000613e3b565b6040515f90819033906001600160e01b0319833516906116779084903690613e6d565b60405180910390a25f80516020613f088339815191525c156116ac5760405163d56a08b560e01b815260040160405180910390fd5b6116b66001612ddf565b60075460ff166116d957604051632e41ba2d60e01b815260040160405180910390fd5b6001600160a01b0387165f9081526009602052604090205460ff1661171157604051634b16fc2d60e11b815260040160405180910390fd5b6001600160a01b0385165f9081526009602052604090205460ff1661174957604051634b16fc2d60e11b815260040160405180910390fd5b6001600160a01b038781165f81815260096020526040808220938916825280822090516370a0823160e01b81523060048201529092906370a0823190602401602060405180830381865afa1580156117a3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117c79190613d33565b6040516370a0823160e01b81523060048201529091505f906001600160a01b038a16906370a0823190602401602060405180830381865afa15801561180e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118329190613d33565b905061185b8161184b6003670de0b6b3a7640000613e3b565b611856906001613e5a565b612d5c565b88111561187b5760405163dad25d8560e01b815260040160405180910390fd5b5f611893838660020154848760020154600654611f88565b9050878111156118b65760405163823a9c3760e01b815260040160405180910390fd5b6118ce8386600201548487600201548d600654612bf3565b96508a8711156118f157604051630451d9ed60e31b815260040160405180910390fd5b6118fb8388612fcb565b9250611907828a612ff0565b9150611920838660020154848760020154600654611f88565b95508086101561194357604051636212302360e01b815260040160405180910390fd5b878611156119645760405163823a9c3760e01b815260040160405180910390fd5b61196e878a612f0e565b81111561198e576040516337fb98f960e11b815260040160405180910390fd5b60408051888152602081018b90526001600160a01b03808d1692908f169133917f908fb5ee8f16c6bc9bc3690973819f32a4d4b10188134543c88706e0e1d43378910160405180910390a46119e48c3389612fb6565b6119ef8a338b613028565b50505050506119ff5f801b612ddf565b9550959350505050565b6040515f90819033906001600160e01b031983351690611a2c9084903690613e6d565b60405180910390a25f80516020613f088339815191525c15611a615760405163d56a08b560e01b815260040160405180910390fd5b611a6b6001612ddf565b60075460ff16611a8e57604051632e41ba2d60e01b815260040160405180910390fd5b6001600160a01b0387165f9081526009602052604090205460ff16611ac657604051634b16fc2d60e11b815260040160405180910390fd5b6001600160a01b0385165f9081526009602052604090205460ff16611afe57604051634b16fc2d60e11b815260040160405180910390fd5b6001600160a01b038781165f81815260096020526040808220938916825280822090516370a0823160e01b81523060048201529092906370a0823190602401602060405180830381865afa158015611b58573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b7c9190613d33565b6040516370a0823160e01b81523060048201529091505f906001600160a01b038a16906370a0823190602401602060405180830381865afa158015611bc3573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611be79190613d33565b9050611bfb826706f05b59d3b20000612d5c565b8a1115611c1b5760405163558fcd9160e11b815260040160405180910390fd5b5f611c33838660020154848760020154600654611f88565b905087811115611c565760405163823a9c3760e01b815260040160405180910390fd5b611c6e8386600201548487600201548f600654612281565b965088871015611c915760405163d6ac339560e01b815260040160405180910390fd5b611c9b838c612fcb565b9250611ca78288612ff0565b9150611cc0838660020154848760020154600654611f88565b955080861015611ce357604051636212302360e01b815260040160405180910390fd5b87861115611d045760405163823a9c3760e01b815260040160405180910390fd5b611d0e8b88612f0e565b811115611d2e576040516337fb98f960e11b815260040160405180910390fd5b604080518c8152602081018990526001600160a01b03808d1692908f169133917f908fb5ee8f16c6bc9bc3690973819f32a4d4b10188134543c88706e0e1d43378910160405180910390a4611d848c338d612fb6565b6119ef8a3389613028565b61090264e8d4a51000670de0b6b3a7640000613e3b565b336001600160a01b03165f356001600160e01b0319166001600160e01b0319165f36604051611dd6929190613e6d565b60405180910390a25f80516020613f088339815191525c15611e0b5760405163d56a08b560e01b815260040160405180910390fd5b611e156001612ddf565b6005546001600160a01b03163314611e4057604051634f0f549960e11b815260040160405180910390fd5b6001600160a01b038116611e67576040516351a9e5c560e01b815260040160405180910390fd5b600580546001600160a01b0319166001600160a01b03831617905561126f5f612ddf565b5f5f80516020613f088339815191525c15611eb95760405163d56a08b560e01b815260040160405180910390fd5b50600a5490565b610902670de0b6b3a76400006064613d1c565b5f5f80516020613f088339815191525c15611f015760405163d56a08b560e01b815260040160405180910390fd5b6001600160a01b0382165f9081526009602052604090205460ff16611f3957604051634b16fc2d60e11b815260040160405180910390fd5b506001600160a01b0381165f908152600960205260409020600201545b919050565b60606004805461085590613cd0565b611f7d6003670de0b6b3a7640000613e3b565b610902906001613e5a565b5f80611f948787612f0e565b90505f611fa18686612f0e565b90505f611fae8383612f0e565b90505f611fd4670de0b6b3a7640000611fcf670de0b6b3a764000089612ff0565b612f0e565b9050611fe08282612d5c565b9a9950505050505050505050565b5f336108e3818585612cff565b336001600160a01b03165f356001600160e01b0319166001600160e01b0319165f3660405161202b929190613e6d565b60405180910390a25f80516020613f088339815191525c156120605760405163d56a08b560e01b815260040160405180910390fd5b61206a6001612ddf565b60075460ff1661208d57604051632e41ba2d60e01b815260040160405180910390fd5b5f61209760025490565b90505f6120a4855f612d5c565b90505f6120b18683612ff0565b90505f6120be8285612f0e565b9050805f036120e057604051630c499f4760e01b815260040160405180910390fd5b6120ea338861303c565b6121147f000000000000000000000000f76c421bab7df8548604e60deccce50477c1046284612dfc565b61211d82613046565b6008545f5b81811015612270575f6008828154811061213e5761213e613eae565b5f9182526020822001546040516370a0823160e01b81523060048201526001600160a01b03909116925082906370a0823190602401602060405180830381865afa15801561218e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121b29190613d33565b90505f6121bf8683612d5c565b9050805f036121e157604051634b4ae51b60e11b815260040160405180910390fd5b8a8a858181106121f3576121f3613eae565b9050602002013581101561221a5760405163341a1f3360e11b815260040160405180910390fd5b6040518181526001600160a01b0384169033907fe74c91552b64c2e2e7bd255639e004e693bd3e1d01cc33e65610b86afcc1ffed9060200160405180910390a3612265833383613028565b505050600101612122565b5050505050506115eb5f801b612ddf565b5f8061228d8786612f0e565b90505f6122a2670de0b6b3a764000085612ff0565b90506122ae8582612d5c565b90505f6122bf8a611fcf8c85612fcb565b90505f6122cc8285613050565b90505f6122e1670de0b6b3a764000083612ff0565b90506122ed8a82612d5c565b9c9b505050505050505050505050565b612312620f4240670de0b6b3a7640000613e3b565b61090290670de0b6b3a7640000613e9b565b6001612339670de0b6b3a76400006002613d1c565b6109029190613e9b565b60605f80516020613f088339815191525c156123725760405163d56a08b560e01b815260040160405180910390fd5b60075460ff1661239557604051632e41ba2d60e01b815260040160405180910390fd5b60088054806020026020016040519081016040528092919081815260200182805480156108cc57602002820191905f5260205f20905b81546001600160a01b031681526001909101906020018083116123cb575050505050905090565b60605f80516020613f088339815191525c156123955760405163d56a08b560e01b815260040160405180910390fd5b336001600160a01b03165f356001600160e01b0319166001600160e01b0319165f36604051612451929190613e6d565b60405180910390a25f80516020613f088339815191525c156124865760405163d56a08b560e01b815260040160405180910390fd5b6124906001612ddf565b6005546001600160a01b031633146124bb57604051634f0f549960e11b815260040160405180910390fd5b60075460ff16156124df5760405163056f633d60e21b815260040160405180910390fd5b6001600160a01b0381165f9081526009602052604090205460ff1661251757604051634b16fc2d60e11b815260040160405180910390fd5b600a546001600160a01b0382165f9081526009602052604090206002015461253f9190612ff0565b600a556001600160a01b0381165f90815260096020526040812060019081015460085490929161256e91613e9b565b90506008818154811061258357612583613eae565b5f91825260209091200154600880546001600160a01b0390921691849081106125ae576125ae613eae565b905f5260205f20015f6101000a8154816001600160a01b0302191690836001600160a01b031602179055508160095f600885815481106125f0576125f0613eae565b5f9182526020808320909101546001600160a01b03168352820192909252604001902060010155600880548061262857612628613ec2565b5f82815260208082205f19908401810180546001600160a01b0319169055909201909255604080516060810182528381528083018481528183018581526001600160a01b0389168087526009909552948390209151825460ff1916901515178255516001820155925160029093019290925590516370a0823160e01b81523060048201526127029185913391906370a0823190602401602060405180830381865afa1580156126d9573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126fd9190613d33565b613028565b5061126f90505f612ddf565b5f5f80516020613f088339815191525c1561273c5760405163d56a08b560e01b815260040160405180910390fd5b5060065490565b335f8181526001602090815260408083206001600160a01b0387168452909152812054909161277991859061163a908690613e5a565b50600192915050565b336001600160a01b03165f356001600160e01b0319166001600160e01b0319165f366040516127b2929190613e6d565b60405180910390a25f80516020613f088339815191525c156127e75760405163d56a08b560e01b815260040160405180910390fd5b6127f16001612ddf565b6005546001600160a01b0316331461281c57604051634f0f549960e11b815260040160405180910390fd5b60075460ff16156128405760405163056f633d60e21b815260040160405180910390fd5b6001600160a01b0383165f9081526009602052604090205460ff161561287957604051636b1ed1b760e11b815260040160405180910390fd5b600880541061289b5760405163c47f9e9360e01b815260040160405180910390fd5b670de0b6b3a76400008110156128c4576040516342eb024360e01b815260040160405180910390fd5b6128d7670de0b6b3a76400006032613d1c565b8111156128f757604051630cbe784360e11b815260040160405180910390fd5b61290e64e8d4a51000670de0b6b3a7640000613e3b565b82101561292e57604051638968448b60e01b815260040160405180910390fd5b61293a600a5482612fcb565b600a55612950670de0b6b3a76400006032613d1c565b600a541115612972576040516342f71f0b60e01b815260040160405180910390fd5b6040805160608101825260018082526008805460208085019182528486018781526001600160a01b038a165f81815260099093529682209551865460ff19169015151786559151858501559051600290940193909355805491820181559091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30180546001600160a01b0319169091179055612a10833384612fb6565b6115eb5f612ddf565b5f80516020613f088339815191525c15612a465760405163d56a08b560e01b815260040160405180910390fd5b336001600160a01b037f0000000000000000000000009008d19f58aabd9ed0d60971565aa8510560ab411614612a8f5760405163bf84897760e01b815260040160405180910390fd5b61126f81612ddf565b5f5f80516020613f088339815191525c15612ac65760405163d56a08b560e01b815260040160405180910390fd5b6001600160a01b0382165f9081526009602052604090205460ff16612afe57604051634b16fc2d60e11b815260040160405180910390fd5b6001600160a01b0382165f90815260096020526040902060020154600a54610da3908290612f0e565b5f5f80516020613f088339815191525c15612b555760405163d56a08b560e01b815260040160405180910390fd5b6001600160a01b0382165f9081526009602052604090205460ff16612b8d57604051634b16fc2d60e11b815260040160405180910390fd5b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015612bcf573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108e99190613d33565b5f80612bff8588612f0e565b90505f612c0c8786612ff0565b90505f612c198883612f0e565b90505f612c268285613050565b9050612c3a81670de0b6b3a7640000612ff0565b9050612c4e670de0b6b3a764000087612ff0565b9450612c63612c5d8c83612d5c565b86612f0e565b9b9a5050505050505050505050565b6115eb8383836001613105565b6001600160a01b038381165f908152600160209081526040808320938616835292905220545f198114612cf95781811015612ceb57604051637dc7a0d960e11b81526001600160a01b038416600482015260248101829052604481018390526064015b60405180910390fd5b612cf984848484035f613105565b50505050565b6001600160a01b038316612d2857604051634b637e8f60e11b81525f6004820152602401612ce2565b6001600160a01b038216612d515760405163ec442f0560e01b81525f6004820152602401612ce2565b6115eb8383836131d7565b5f8282028315801590612d7e575082848281612d7a57612d7a613e27565b0414155b15612d9c5760405163202e377f60e01b815260040160405180910390fd5b6706f05b59d3b20000810181811015612dc85760405163202e377f60e01b815260040160405180910390fd5b5f670de0b6b3a7640000825b049695505050505050565b805f80516020613f088339815191525d50565b61126f30826132fd565b612e068282613331565b5050565b6008545f5b81811015612e7357612e6b7f000000000000000000000000c92e8bdf79f0507f65a392b0ab4667716bfe01105f1960088481548110612e5057612e50613eae565b5f918252602090912001546001600160a01b0316919061333c565b600101612e0f565b507f000000000000000000000000f76c421bab7df8548604e60deccce50477c104626001600160a01b03166352b8cb636040518163ffffffff1660e01b81526004015f604051808303815f87803b158015612ecc575f80fd5b505af1925050508015612edd575060015b61126f5760405130907f0d03834d0d86c7f57e877af40e26f176dc31bd637535d4ba153d1ac9de88a7ea905f90a250565b5f815f03612f2f5760405163abcf2e7560e01b815260040160405180910390fd5b670de0b6b3a764000083028315801590612f605750670de0b6b3a7640000848281612f5c57612f5c613e27565b0414155b15612f7e576040516394fb03d760e01b815260040160405180910390fd5b600183901c810181811015612fa6576040516394fb03d760e01b815260040160405180910390fd5b5f848281612dd457612dd4613e27565b6115eb6001600160a01b0384168330846133f9565b5f82820183811015610da35760405163e468448f60e01b815260040160405180910390fd5b5f805f612ffd8585613432565b91509150801561302057604051630a5c778b60e31b815260040160405180910390fd5b509392505050565b6115eb6001600160a01b0384168383613455565b612e068282613486565b61126f3082613491565b5f600183101561307357604051635567969f60e11b815260040160405180910390fd5b671bc16d674ec7ffff83111561309c57604051638554775f60e01b815260040160405180910390fd5b670de0b6b3a7640000808304025f6130b48483612ff0565b90505f6130cb86670de0b6b3a764000085046134c5565b9050815f036130de5792506108e9915050565b5f6130ee87846305f5e10061351d565b90506130fa8282612d5c565b979650505050505050565b6001600160a01b03841661312e5760405163e602df0560e01b81525f6004820152602401612ce2565b6001600160a01b03831661315757604051634a1406b160e11b81525f6004820152602401612ce2565b6001600160a01b038085165f9081526001602090815260408083209387168352929052208290558015612cf957826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516131c991815260200190565b60405180910390a350505050565b6001600160a01b038316613201578060025f8282546131f69190613e5a565b909155506132719050565b6001600160a01b0383165f90815260208190526040902054818110156132535760405163391434e360e21b81526001600160a01b03851660048201526024810182905260448101839052606401612ce2565b6001600160a01b0384165f9081526020819052604090209082900390555b6001600160a01b03821661328d576002805482900390556132ab565b6001600160a01b0382165f9081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516132f091815260200190565b60405180910390a3505050565b6001600160a01b0382166133265760405163ec442f0560e01b81525f6004820152602401612ce2565b612e065f83836131d7565b612e06308383612cff565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b17905261338d84826135f9565b612cf9576040516001600160a01b0384811660248301525f60448301526133ef91869182169063095ea7b3906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050613696565b612cf98482613696565b6040516001600160a01b038481166024830152838116604483015260648201839052612cf99186918216906323b872dd906084016133bd565b5f808284106134465750508082035f61344e565b505081810360015b9250929050565b6040516001600160a01b038381166024830152604482018390526115eb91859182169063a9059cbb906064016133bd565b612e06823083612cff565b6001600160a01b0382166134ba57604051634b637e8f60e11b81525f6004820152602401612ce2565b612e06825f836131d7565b5f80600283065f036134df57670de0b6b3a76400006134e1565b835b90506002830492505b8215610da3576134fa8485612d5c565b935060028306156135125761350f8185612d5c565b90505b6002830492506134ea565b5f82818061353387670de0b6b3a7640000613432565b9092509050670de0b6b3a7640000805f60015b8884106135ea575f670de0b6b3a7640000820290505f806135788a61357385670de0b6b3a7640000612ff0565b613432565b9150915061358a87611856848c612d5c565b96506135968784612f0e565b9650865f036135a7575050506135ea565b87156135b1579315935b80156135bb579315935b84156135d2576135cb8688612ff0565b95506135df565b6135dc8688612fcb565b95505b505050600101613546565b50909998505050505050505050565b5f805f846001600160a01b0316846040516136149190613ed6565b5f604051808303815f865af19150503d805f811461364d576040519150601f19603f3d011682016040523d82523d5f602084013e613652565b606091505b509150915081801561367c57508051158061367c57508080602001905181019061367c9190613eec565b8015610a9b5750505050506001600160a01b03163b151590565b5f6136aa6001600160a01b038416836136f7565b905080515f141580156136ce5750808060200190518101906136cc9190613eec565b155b156115eb57604051635274afe760e01b81526001600160a01b0384166004820152602401612ce2565b6060610da383835f845f80856001600160a01b0316848660405161371b9190613ed6565b5f6040518083038185875af1925050503d805f8114613755576040519150601f19603f3d011682016040523d82523d5f602084013e61375a565b606091505b509150915061376a868383613774565b9695505050505050565b60608261378957613784826137d0565b610da3565b81511580156137a057506001600160a01b0384163b155b156137c957604051639996b31560e01b81526001600160a01b0385166004820152602401612ce2565b5080610da3565b8051156137e05780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b6001600160a01b038116811461126f575f80fd5b8035611f568161382e565b5f806040838503121561385e575f80fd5b82356138698161382e565b946020939093013593505050565b5f8060408385031215613888575f80fd5b82356138938161382e565b915060208301356138a38161382e565b809150509250929050565b634e487b7160e01b5f52604160045260245ffd5b604051610180810167ffffffffffffffff811182821017156138e6576138e66138ae565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715613915576139156138ae565b604052919050565b5f806040838503121561392e575f80fd5b8235915060208084013567ffffffffffffffff8082111561394d575f80fd5b818601915086601f830112613960575f80fd5b813581811115613972576139726138ae565b613984601f8201601f191685016138ec565b91508082528784828501011115613999575f80fd5b80848401858401375f848284010152508093505050509250929050565b5f805f606084860312156139c8575f80fd5b83356139d38161382e565b925060208401356139e38161382e565b929592945050506040919091013590565b63ffffffff8116811461126f575f80fd5b8035611f56816139f4565b801515811461126f575f80fd5b8035611f5681613a10565b5f6101808284031215613a39575f80fd5b613a416138c2565b613a4a83613842565b8152613a5860208401613842565b6020820152613a6960408401613842565b60408201526060830135606082015260808301356080820152613a8e60a08401613a05565b60a082015260c083013560c082015260e083013560e0820152610100808401358183015250610120613ac1818501613a1d565b908201526101408381013590820152610160928301359281019290925250919050565b5f60208284031215613af4575f80fd5b8135610da38161382e565b5f60208284031215613b0f575f80fd5b5035919050565b5f805f60408486031215613b28575f80fd5b83359250602084013567ffffffffffffffff80821115613b46575f80fd5b818601915086601f830112613b59575f80fd5b813581811115613b67575f80fd5b8760208260051b8501011115613b7b575f80fd5b6020830194508093505050509250925092565b5f805f805f60a08688031215613ba2575f80fd5b8535613bad8161382e565b9450602086013593506040860135613bc48161382e565b94979396509394606081013594506080013592915050565b5f805f805f60a08688031215613bf0575f80fd5b505083359560208501359550604085013594606081013594506080013592509050565b5f805f805f8060c08789031215613c28575f80fd5b505084359660208601359650604086013595606081013595506080810135945060a0013592509050565b602080825282518282018190525f9190848201906040850190845b81811015613c925783516001600160a01b031683529284019291840191600101613c6d565b50909695505050505050565b5f805f60608486031215613cb0575f80fd5b8335613cbb8161382e565b95602085013595506040909401359392505050565b600181811c90821680613ce457607f821691505b602082108103613d0257634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52601160045260245ffd5b80820281158282048414176108e9576108e9613d08565b5f60208284031215613d43575f80fd5b5051919050565b8051611f568161382e565b8051611f56816139f4565b8051611f5681613a10565b5f6101808284031215613d7c575f80fd5b613d846138c2565b613d8d83613d4a565b8152613d9b60208401613d4a565b6020820152613dac60408401613d4a565b60408201526060830151606082015260808301516080820152613dd160a08401613d55565b60a082015260c083015160c082015260e083015160e0820152610100808401518183015250610120613e04818501613d60565b908201526101408381015190820152610160928301519281019290925250919050565b634e487b7160e01b5f52601260045260245ffd5b5f82613e5557634e487b7160e01b5f52601260045260245ffd5b500490565b808201808211156108e9576108e9613d08565b60208152816020820152818360408301375f818301604090810191909152601f909201601f19160101919050565b818103818111156108e9576108e9613d08565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52603160045260245ffd5b5f82518060208501845e5f920191825250919050565b5f60208284031215613efc575f80fd5b8151610da381613a1056fe3f8f4c536ce1b925b469af1b09a44da237dab5bbc584585648c12be1ca25a8c4a26469706673582212201c2ab66e24826998fe1115ecda27a1ca1f02b6dd605dfec58cf6ededc7327f0764736f6c63430008190033

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.