Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 62 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
New B Pool | 21688115 | 10 days ago | IN | 0 ETH | 0.0614649 | ||||
New B Pool | 21687116 | 10 days ago | IN | 0 ETH | 0.02438381 | ||||
New B Pool | 21572987 | 26 days ago | IN | 0 ETH | 0.03552119 | ||||
New B Pool | 21362702 | 55 days ago | IN | 0 ETH | 0.03664151 | ||||
New B Pool | 21356067 | 56 days ago | IN | 0 ETH | 0.02951197 | ||||
New B Pool | 21337455 | 59 days ago | IN | 0 ETH | 0.09304589 | ||||
New B Pool | 21316485 | 61 days ago | IN | 0 ETH | 0.13427151 | ||||
New B Pool | 21286494 | 66 days ago | IN | 0 ETH | 0.04110339 | ||||
New B Pool | 21281907 | 66 days ago | IN | 0 ETH | 0.06054203 | ||||
New B Pool | 21265109 | 69 days ago | IN | 0 ETH | 0.05922906 | ||||
New B Pool | 21237575 | 72 days ago | IN | 0 ETH | 0.04472552 | ||||
New B Pool | 21208012 | 77 days ago | IN | 0 ETH | 0.03306147 | ||||
New B Pool | 21176076 | 81 days ago | IN | 0 ETH | 0.08530515 | ||||
New B Pool | 21152999 | 84 days ago | IN | 0 ETH | 0.03536475 | ||||
New B Pool | 21144380 | 85 days ago | IN | 0 ETH | 0.07378919 | ||||
New B Pool | 21135134 | 87 days ago | IN | 0 ETH | 0.05795978 | ||||
New B Pool | 21131328 | 87 days ago | IN | 0 ETH | 0.08049132 | ||||
New B Pool | 21105545 | 91 days ago | IN | 0 ETH | 0.0081969 | ||||
New B Pool | 21099780 | 92 days ago | IN | 0 ETH | 0.0106298 | ||||
New B Pool | 21099417 | 92 days ago | IN | 0 ETH | 0.01099933 | ||||
New B Pool | 21072875 | 95 days ago | IN | 0 ETH | 0.07456436 | ||||
New B Pool | 21066846 | 96 days ago | IN | 0 ETH | 0.03246205 | ||||
New B Pool | 21061478 | 97 days ago | IN | 0 ETH | 0.01761928 | ||||
New B Pool | 21057472 | 98 days ago | IN | 0 ETH | 0.02320186 | ||||
New B Pool | 21054302 | 98 days ago | IN | 0 ETH | 0.01207758 |
Latest 25 internal transactions (View All)
Advanced mode:
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
BCoWFactory
Compiler Version
v0.8.25+commit.b61c2a91
Optimization Enabled:
Yes with 500 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.25; import {BCoWPool} from './BCoWPool.sol'; import {BFactory} from './BFactory.sol'; import {IBCoWFactory} from 'interfaces/IBCoWFactory.sol'; import {IBPool} from 'interfaces/IBPool.sol'; /** * @title BCoWFactory * @notice Creates new BCoWPools, logging their addresses and acting as a registry of pools. * @dev Inherits BFactory contract functionalities, but deploys BCoWPools instead of BPool. */ contract BCoWFactory is BFactory, IBCoWFactory { /// @inheritdoc IBCoWFactory address public immutable SOLUTION_SETTLER; /// @inheritdoc IBCoWFactory bytes32 public immutable APP_DATA; constructor(address solutionSettler, bytes32 appData) BFactory() { SOLUTION_SETTLER = solutionSettler; APP_DATA = appData; } /// @inheritdoc IBCoWFactory function logBCoWPool() external { if (!_isBPool[msg.sender]) revert BCoWFactory_NotValidBCoWPool(); emit COWAMMPoolCreated(msg.sender); } /** * @dev Deploys a BCoWPool instead of a regular BPool. * @param name The name of the Pool ERC20 token * @param symbol The symbol of the Pool ERC20 token * @return bCoWPool The deployed BCoWPool */ function _newBPool(string memory name, string memory symbol) internal virtual override returns (IBPool bCoWPool) { bCoWPool = new BCoWPool(SOLUTION_SETTLER, APP_DATA, name, symbol); } }
// 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)); } } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.25; import {BPool} from './BPool.sol'; import {SafeERC20} from '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol'; import {IBFactory} from 'interfaces/IBFactory.sol'; import {IBPool} from 'interfaces/IBPool.sol'; /** * @title BFactory * @notice Creates new BPools, logging their addresses and acting as a registry of pools. */ contract BFactory is IBFactory { /// @dev Mapping indicating whether the address is a BPool. mapping(address => bool) internal _isBPool; /// @dev bDao address. address internal _bDao; constructor() { _bDao = msg.sender; } /// @inheritdoc IBFactory function newBPool(string memory name, string memory symbol) external returns (IBPool bPool) { bPool = _newBPool(name, symbol); _isBPool[address(bPool)] = true; emit LOG_NEW_POOL(msg.sender, address(bPool)); bPool.setController(msg.sender); } /// @inheritdoc IBFactory function setBDao(address bDao) external { if (bDao == address(0)) { revert BFactory_AddressZero(); } if (msg.sender != _bDao) { revert BFactory_NotBDao(); } emit LOG_BDAO(msg.sender, bDao); _bDao = bDao; } /// @inheritdoc IBFactory function collect(IBPool bPool) external { if (msg.sender != _bDao) { revert BFactory_NotBDao(); } uint256 collected = bPool.balanceOf(address(this)); SafeERC20.safeTransfer(bPool, _bDao, collected); } /// @inheritdoc IBFactory function isBPool(address bPool) external view returns (bool) { return _isBPool[bPool]; } /// @inheritdoc IBFactory function getBDao() external view returns (address) { return _bDao; } /** * @notice Deploys a new BPool. * @param name The name of the Pool ERC20 token * @param symbol The symbol of the Pool ERC20 token * @dev Internal function to allow overriding in derived contracts. * @return bPool The deployed BPool */ function _newBPool(string memory name, string memory symbol) internal virtual returns (IBPool bPool) { bPool = new BPool(name, symbol); } }
// 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); }
// 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); }
// 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; }
// 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) } } }
// 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))) } } }
// 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); }
// 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); }
// 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; } }
// 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; }
// 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); }
// 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); }
// 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; } }
// 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); } }
// 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 ); }
// 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); }
// 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(); } } }
// 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) } } } }
// 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); } }
// 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)); }
// 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; } } }
// 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); } } } }
// 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" ); } }
// 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); }
// 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; } }
// 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); }
// 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); }
{ "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
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"solutionSettler","type":"address"},{"internalType":"bytes32","name":"appData","type":"bytes32"}],"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":"BCoWFactory_NotValidBCoWPool","type":"error"},{"inputs":[],"name":"BFactory_AddressZero","type":"error"},{"inputs":[],"name":"BFactory_NotBDao","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"bCoWPool","type":"address"}],"name":"COWAMMPoolCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"bDao","type":"address"}],"name":"LOG_BDAO","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"bPool","type":"address"}],"name":"LOG_NEW_POOL","type":"event"},{"inputs":[],"name":"APP_DATA","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SOLUTION_SETTLER","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IBPool","name":"bPool","type":"address"}],"name":"collect","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getBDao","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"bPool","type":"address"}],"name":"isBPool","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"logBCoWPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"}],"name":"newBPool","outputs":[{"internalType":"contract IBPool","name":"bPool","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"bDao","type":"address"}],"name":"setBDao","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60c0604052348015600e575f80fd5b50604051614d79380380614d79833981016040819052602b916053565b600180546001600160a01b031916331790556001600160a01b039190911660805260a0526088565b5f80604083850312156063575f80fd5b82516001600160a01b03811681146078575f80fd5b6020939093015192949293505050565b60805160a051614cc36100b65f395f818160ab015261049701525f818161012101526104760152614cc35ff3fe608060405234801561000f575f80fd5b5060043610610085575f3560e01c806383f7b7a41161005857806383f7b7a41461010b5780638b54ab1f1461011c578063c2bb6dc214610143578063c3cb0aa81461017e575f80fd5b806306ec16f81461008957806352b8cb631461009e5780636dbc8813146100a657806376233368146100e0575b5f80fd5b61009c6100973660046106ae565b610191565b005b61009c610243565b6100cd7f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b6100f36100ee366004610766565b61029e565b6040516001600160a01b0390911681526020016100d7565b6001546001600160a01b03166100f3565b6100f37f000000000000000000000000000000000000000000000000000000000000000081565b61016e6101513660046106ae565b6001600160a01b03165f9081526020819052604090205460ff1690565b60405190151581526020016100d7565b61009c61018c3660046106ae565b610351565b6001546001600160a01b031633146101bc5760405163064749d160e21b815260040160405180910390fd5b6040516370a0823160e01b81523060048201525f906001600160a01b038316906370a0823190602401602060405180830381865afa158015610200573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061022491906107c6565b60015490915061023f9083906001600160a01b031683610407565b5050565b335f9081526020819052604090205460ff166102725760405163983f976960e01b815260040160405180910390fd5b60405133907f0d03834d0d86c7f57e877af40e26f176dc31bd637535d4ba153d1ac9de88a7ea905f90a2565b5f6102a98383610473565b6001600160a01b0381165f81815260208190526040808220805460ff1916600117905551929350909133917f8ccec77b0cb63ac2cafd0f5de8cdfadab91ce656d262240ba8a6343bccc5f94591a36040516392eefe9b60e01b81523360048201526001600160a01b038216906392eefe9b906024015f604051808303815f87803b158015610335575f80fd5b505af1158015610347573d5f803e3d5ffd5b5050505092915050565b6001600160a01b038116610378576040516317945d4560e21b815260040160405180910390fd5b6001546001600160a01b031633146103a35760405163064749d160e21b815260040160405180910390fd5b6040516001600160a01b0382169033907f0571ff6d71d9d004e54297a3fb6b2a2caa93c1fda4662d3a958614dc0a2c5451905f90a36001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1663a9059cbb60e01b17905261046e9084906104f2565b505050565b5f7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000084846040516104c49061068d565b6104d1949392919061080b565b604051809103905ff0801580156104ea573d5f803e3d5ffd5b509392505050565b5f6105066001600160a01b03841683610558565b905080515f1415801561052a575080806020019051810190610528919061084f565b155b1561046e57604051635274afe760e01b81526001600160a01b03841660048201526024015b60405180910390fd5b606061056583835f61056c565b9392505050565b6060814710156105915760405163cd78605960e01b815230600482015260240161054f565b5f80856001600160a01b031684866040516105ac919061086e565b5f6040518083038185875af1925050503d805f81146105e6576040519150601f19603f3d011682016040523d82523d5f602084013e6105eb565b606091505b50915091506105fb868383610605565b9695505050505050565b60608261061a5761061582610661565b610565565b815115801561063157506001600160a01b0384163b155b1561065a57604051639996b31560e01b81526001600160a01b038516600482015260240161054f565b5080610565565b8051156106715780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b50565b6144098061088583390190565b6001600160a01b038116811461068a575f80fd5b5f602082840312156106be575f80fd5b81356105658161069a565b634e487b7160e01b5f52604160045260245ffd5b5f82601f8301126106ec575f80fd5b813567ffffffffffffffff80821115610707576107076106c9565b604051601f8301601f19908116603f0116810190828211818310171561072f5761072f6106c9565b81604052838152866020858801011115610747575f80fd5b836020870160208301375f602085830101528094505050505092915050565b5f8060408385031215610777575f80fd5b823567ffffffffffffffff8082111561078e575f80fd5b61079a868387016106dd565b935060208501359150808211156107af575f80fd5b506107bc858286016106dd565b9150509250929050565b5f602082840312156107d6575f80fd5b5051919050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b6001600160a01b0385168152836020820152608060408201525f61083260808301856107dd565b828103606084015261084481856107dd565b979650505050505050565b5f6020828403121561085f575f80fd5b81518015158114610565575f80fd5b5f82518060208501845e5f92019182525091905056fe610120604052348015610010575f80fd5b5060405161440938038061440983398101604081905261002f91610233565b81818181818160036100418382610330565b50600461004e8282610330565b5050600580546001600160a01b03191633908117909155608052506100829150620f42409050670de0b6b3a76400006103ef565b60065550506007805460ff191690556001600160a01b03841660e08190526040805163f698da2560e01b8152905163f698da25916004808201926020929091908290030181865afa1580156100d9573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100fd919061040e565b60c08181525050836001600160a01b0316639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610140573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101649190610425565b6001600160a01b031660a05250506101005250610445565b80516001600160a01b0381168114610192575f80fd5b919050565b634e487b7160e01b5f52604160045260245ffd5b5f82601f8301126101ba575f80fd5b81516001600160401b03808211156101d4576101d4610197565b604051601f8301601f19908116603f011681019082821181831017156101fc576101fc610197565b81604052838152866020858801011115610214575f80fd5b8360208701602083015e5f602085830101528094505050505092915050565b5f805f8060808587031215610246575f80fd5b61024f8561017c565b6020860151604087015191955093506001600160401b0380821115610272575f80fd5b61027e888389016101ab565b93506060870151915080821115610293575f80fd5b506102a0878288016101ab565b91505092959194509250565b600181811c908216806102c057607f821691505b6020821081036102de57634e487b7160e01b5f52602260045260245ffd5b50919050565b601f82111561032b57805f5260205f20601f840160051c810160208510156103095750805b601f840160051c820191505b81811015610328575f8155600101610315565b50505b505050565b81516001600160401b0381111561034957610349610197565b61035d8161035784546102ac565b846102e4565b602080601f831160018114610390575f84156103795750858301515b5f19600386901b1c1916600185901b1785556103e7565b5f85815260208120601f198616915b828110156103be5788860151825594840194600190910190840161039f565b50858210156103db57878501515f19600388901b60f8161c191681555b505060018460011b0185555b505050505050565b5f8261040957634e487b7160e01b5f52601260045260245ffd5b500490565b5f6020828403121561041e575f80fd5b5051919050565b5f60208284031215610435575f80fd5b61043e8261017c565b9392505050565b60805160a05160c05160e05161010051613f5d6104ac5f395f81816105800152610c5601525f818161061a0152612a5101525f818161077e0152610cd601525f81816104820152612e1c01525f81816104d6015281816120ef0152612e760152613f5d5ff3fe608060405234801561000f575f80fd5b506004361061039e575f3560e01c80639381cd2b116101ea578063c36596a611610114578063dd62ed3e116100a9578063f14fcbc811610079578063f14fcbc8146107fa578063f1b8a9b71461080d578063f8b2cb4f14610820578063f8d6aed414610833575f80fd5b8063dd62ed3e146107a0578063e4a28a52146103e3578063e4e1e538146107d8578063ec093021146107eb575f80fd5b8063cf5e7bd3116100e4578063cf5e7bd31461074b578063d4cadf681461075e578063d73dd62314610766578063da08c4dc14610779575f80fd5b8063c36596a61461045b578063c6580d1214610734578063cc77828d1461073b578063cd2ed8fb14610743575f80fd5b8063b02f0b731161018a578063ba9530a61161015a578063ba9530a6146106fc578063bc063e1a1461070f578063bc694ea214610717578063be3bbd2e1461071f575f80fd5b8063b02f0b73146106d1578063b0e0d136146106e4578063b7b800a4146106ec578063ba019dab146106f4575f80fd5b8063981a160b116101c5578063981a160b14610685578063992e2a92146106a3578063a221ee49146106ab578063a9059cbb146106be575f80fd5b80639381cd2b14610662578063948d8ce61461066a57806395d89b411461067d575f80fd5b8063313ce567116102cb57806376c7a3c71161026b5780638b54ab1f1161023b5780638b54ab1f146106155780638d4e40831461063c57806392eefe9b14610647578063936c34771461065a575f80fd5b806376c7a3c7146105ca5780637c5e9ea4146105d25780638201aa3f146105fa578063867378c51461060d575f80fd5b80634f69c0d4116102a65780634f69c0d41461055557806366188463146105685780636dbc88131461057b57806370a08231146105a2575f80fd5b8063313ce5671461052b57806334e199071461053a5780634bb278f31461054d575f80fd5b8063189d00ca1161034157806328bd64431161031157806328bd6443146104bc5780632dd31000146104d15780632f37b624146104f85780633018205f14610523575f80fd5b8063189d00ca14610453578063218b53821461045b57806323b872dd1461046a5780632626f2941461047d575f80fd5b80631446a7ff1161037c5780631446a7ff146103f957806315e84af91461040c5780631626ba7e1461041f57806318160ddd1461044b575f80fd5b806306fdde03146103a2578063095ea7b3146103c057806309a3bbe4146103e3575b5f80fd5b6103aa610846565b6040516103b791906137f9565b60405180910390f35b6103d36103ce36600461384d565b6108d6565b60405190151581526020016103b7565b6103eb6108ef565b6040519081526020016103b7565b6103eb610407366004613877565b610905565b6103eb61041a366004613877565b610aa4565b61043261042d36600461391d565b610c3c565b6040516001600160e01b031990911681526020016103b7565b6002546103eb565b6103eb610d6e565b6103eb670de0b6b3a764000081565b6103d36104783660046139b6565b610d85565b6104a47f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016103b7565b6104cf6104ca366004613a28565b610daa565b005b6104a47f000000000000000000000000000000000000000000000000000000000000000081565b6103d3610506366004613ae4565b6001600160a01b03165f9081526009602052604090205460ff1690565b6104a46110e9565b604051601281526020016103b7565b6104cf610548366004613aff565b611127565b6104cf611272565b6104cf610563366004613b16565b6113ab565b6103d361057636600461384d565b6115f0565b6103eb7f000000000000000000000000000000000000000000000000000000000000000081565b6103eb6105b0366004613ae4565b6001600160a01b03165f9081526020819052604090205490565b6103eb61163f565b6105e56105e0366004613b8e565b611654565b604080519283526020830191909152016103b7565b6105e5610608366004613b8e565b611a09565b6103eb611d8f565b6104a47f000000000000000000000000000000000000000000000000000000000000000081565b60075460ff166103d3565b6104cf610655366004613ae4565b611da6565b6103eb611e8b565b6103eb611ec0565b6103eb610678366004613ae4565b611ed3565b6103aa611f5b565b61068e61012c81565b60405163ffffffff90911681526020016103b7565b6103eb611f6a565b6103eb6106b9366004613bdc565b611f88565b6103d36106cc36600461384d565b611fee565b6104cf6106df366004613b16565b611ffb565b6103eb600881565b6103eb600281565b6103eb600181565b6103eb61070a366004613c13565b612281565b6103eb6122fd565b6103eb612324565b610727612343565b6040516103b79190613c52565b6103eb5f81565b6107276123f2565b6008546103eb565b6104cf610759366004613ae4565b612421565b6103eb61270e565b6103d361077436600461384d565b612743565b6103eb7f000000000000000000000000000000000000000000000000000000000000000081565b6103eb6107ae366004613877565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205490565b6104cf6107e6366004613c9e565b612782565b6103eb6706f05b59d3b2000081565b6104cf610808366004613aff565b612a19565b6103eb61081b366004613ae4565b612a98565b6103eb61082e366004613ae4565b612b27565b6103eb610841366004613c13565b612bf3565b60606003805461085590613cd0565b80601f016020809104026020016040519081016040528092919081815260200182805461088190613cd0565b80156108cc5780601f106108a3576101008083540402835291602001916108cc565b820191905f5260205f20905b8154815290600101906020018083116108af57829003601f168201915b5050505050905090565b5f336108e3818585612c72565b60019150505b92915050565b610902670de0b6b3a76400006032613d1c565b81565b5f5f80516020613f088339815191525c156109335760405163d56a08b560e01b815260040160405180910390fd5b6001600160a01b0383165f9081526009602052604090205460ff1661096b57604051634b16fc2d60e11b815260040160405180910390fd5b6001600160a01b0382165f9081526009602052604090205460ff166109a357604051634b16fc2d60e11b815260040160405180910390fd5b6001600160a01b038381165f8181526009602052604080822093861682529081902090516370a0823160e01b81523060048201529091610a9b916370a0823190602401602060405180830381865afa158015610a01573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a259190613d33565b60028401546040516370a0823160e01b81523060048201526001600160a01b038816906370a0823190602401602060405180830381865afa158015610a6c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a909190613d33565b84600201545f611f88565b95945050505050565b5f5f80516020613f088339815191525c15610ad25760405163d56a08b560e01b815260040160405180910390fd5b6001600160a01b0383165f9081526009602052604090205460ff16610b0a57604051634b16fc2d60e11b815260040160405180910390fd5b6001600160a01b0382165f9081526009602052604090205460ff16610b4257604051634b16fc2d60e11b815260040160405180910390fd5b6001600160a01b038381165f8181526009602052604080822093861682529081902090516370a0823160e01b81523060048201529091610a9b916370a0823190602401602060405180830381865afa158015610ba0573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bc49190613d33565b60028401546040516370a0823160e01b81523060048201526001600160a01b038816906370a0823190602401602060405180830381865afa158015610c0b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c2f9190613d33565b8460020154600654611f88565b5f8082806020019051810190610c529190613d6b565b90507f00000000000000000000000000000000000000000000000000000000000000008160c0015114610c9857604051630e1a1b6360e41b815260040160405180910390fd5b601f19810180517fd5a25ba2e97094ad7d83dc28a6572da797d6b3e7fc6663bd93efb789fc17e48982526101a08220915260405161190160f01b81527f00000000000000000000000000000000000000000000000000000000000000006002820152602281019190915260429020848114610d265760405163593fcacd60e01b815260040160405180910390fd5b5f80516020613f088339815191525c8114610d545760405163dafbdd1f60e01b815260040160405180910390fd5b610d5d82610daa565b50630b135d3f60e11b949350505050565b6109026402540be400670de0b6b3a7640000613e3b565b5f33610d92858285612c7f565b610d9d858585612cff565b60019150505b9392505050565b6020808201516001600160a01b039081165f90815260098084526040808320815160608082018452825460ff90811615158352600180850154848b0152600294850154848701528a519098168752948852948390208351958601845280549094161515855294830154958401959095529301549281019290925280519091901580610e3457508051155b15610e5257604051634b16fc2d60e11b815260040160405180910390fd5b60408301516001600160a01b031615610e7d57604051623c9da560e61b815260040160405180910390fd5b610e8961012c42613e5a565b8360a0015163ffffffff161115610eb35760405163326389f960e11b815260040160405180910390fd5b60e083015115610ed557604051620e5bdf60e41b815260040160405180910390fd5b7ff3b277728b3fee749481eb3e0b3b48980dbbab78658fc419025cb16eee34677583610100015114610f1a57604051632c9634af60e01b815260040160405180910390fd5b7f5a28e9363bb942b639270062aa6bb295f434bcdfc42c97267bf003f272060dc9836101600151141580610f7357507f5a28e9363bb942b639270062aa6bb295f434bcdfc42c97267bf003f272060dc983610140015114155b15610f91576040516397a2328160e01b815260040160405180910390fd5b60208301516040516370a0823160e01b81523060048201525f916001600160a01b0316906370a0823190602401602060405180830381865afa158015610fd9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ffd9190613d33565b9050611011816706f05b59d3b20000612d5c565b846080015111156110355760405163558fcd9160e11b815260040160405180910390fd5b604080840151855191516370a0823160e01b81523060048201525f926110bb92859290916001600160a01b0316906370a0823190602401602060405180830381865afa158015611087573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110ab9190613d33565b866040015189608001515f612281565b905084606001518110156110e25760405163d6ac339560e01b815260040160405180910390fd5b5050505050565b5f5f80516020613f088339815191525c156111175760405163d56a08b560e01b815260040160405180910390fd5b506005546001600160a01b031690565b336001600160a01b03165f356001600160e01b0319166001600160e01b0319165f36604051611157929190613e6d565b60405180910390a25f80516020613f088339815191525c1561118c5760405163d56a08b560e01b815260040160405180910390fd5b6111966001612ddf565b6005546001600160a01b031633146111c157604051634f0f549960e11b815260040160405180910390fd5b60075460ff16156111e55760405163056f633d60e21b815260040160405180910390fd5b6111fa620f4240670de0b6b3a7640000613e3b565b81101561121a57604051633b46575d60e01b815260040160405180910390fd5b61122f620f4240670de0b6b3a7640000613e3b565b61124190670de0b6b3a7640000613e9b565b81111561126157604051630f71fbbf60e11b815260040160405180910390fd5b600681905561126f5f612ddf565b50565b336001600160a01b03165f356001600160e01b0319166001600160e01b0319165f366040516112a2929190613e6d565b60405180910390a25f80516020613f088339815191525c156112d75760405163d56a08b560e01b815260040160405180910390fd5b6112e16001612ddf565b6005546001600160a01b0316331461130c57604051634f0f549960e11b815260040160405180910390fd5b60075460ff16156113305760405163056f633d60e21b815260040160405180910390fd5b600854600211156113545760405163af785ec560e01b815260040160405180910390fd5b6007805460ff1916600117905561137c611377670de0b6b3a76400006064613d1c565b612df2565b61139833611393670de0b6b3a76400006064613d1c565b612dfc565b6113a0612e0a565b6113a95f612ddf565b565b336001600160a01b03165f356001600160e01b0319166001600160e01b0319165f366040516113db929190613e6d565b60405180910390a25f80516020613f088339815191525c156114105760405163d56a08b560e01b815260040160405180910390fd5b61141a6001612ddf565b60075460ff1661143d57604051632e41ba2d60e01b815260040160405180910390fd5b5f61144760025490565b90505f6114548583612f0e565b9050805f0361147657604051630c499f4760e01b815260040160405180910390fd5b6008545f5b818110156115c9575f6008828154811061149757611497613eae565b5f9182526020822001546040516370a0823160e01b81523060048201526001600160a01b03909116925082906370a0823190602401602060405180830381865afa1580156114e7573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061150b9190613d33565b90505f6115188683612d5c565b9050805f0361153a57604051635b00df6960e11b815260040160405180910390fd5b88888581811061154c5761154c613eae565b9050602002013581111561157357604051630451d9ed60e31b815260040160405180910390fd5b6040518181526001600160a01b0384169033907f63982df10efd8dfaaaa0fcc7f50b2d93b7cba26ccc48adee2873220d485dc39a9060200160405180910390a36115be833383612fb6565b50505060010161147b565b506115d386612df2565b6115dd3387612dfc565b5050506115eb5f801b612ddf565b505050565b335f9081526001602090815260408083206001600160a01b03861684529091528120548083111561162b5761162633855f612c72565b6108e3565b6108e3338561163a8685613e9b565b612c72565b610902620f4240670de0b6b3a7640000613e3b565b6040515f90819033906001600160e01b0319833516906116779084903690613e6d565b60405180910390a25f80516020613f088339815191525c156116ac5760405163d56a08b560e01b815260040160405180910390fd5b6116b66001612ddf565b60075460ff166116d957604051632e41ba2d60e01b815260040160405180910390fd5b6001600160a01b0387165f9081526009602052604090205460ff1661171157604051634b16fc2d60e11b815260040160405180910390fd5b6001600160a01b0385165f9081526009602052604090205460ff1661174957604051634b16fc2d60e11b815260040160405180910390fd5b6001600160a01b038781165f81815260096020526040808220938916825280822090516370a0823160e01b81523060048201529092906370a0823190602401602060405180830381865afa1580156117a3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117c79190613d33565b6040516370a0823160e01b81523060048201529091505f906001600160a01b038a16906370a0823190602401602060405180830381865afa15801561180e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118329190613d33565b905061185b8161184b6003670de0b6b3a7640000613e3b565b611856906001613e5a565b612d5c565b88111561187b5760405163dad25d8560e01b815260040160405180910390fd5b5f611893838660020154848760020154600654611f88565b9050878111156118b65760405163823a9c3760e01b815260040160405180910390fd5b6118ce8386600201548487600201548d600654612bf3565b96508a8711156118f157604051630451d9ed60e31b815260040160405180910390fd5b6118fb8388612fcb565b9250611907828a612ff0565b9150611920838660020154848760020154600654611f88565b95508086101561194357604051636212302360e01b815260040160405180910390fd5b878611156119645760405163823a9c3760e01b815260040160405180910390fd5b61196e878a612f0e565b81111561198e576040516337fb98f960e11b815260040160405180910390fd5b60408051888152602081018b90526001600160a01b03808d1692908f169133917f908fb5ee8f16c6bc9bc3690973819f32a4d4b10188134543c88706e0e1d43378910160405180910390a46119e48c3389612fb6565b6119ef8a338b613028565b50505050506119ff5f801b612ddf565b9550959350505050565b6040515f90819033906001600160e01b031983351690611a2c9084903690613e6d565b60405180910390a25f80516020613f088339815191525c15611a615760405163d56a08b560e01b815260040160405180910390fd5b611a6b6001612ddf565b60075460ff16611a8e57604051632e41ba2d60e01b815260040160405180910390fd5b6001600160a01b0387165f9081526009602052604090205460ff16611ac657604051634b16fc2d60e11b815260040160405180910390fd5b6001600160a01b0385165f9081526009602052604090205460ff16611afe57604051634b16fc2d60e11b815260040160405180910390fd5b6001600160a01b038781165f81815260096020526040808220938916825280822090516370a0823160e01b81523060048201529092906370a0823190602401602060405180830381865afa158015611b58573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b7c9190613d33565b6040516370a0823160e01b81523060048201529091505f906001600160a01b038a16906370a0823190602401602060405180830381865afa158015611bc3573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611be79190613d33565b9050611bfb826706f05b59d3b20000612d5c565b8a1115611c1b5760405163558fcd9160e11b815260040160405180910390fd5b5f611c33838660020154848760020154600654611f88565b905087811115611c565760405163823a9c3760e01b815260040160405180910390fd5b611c6e8386600201548487600201548f600654612281565b965088871015611c915760405163d6ac339560e01b815260040160405180910390fd5b611c9b838c612fcb565b9250611ca78288612ff0565b9150611cc0838660020154848760020154600654611f88565b955080861015611ce357604051636212302360e01b815260040160405180910390fd5b87861115611d045760405163823a9c3760e01b815260040160405180910390fd5b611d0e8b88612f0e565b811115611d2e576040516337fb98f960e11b815260040160405180910390fd5b604080518c8152602081018990526001600160a01b03808d1692908f169133917f908fb5ee8f16c6bc9bc3690973819f32a4d4b10188134543c88706e0e1d43378910160405180910390a4611d848c338d612fb6565b6119ef8a3389613028565b61090264e8d4a51000670de0b6b3a7640000613e3b565b336001600160a01b03165f356001600160e01b0319166001600160e01b0319165f36604051611dd6929190613e6d565b60405180910390a25f80516020613f088339815191525c15611e0b5760405163d56a08b560e01b815260040160405180910390fd5b611e156001612ddf565b6005546001600160a01b03163314611e4057604051634f0f549960e11b815260040160405180910390fd5b6001600160a01b038116611e67576040516351a9e5c560e01b815260040160405180910390fd5b600580546001600160a01b0319166001600160a01b03831617905561126f5f612ddf565b5f5f80516020613f088339815191525c15611eb95760405163d56a08b560e01b815260040160405180910390fd5b50600a5490565b610902670de0b6b3a76400006064613d1c565b5f5f80516020613f088339815191525c15611f015760405163d56a08b560e01b815260040160405180910390fd5b6001600160a01b0382165f9081526009602052604090205460ff16611f3957604051634b16fc2d60e11b815260040160405180910390fd5b506001600160a01b0381165f908152600960205260409020600201545b919050565b60606004805461085590613cd0565b611f7d6003670de0b6b3a7640000613e3b565b610902906001613e5a565b5f80611f948787612f0e565b90505f611fa18686612f0e565b90505f611fae8383612f0e565b90505f611fd4670de0b6b3a7640000611fcf670de0b6b3a764000089612ff0565b612f0e565b9050611fe08282612d5c565b9a9950505050505050505050565b5f336108e3818585612cff565b336001600160a01b03165f356001600160e01b0319166001600160e01b0319165f3660405161202b929190613e6d565b60405180910390a25f80516020613f088339815191525c156120605760405163d56a08b560e01b815260040160405180910390fd5b61206a6001612ddf565b60075460ff1661208d57604051632e41ba2d60e01b815260040160405180910390fd5b5f61209760025490565b90505f6120a4855f612d5c565b90505f6120b18683612ff0565b90505f6120be8285612f0e565b9050805f036120e057604051630c499f4760e01b815260040160405180910390fd5b6120ea338861303c565b6121147f000000000000000000000000000000000000000000000000000000000000000084612dfc565b61211d82613046565b6008545f5b81811015612270575f6008828154811061213e5761213e613eae565b5f9182526020822001546040516370a0823160e01b81523060048201526001600160a01b03909116925082906370a0823190602401602060405180830381865afa15801561218e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121b29190613d33565b90505f6121bf8683612d5c565b9050805f036121e157604051634b4ae51b60e11b815260040160405180910390fd5b8a8a858181106121f3576121f3613eae565b9050602002013581101561221a5760405163341a1f3360e11b815260040160405180910390fd5b6040518181526001600160a01b0384169033907fe74c91552b64c2e2e7bd255639e004e693bd3e1d01cc33e65610b86afcc1ffed9060200160405180910390a3612265833383613028565b505050600101612122565b5050505050506115eb5f801b612ddf565b5f8061228d8786612f0e565b90505f6122a2670de0b6b3a764000085612ff0565b90506122ae8582612d5c565b90505f6122bf8a611fcf8c85612fcb565b90505f6122cc8285613050565b90505f6122e1670de0b6b3a764000083612ff0565b90506122ed8a82612d5c565b9c9b505050505050505050505050565b612312620f4240670de0b6b3a7640000613e3b565b61090290670de0b6b3a7640000613e9b565b6001612339670de0b6b3a76400006002613d1c565b6109029190613e9b565b60605f80516020613f088339815191525c156123725760405163d56a08b560e01b815260040160405180910390fd5b60075460ff1661239557604051632e41ba2d60e01b815260040160405180910390fd5b60088054806020026020016040519081016040528092919081815260200182805480156108cc57602002820191905f5260205f20905b81546001600160a01b031681526001909101906020018083116123cb575050505050905090565b60605f80516020613f088339815191525c156123955760405163d56a08b560e01b815260040160405180910390fd5b336001600160a01b03165f356001600160e01b0319166001600160e01b0319165f36604051612451929190613e6d565b60405180910390a25f80516020613f088339815191525c156124865760405163d56a08b560e01b815260040160405180910390fd5b6124906001612ddf565b6005546001600160a01b031633146124bb57604051634f0f549960e11b815260040160405180910390fd5b60075460ff16156124df5760405163056f633d60e21b815260040160405180910390fd5b6001600160a01b0381165f9081526009602052604090205460ff1661251757604051634b16fc2d60e11b815260040160405180910390fd5b600a546001600160a01b0382165f9081526009602052604090206002015461253f9190612ff0565b600a556001600160a01b0381165f90815260096020526040812060019081015460085490929161256e91613e9b565b90506008818154811061258357612583613eae565b5f91825260209091200154600880546001600160a01b0390921691849081106125ae576125ae613eae565b905f5260205f20015f6101000a8154816001600160a01b0302191690836001600160a01b031602179055508160095f600885815481106125f0576125f0613eae565b5f9182526020808320909101546001600160a01b03168352820192909252604001902060010155600880548061262857612628613ec2565b5f82815260208082205f19908401810180546001600160a01b0319169055909201909255604080516060810182528381528083018481528183018581526001600160a01b0389168087526009909552948390209151825460ff1916901515178255516001820155925160029093019290925590516370a0823160e01b81523060048201526127029185913391906370a0823190602401602060405180830381865afa1580156126d9573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126fd9190613d33565b613028565b5061126f90505f612ddf565b5f5f80516020613f088339815191525c1561273c5760405163d56a08b560e01b815260040160405180910390fd5b5060065490565b335f8181526001602090815260408083206001600160a01b0387168452909152812054909161277991859061163a908690613e5a565b50600192915050565b336001600160a01b03165f356001600160e01b0319166001600160e01b0319165f366040516127b2929190613e6d565b60405180910390a25f80516020613f088339815191525c156127e75760405163d56a08b560e01b815260040160405180910390fd5b6127f16001612ddf565b6005546001600160a01b0316331461281c57604051634f0f549960e11b815260040160405180910390fd5b60075460ff16156128405760405163056f633d60e21b815260040160405180910390fd5b6001600160a01b0383165f9081526009602052604090205460ff161561287957604051636b1ed1b760e11b815260040160405180910390fd5b600880541061289b5760405163c47f9e9360e01b815260040160405180910390fd5b670de0b6b3a76400008110156128c4576040516342eb024360e01b815260040160405180910390fd5b6128d7670de0b6b3a76400006032613d1c565b8111156128f757604051630cbe784360e11b815260040160405180910390fd5b61290e64e8d4a51000670de0b6b3a7640000613e3b565b82101561292e57604051638968448b60e01b815260040160405180910390fd5b61293a600a5482612fcb565b600a55612950670de0b6b3a76400006032613d1c565b600a541115612972576040516342f71f0b60e01b815260040160405180910390fd5b6040805160608101825260018082526008805460208085019182528486018781526001600160a01b038a165f81815260099093529682209551865460ff19169015151786559151858501559051600290940193909355805491820181559091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30180546001600160a01b0319169091179055612a10833384612fb6565b6115eb5f612ddf565b5f80516020613f088339815191525c15612a465760405163d56a08b560e01b815260040160405180910390fd5b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614612a8f5760405163bf84897760e01b815260040160405180910390fd5b61126f81612ddf565b5f5f80516020613f088339815191525c15612ac65760405163d56a08b560e01b815260040160405180910390fd5b6001600160a01b0382165f9081526009602052604090205460ff16612afe57604051634b16fc2d60e11b815260040160405180910390fd5b6001600160a01b0382165f90815260096020526040902060020154600a54610da3908290612f0e565b5f5f80516020613f088339815191525c15612b555760405163d56a08b560e01b815260040160405180910390fd5b6001600160a01b0382165f9081526009602052604090205460ff16612b8d57604051634b16fc2d60e11b815260040160405180910390fd5b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015612bcf573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108e99190613d33565b5f80612bff8588612f0e565b90505f612c0c8786612ff0565b90505f612c198883612f0e565b90505f612c268285613050565b9050612c3a81670de0b6b3a7640000612ff0565b9050612c4e670de0b6b3a764000087612ff0565b9450612c63612c5d8c83612d5c565b86612f0e565b9b9a5050505050505050505050565b6115eb8383836001613105565b6001600160a01b038381165f908152600160209081526040808320938616835292905220545f198114612cf95781811015612ceb57604051637dc7a0d960e11b81526001600160a01b038416600482015260248101829052604481018390526064015b60405180910390fd5b612cf984848484035f613105565b50505050565b6001600160a01b038316612d2857604051634b637e8f60e11b81525f6004820152602401612ce2565b6001600160a01b038216612d515760405163ec442f0560e01b81525f6004820152602401612ce2565b6115eb8383836131d7565b5f8282028315801590612d7e575082848281612d7a57612d7a613e27565b0414155b15612d9c5760405163202e377f60e01b815260040160405180910390fd5b6706f05b59d3b20000810181811015612dc85760405163202e377f60e01b815260040160405180910390fd5b5f670de0b6b3a7640000825b049695505050505050565b805f80516020613f088339815191525d50565b61126f30826132fd565b612e068282613331565b5050565b6008545f5b81811015612e7357612e6b7f00000000000000000000000000000000000000000000000000000000000000005f1960088481548110612e5057612e50613eae565b5f918252602090912001546001600160a01b0316919061333c565b600101612e0f565b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166352b8cb636040518163ffffffff1660e01b81526004015f604051808303815f87803b158015612ecc575f80fd5b505af1925050508015612edd575060015b61126f5760405130907f0d03834d0d86c7f57e877af40e26f176dc31bd637535d4ba153d1ac9de88a7ea905f90a250565b5f815f03612f2f5760405163abcf2e7560e01b815260040160405180910390fd5b670de0b6b3a764000083028315801590612f605750670de0b6b3a7640000848281612f5c57612f5c613e27565b0414155b15612f7e576040516394fb03d760e01b815260040160405180910390fd5b600183901c810181811015612fa6576040516394fb03d760e01b815260040160405180910390fd5b5f848281612dd457612dd4613e27565b6115eb6001600160a01b0384168330846133f9565b5f82820183811015610da35760405163e468448f60e01b815260040160405180910390fd5b5f805f612ffd8585613432565b91509150801561302057604051630a5c778b60e31b815260040160405180910390fd5b509392505050565b6115eb6001600160a01b0384168383613455565b612e068282613486565b61126f3082613491565b5f600183101561307357604051635567969f60e11b815260040160405180910390fd5b671bc16d674ec7ffff83111561309c57604051638554775f60e01b815260040160405180910390fd5b670de0b6b3a7640000808304025f6130b48483612ff0565b90505f6130cb86670de0b6b3a764000085046134c5565b9050815f036130de5792506108e9915050565b5f6130ee87846305f5e10061351d565b90506130fa8282612d5c565b979650505050505050565b6001600160a01b03841661312e5760405163e602df0560e01b81525f6004820152602401612ce2565b6001600160a01b03831661315757604051634a1406b160e11b81525f6004820152602401612ce2565b6001600160a01b038085165f9081526001602090815260408083209387168352929052208290558015612cf957826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516131c991815260200190565b60405180910390a350505050565b6001600160a01b038316613201578060025f8282546131f69190613e5a565b909155506132719050565b6001600160a01b0383165f90815260208190526040902054818110156132535760405163391434e360e21b81526001600160a01b03851660048201526024810182905260448101839052606401612ce2565b6001600160a01b0384165f9081526020819052604090209082900390555b6001600160a01b03821661328d576002805482900390556132ab565b6001600160a01b0382165f9081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516132f091815260200190565b60405180910390a3505050565b6001600160a01b0382166133265760405163ec442f0560e01b81525f6004820152602401612ce2565b612e065f83836131d7565b612e06308383612cff565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b17905261338d84826135f9565b612cf9576040516001600160a01b0384811660248301525f60448301526133ef91869182169063095ea7b3906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050613696565b612cf98482613696565b6040516001600160a01b038481166024830152838116604483015260648201839052612cf99186918216906323b872dd906084016133bd565b5f808284106134465750508082035f61344e565b505081810360015b9250929050565b6040516001600160a01b038381166024830152604482018390526115eb91859182169063a9059cbb906064016133bd565b612e06823083612cff565b6001600160a01b0382166134ba57604051634b637e8f60e11b81525f6004820152602401612ce2565b612e06825f836131d7565b5f80600283065f036134df57670de0b6b3a76400006134e1565b835b90506002830492505b8215610da3576134fa8485612d5c565b935060028306156135125761350f8185612d5c565b90505b6002830492506134ea565b5f82818061353387670de0b6b3a7640000613432565b9092509050670de0b6b3a7640000805f60015b8884106135ea575f670de0b6b3a7640000820290505f806135788a61357385670de0b6b3a7640000612ff0565b613432565b9150915061358a87611856848c612d5c565b96506135968784612f0e565b9650865f036135a7575050506135ea565b87156135b1579315935b80156135bb579315935b84156135d2576135cb8688612ff0565b95506135df565b6135dc8688612fcb565b95505b505050600101613546565b50909998505050505050505050565b5f805f846001600160a01b0316846040516136149190613ed6565b5f604051808303815f865af19150503d805f811461364d576040519150601f19603f3d011682016040523d82523d5f602084013e613652565b606091505b509150915081801561367c57508051158061367c57508080602001905181019061367c9190613eec565b8015610a9b5750505050506001600160a01b03163b151590565b5f6136aa6001600160a01b038416836136f7565b905080515f141580156136ce5750808060200190518101906136cc9190613eec565b155b156115eb57604051635274afe760e01b81526001600160a01b0384166004820152602401612ce2565b6060610da383835f845f80856001600160a01b0316848660405161371b9190613ed6565b5f6040518083038185875af1925050503d805f8114613755576040519150601f19603f3d011682016040523d82523d5f602084013e61375a565b606091505b509150915061376a868383613774565b9695505050505050565b60608261378957613784826137d0565b610da3565b81511580156137a057506001600160a01b0384163b155b156137c957604051639996b31560e01b81526001600160a01b0385166004820152602401612ce2565b5080610da3565b8051156137e05780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b6001600160a01b038116811461126f575f80fd5b8035611f568161382e565b5f806040838503121561385e575f80fd5b82356138698161382e565b946020939093013593505050565b5f8060408385031215613888575f80fd5b82356138938161382e565b915060208301356138a38161382e565b809150509250929050565b634e487b7160e01b5f52604160045260245ffd5b604051610180810167ffffffffffffffff811182821017156138e6576138e66138ae565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715613915576139156138ae565b604052919050565b5f806040838503121561392e575f80fd5b8235915060208084013567ffffffffffffffff8082111561394d575f80fd5b818601915086601f830112613960575f80fd5b813581811115613972576139726138ae565b613984601f8201601f191685016138ec565b91508082528784828501011115613999575f80fd5b80848401858401375f848284010152508093505050509250929050565b5f805f606084860312156139c8575f80fd5b83356139d38161382e565b925060208401356139e38161382e565b929592945050506040919091013590565b63ffffffff8116811461126f575f80fd5b8035611f56816139f4565b801515811461126f575f80fd5b8035611f5681613a10565b5f6101808284031215613a39575f80fd5b613a416138c2565b613a4a83613842565b8152613a5860208401613842565b6020820152613a6960408401613842565b60408201526060830135606082015260808301356080820152613a8e60a08401613a05565b60a082015260c083013560c082015260e083013560e0820152610100808401358183015250610120613ac1818501613a1d565b908201526101408381013590820152610160928301359281019290925250919050565b5f60208284031215613af4575f80fd5b8135610da38161382e565b5f60208284031215613b0f575f80fd5b5035919050565b5f805f60408486031215613b28575f80fd5b83359250602084013567ffffffffffffffff80821115613b46575f80fd5b818601915086601f830112613b59575f80fd5b813581811115613b67575f80fd5b8760208260051b8501011115613b7b575f80fd5b6020830194508093505050509250925092565b5f805f805f60a08688031215613ba2575f80fd5b8535613bad8161382e565b9450602086013593506040860135613bc48161382e565b94979396509394606081013594506080013592915050565b5f805f805f60a08688031215613bf0575f80fd5b505083359560208501359550604085013594606081013594506080013592509050565b5f805f805f8060c08789031215613c28575f80fd5b505084359660208601359650604086013595606081013595506080810135945060a0013592509050565b602080825282518282018190525f9190848201906040850190845b81811015613c925783516001600160a01b031683529284019291840191600101613c6d565b50909695505050505050565b5f805f60608486031215613cb0575f80fd5b8335613cbb8161382e565b95602085013595506040909401359392505050565b600181811c90821680613ce457607f821691505b602082108103613d0257634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52601160045260245ffd5b80820281158282048414176108e9576108e9613d08565b5f60208284031215613d43575f80fd5b5051919050565b8051611f568161382e565b8051611f56816139f4565b8051611f5681613a10565b5f6101808284031215613d7c575f80fd5b613d846138c2565b613d8d83613d4a565b8152613d9b60208401613d4a565b6020820152613dac60408401613d4a565b60408201526060830151606082015260808301516080820152613dd160a08401613d55565b60a082015260c083015160c082015260e083015160e0820152610100808401518183015250610120613e04818501613d60565b908201526101408381015190820152610160928301519281019290925250919050565b634e487b7160e01b5f52601260045260245ffd5b5f82613e5557634e487b7160e01b5f52601260045260245ffd5b500490565b808201808211156108e9576108e9613d08565b60208152816020820152818360408301375f818301604090810191909152601f909201601f19160101919050565b818103818111156108e9576108e9613d08565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52603160045260245ffd5b5f82518060208501845e5f920191825250919050565b5f60208284031215613efc575f80fd5b8151610da381613a1056fe3f8f4c536ce1b925b469af1b09a44da237dab5bbc584585648c12be1ca25a8c4a26469706673582212201c2ab66e24826998fe1115ecda27a1ca1f02b6dd605dfec58cf6ededc7327f0764736f6c63430008190033a2646970667358221220d96d5f31f034eaa8368c9c67131bf5f91bde789b0b870d0a9def6b1531e8c34e64736f6c634300081900330000000000000000000000009008d19f58aabd9ed0d60971565aa8510560ab41362e5182440b52aa8fffe70a251550fbbcbca424740fe5a14f59bf0c1b06fe1d
Deployed Bytecode
0x608060405234801561000f575f80fd5b5060043610610085575f3560e01c806383f7b7a41161005857806383f7b7a41461010b5780638b54ab1f1461011c578063c2bb6dc214610143578063c3cb0aa81461017e575f80fd5b806306ec16f81461008957806352b8cb631461009e5780636dbc8813146100a657806376233368146100e0575b5f80fd5b61009c6100973660046106ae565b610191565b005b61009c610243565b6100cd7f362e5182440b52aa8fffe70a251550fbbcbca424740fe5a14f59bf0c1b06fe1d81565b6040519081526020015b60405180910390f35b6100f36100ee366004610766565b61029e565b6040516001600160a01b0390911681526020016100d7565b6001546001600160a01b03166100f3565b6100f37f0000000000000000000000009008d19f58aabd9ed0d60971565aa8510560ab4181565b61016e6101513660046106ae565b6001600160a01b03165f9081526020819052604090205460ff1690565b60405190151581526020016100d7565b61009c61018c3660046106ae565b610351565b6001546001600160a01b031633146101bc5760405163064749d160e21b815260040160405180910390fd5b6040516370a0823160e01b81523060048201525f906001600160a01b038316906370a0823190602401602060405180830381865afa158015610200573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061022491906107c6565b60015490915061023f9083906001600160a01b031683610407565b5050565b335f9081526020819052604090205460ff166102725760405163983f976960e01b815260040160405180910390fd5b60405133907f0d03834d0d86c7f57e877af40e26f176dc31bd637535d4ba153d1ac9de88a7ea905f90a2565b5f6102a98383610473565b6001600160a01b0381165f81815260208190526040808220805460ff1916600117905551929350909133917f8ccec77b0cb63ac2cafd0f5de8cdfadab91ce656d262240ba8a6343bccc5f94591a36040516392eefe9b60e01b81523360048201526001600160a01b038216906392eefe9b906024015f604051808303815f87803b158015610335575f80fd5b505af1158015610347573d5f803e3d5ffd5b5050505092915050565b6001600160a01b038116610378576040516317945d4560e21b815260040160405180910390fd5b6001546001600160a01b031633146103a35760405163064749d160e21b815260040160405180910390fd5b6040516001600160a01b0382169033907f0571ff6d71d9d004e54297a3fb6b2a2caa93c1fda4662d3a958614dc0a2c5451905f90a36001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1663a9059cbb60e01b17905261046e9084906104f2565b505050565b5f7f0000000000000000000000009008d19f58aabd9ed0d60971565aa8510560ab417f362e5182440b52aa8fffe70a251550fbbcbca424740fe5a14f59bf0c1b06fe1d84846040516104c49061068d565b6104d1949392919061080b565b604051809103905ff0801580156104ea573d5f803e3d5ffd5b509392505050565b5f6105066001600160a01b03841683610558565b905080515f1415801561052a575080806020019051810190610528919061084f565b155b1561046e57604051635274afe760e01b81526001600160a01b03841660048201526024015b60405180910390fd5b606061056583835f61056c565b9392505050565b6060814710156105915760405163cd78605960e01b815230600482015260240161054f565b5f80856001600160a01b031684866040516105ac919061086e565b5f6040518083038185875af1925050503d805f81146105e6576040519150601f19603f3d011682016040523d82523d5f602084013e6105eb565b606091505b50915091506105fb868383610605565b9695505050505050565b60608261061a5761061582610661565b610565565b815115801561063157506001600160a01b0384163b155b1561065a57604051639996b31560e01b81526001600160a01b038516600482015260240161054f565b5080610565565b8051156106715780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b50565b6144098061088583390190565b6001600160a01b038116811461068a575f80fd5b5f602082840312156106be575f80fd5b81356105658161069a565b634e487b7160e01b5f52604160045260245ffd5b5f82601f8301126106ec575f80fd5b813567ffffffffffffffff80821115610707576107076106c9565b604051601f8301601f19908116603f0116810190828211818310171561072f5761072f6106c9565b81604052838152866020858801011115610747575f80fd5b836020870160208301375f602085830101528094505050505092915050565b5f8060408385031215610777575f80fd5b823567ffffffffffffffff8082111561078e575f80fd5b61079a868387016106dd565b935060208501359150808211156107af575f80fd5b506107bc858286016106dd565b9150509250929050565b5f602082840312156107d6575f80fd5b5051919050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b6001600160a01b0385168152836020820152608060408201525f61083260808301856107dd565b828103606084015261084481856107dd565b979650505050505050565b5f6020828403121561085f575f80fd5b81518015158114610565575f80fd5b5f82518060208501845e5f92019182525091905056fe610120604052348015610010575f80fd5b5060405161440938038061440983398101604081905261002f91610233565b81818181818160036100418382610330565b50600461004e8282610330565b5050600580546001600160a01b03191633908117909155608052506100829150620f42409050670de0b6b3a76400006103ef565b60065550506007805460ff191690556001600160a01b03841660e08190526040805163f698da2560e01b8152905163f698da25916004808201926020929091908290030181865afa1580156100d9573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100fd919061040e565b60c08181525050836001600160a01b0316639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610140573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101649190610425565b6001600160a01b031660a05250506101005250610445565b80516001600160a01b0381168114610192575f80fd5b919050565b634e487b7160e01b5f52604160045260245ffd5b5f82601f8301126101ba575f80fd5b81516001600160401b03808211156101d4576101d4610197565b604051601f8301601f19908116603f011681019082821181831017156101fc576101fc610197565b81604052838152866020858801011115610214575f80fd5b8360208701602083015e5f602085830101528094505050505092915050565b5f805f8060808587031215610246575f80fd5b61024f8561017c565b6020860151604087015191955093506001600160401b0380821115610272575f80fd5b61027e888389016101ab565b93506060870151915080821115610293575f80fd5b506102a0878288016101ab565b91505092959194509250565b600181811c908216806102c057607f821691505b6020821081036102de57634e487b7160e01b5f52602260045260245ffd5b50919050565b601f82111561032b57805f5260205f20601f840160051c810160208510156103095750805b601f840160051c820191505b81811015610328575f8155600101610315565b50505b505050565b81516001600160401b0381111561034957610349610197565b61035d8161035784546102ac565b846102e4565b602080601f831160018114610390575f84156103795750858301515b5f19600386901b1c1916600185901b1785556103e7565b5f85815260208120601f198616915b828110156103be5788860151825594840194600190910190840161039f565b50858210156103db57878501515f19600388901b60f8161c191681555b505060018460011b0185555b505050505050565b5f8261040957634e487b7160e01b5f52601260045260245ffd5b500490565b5f6020828403121561041e575f80fd5b5051919050565b5f60208284031215610435575f80fd5b61043e8261017c565b9392505050565b60805160a05160c05160e05161010051613f5d6104ac5f395f81816105800152610c5601525f818161061a0152612a5101525f818161077e0152610cd601525f81816104820152612e1c01525f81816104d6015281816120ef0152612e760152613f5d5ff3fe608060405234801561000f575f80fd5b506004361061039e575f3560e01c80639381cd2b116101ea578063c36596a611610114578063dd62ed3e116100a9578063f14fcbc811610079578063f14fcbc8146107fa578063f1b8a9b71461080d578063f8b2cb4f14610820578063f8d6aed414610833575f80fd5b8063dd62ed3e146107a0578063e4a28a52146103e3578063e4e1e538146107d8578063ec093021146107eb575f80fd5b8063cf5e7bd3116100e4578063cf5e7bd31461074b578063d4cadf681461075e578063d73dd62314610766578063da08c4dc14610779575f80fd5b8063c36596a61461045b578063c6580d1214610734578063cc77828d1461073b578063cd2ed8fb14610743575f80fd5b8063b02f0b731161018a578063ba9530a61161015a578063ba9530a6146106fc578063bc063e1a1461070f578063bc694ea214610717578063be3bbd2e1461071f575f80fd5b8063b02f0b73146106d1578063b0e0d136146106e4578063b7b800a4146106ec578063ba019dab146106f4575f80fd5b8063981a160b116101c5578063981a160b14610685578063992e2a92146106a3578063a221ee49146106ab578063a9059cbb146106be575f80fd5b80639381cd2b14610662578063948d8ce61461066a57806395d89b411461067d575f80fd5b8063313ce567116102cb57806376c7a3c71161026b5780638b54ab1f1161023b5780638b54ab1f146106155780638d4e40831461063c57806392eefe9b14610647578063936c34771461065a575f80fd5b806376c7a3c7146105ca5780637c5e9ea4146105d25780638201aa3f146105fa578063867378c51461060d575f80fd5b80634f69c0d4116102a65780634f69c0d41461055557806366188463146105685780636dbc88131461057b57806370a08231146105a2575f80fd5b8063313ce5671461052b57806334e199071461053a5780634bb278f31461054d575f80fd5b8063189d00ca1161034157806328bd64431161031157806328bd6443146104bc5780632dd31000146104d15780632f37b624146104f85780633018205f14610523575f80fd5b8063189d00ca14610453578063218b53821461045b57806323b872dd1461046a5780632626f2941461047d575f80fd5b80631446a7ff1161037c5780631446a7ff146103f957806315e84af91461040c5780631626ba7e1461041f57806318160ddd1461044b575f80fd5b806306fdde03146103a2578063095ea7b3146103c057806309a3bbe4146103e3575b5f80fd5b6103aa610846565b6040516103b791906137f9565b60405180910390f35b6103d36103ce36600461384d565b6108d6565b60405190151581526020016103b7565b6103eb6108ef565b6040519081526020016103b7565b6103eb610407366004613877565b610905565b6103eb61041a366004613877565b610aa4565b61043261042d36600461391d565b610c3c565b6040516001600160e01b031990911681526020016103b7565b6002546103eb565b6103eb610d6e565b6103eb670de0b6b3a764000081565b6103d36104783660046139b6565b610d85565b6104a47f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016103b7565b6104cf6104ca366004613a28565b610daa565b005b6104a47f000000000000000000000000000000000000000000000000000000000000000081565b6103d3610506366004613ae4565b6001600160a01b03165f9081526009602052604090205460ff1690565b6104a46110e9565b604051601281526020016103b7565b6104cf610548366004613aff565b611127565b6104cf611272565b6104cf610563366004613b16565b6113ab565b6103d361057636600461384d565b6115f0565b6103eb7f000000000000000000000000000000000000000000000000000000000000000081565b6103eb6105b0366004613ae4565b6001600160a01b03165f9081526020819052604090205490565b6103eb61163f565b6105e56105e0366004613b8e565b611654565b604080519283526020830191909152016103b7565b6105e5610608366004613b8e565b611a09565b6103eb611d8f565b6104a47f000000000000000000000000000000000000000000000000000000000000000081565b60075460ff166103d3565b6104cf610655366004613ae4565b611da6565b6103eb611e8b565b6103eb611ec0565b6103eb610678366004613ae4565b611ed3565b6103aa611f5b565b61068e61012c81565b60405163ffffffff90911681526020016103b7565b6103eb611f6a565b6103eb6106b9366004613bdc565b611f88565b6103d36106cc36600461384d565b611fee565b6104cf6106df366004613b16565b611ffb565b6103eb600881565b6103eb600281565b6103eb600181565b6103eb61070a366004613c13565b612281565b6103eb6122fd565b6103eb612324565b610727612343565b6040516103b79190613c52565b6103eb5f81565b6107276123f2565b6008546103eb565b6104cf610759366004613ae4565b612421565b6103eb61270e565b6103d361077436600461384d565b612743565b6103eb7f000000000000000000000000000000000000000000000000000000000000000081565b6103eb6107ae366004613877565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205490565b6104cf6107e6366004613c9e565b612782565b6103eb6706f05b59d3b2000081565b6104cf610808366004613aff565b612a19565b6103eb61081b366004613ae4565b612a98565b6103eb61082e366004613ae4565b612b27565b6103eb610841366004613c13565b612bf3565b60606003805461085590613cd0565b80601f016020809104026020016040519081016040528092919081815260200182805461088190613cd0565b80156108cc5780601f106108a3576101008083540402835291602001916108cc565b820191905f5260205f20905b8154815290600101906020018083116108af57829003601f168201915b5050505050905090565b5f336108e3818585612c72565b60019150505b92915050565b610902670de0b6b3a76400006032613d1c565b81565b5f5f80516020613f088339815191525c156109335760405163d56a08b560e01b815260040160405180910390fd5b6001600160a01b0383165f9081526009602052604090205460ff1661096b57604051634b16fc2d60e11b815260040160405180910390fd5b6001600160a01b0382165f9081526009602052604090205460ff166109a357604051634b16fc2d60e11b815260040160405180910390fd5b6001600160a01b038381165f8181526009602052604080822093861682529081902090516370a0823160e01b81523060048201529091610a9b916370a0823190602401602060405180830381865afa158015610a01573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a259190613d33565b60028401546040516370a0823160e01b81523060048201526001600160a01b038816906370a0823190602401602060405180830381865afa158015610a6c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a909190613d33565b84600201545f611f88565b95945050505050565b5f5f80516020613f088339815191525c15610ad25760405163d56a08b560e01b815260040160405180910390fd5b6001600160a01b0383165f9081526009602052604090205460ff16610b0a57604051634b16fc2d60e11b815260040160405180910390fd5b6001600160a01b0382165f9081526009602052604090205460ff16610b4257604051634b16fc2d60e11b815260040160405180910390fd5b6001600160a01b038381165f8181526009602052604080822093861682529081902090516370a0823160e01b81523060048201529091610a9b916370a0823190602401602060405180830381865afa158015610ba0573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bc49190613d33565b60028401546040516370a0823160e01b81523060048201526001600160a01b038816906370a0823190602401602060405180830381865afa158015610c0b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c2f9190613d33565b8460020154600654611f88565b5f8082806020019051810190610c529190613d6b565b90507f00000000000000000000000000000000000000000000000000000000000000008160c0015114610c9857604051630e1a1b6360e41b815260040160405180910390fd5b601f19810180517fd5a25ba2e97094ad7d83dc28a6572da797d6b3e7fc6663bd93efb789fc17e48982526101a08220915260405161190160f01b81527f00000000000000000000000000000000000000000000000000000000000000006002820152602281019190915260429020848114610d265760405163593fcacd60e01b815260040160405180910390fd5b5f80516020613f088339815191525c8114610d545760405163dafbdd1f60e01b815260040160405180910390fd5b610d5d82610daa565b50630b135d3f60e11b949350505050565b6109026402540be400670de0b6b3a7640000613e3b565b5f33610d92858285612c7f565b610d9d858585612cff565b60019150505b9392505050565b6020808201516001600160a01b039081165f90815260098084526040808320815160608082018452825460ff90811615158352600180850154848b0152600294850154848701528a519098168752948852948390208351958601845280549094161515855294830154958401959095529301549281019290925280519091901580610e3457508051155b15610e5257604051634b16fc2d60e11b815260040160405180910390fd5b60408301516001600160a01b031615610e7d57604051623c9da560e61b815260040160405180910390fd5b610e8961012c42613e5a565b8360a0015163ffffffff161115610eb35760405163326389f960e11b815260040160405180910390fd5b60e083015115610ed557604051620e5bdf60e41b815260040160405180910390fd5b7ff3b277728b3fee749481eb3e0b3b48980dbbab78658fc419025cb16eee34677583610100015114610f1a57604051632c9634af60e01b815260040160405180910390fd5b7f5a28e9363bb942b639270062aa6bb295f434bcdfc42c97267bf003f272060dc9836101600151141580610f7357507f5a28e9363bb942b639270062aa6bb295f434bcdfc42c97267bf003f272060dc983610140015114155b15610f91576040516397a2328160e01b815260040160405180910390fd5b60208301516040516370a0823160e01b81523060048201525f916001600160a01b0316906370a0823190602401602060405180830381865afa158015610fd9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ffd9190613d33565b9050611011816706f05b59d3b20000612d5c565b846080015111156110355760405163558fcd9160e11b815260040160405180910390fd5b604080840151855191516370a0823160e01b81523060048201525f926110bb92859290916001600160a01b0316906370a0823190602401602060405180830381865afa158015611087573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110ab9190613d33565b866040015189608001515f612281565b905084606001518110156110e25760405163d6ac339560e01b815260040160405180910390fd5b5050505050565b5f5f80516020613f088339815191525c156111175760405163d56a08b560e01b815260040160405180910390fd5b506005546001600160a01b031690565b336001600160a01b03165f356001600160e01b0319166001600160e01b0319165f36604051611157929190613e6d565b60405180910390a25f80516020613f088339815191525c1561118c5760405163d56a08b560e01b815260040160405180910390fd5b6111966001612ddf565b6005546001600160a01b031633146111c157604051634f0f549960e11b815260040160405180910390fd5b60075460ff16156111e55760405163056f633d60e21b815260040160405180910390fd5b6111fa620f4240670de0b6b3a7640000613e3b565b81101561121a57604051633b46575d60e01b815260040160405180910390fd5b61122f620f4240670de0b6b3a7640000613e3b565b61124190670de0b6b3a7640000613e9b565b81111561126157604051630f71fbbf60e11b815260040160405180910390fd5b600681905561126f5f612ddf565b50565b336001600160a01b03165f356001600160e01b0319166001600160e01b0319165f366040516112a2929190613e6d565b60405180910390a25f80516020613f088339815191525c156112d75760405163d56a08b560e01b815260040160405180910390fd5b6112e16001612ddf565b6005546001600160a01b0316331461130c57604051634f0f549960e11b815260040160405180910390fd5b60075460ff16156113305760405163056f633d60e21b815260040160405180910390fd5b600854600211156113545760405163af785ec560e01b815260040160405180910390fd5b6007805460ff1916600117905561137c611377670de0b6b3a76400006064613d1c565b612df2565b61139833611393670de0b6b3a76400006064613d1c565b612dfc565b6113a0612e0a565b6113a95f612ddf565b565b336001600160a01b03165f356001600160e01b0319166001600160e01b0319165f366040516113db929190613e6d565b60405180910390a25f80516020613f088339815191525c156114105760405163d56a08b560e01b815260040160405180910390fd5b61141a6001612ddf565b60075460ff1661143d57604051632e41ba2d60e01b815260040160405180910390fd5b5f61144760025490565b90505f6114548583612f0e565b9050805f0361147657604051630c499f4760e01b815260040160405180910390fd5b6008545f5b818110156115c9575f6008828154811061149757611497613eae565b5f9182526020822001546040516370a0823160e01b81523060048201526001600160a01b03909116925082906370a0823190602401602060405180830381865afa1580156114e7573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061150b9190613d33565b90505f6115188683612d5c565b9050805f0361153a57604051635b00df6960e11b815260040160405180910390fd5b88888581811061154c5761154c613eae565b9050602002013581111561157357604051630451d9ed60e31b815260040160405180910390fd5b6040518181526001600160a01b0384169033907f63982df10efd8dfaaaa0fcc7f50b2d93b7cba26ccc48adee2873220d485dc39a9060200160405180910390a36115be833383612fb6565b50505060010161147b565b506115d386612df2565b6115dd3387612dfc565b5050506115eb5f801b612ddf565b505050565b335f9081526001602090815260408083206001600160a01b03861684529091528120548083111561162b5761162633855f612c72565b6108e3565b6108e3338561163a8685613e9b565b612c72565b610902620f4240670de0b6b3a7640000613e3b565b6040515f90819033906001600160e01b0319833516906116779084903690613e6d565b60405180910390a25f80516020613f088339815191525c156116ac5760405163d56a08b560e01b815260040160405180910390fd5b6116b66001612ddf565b60075460ff166116d957604051632e41ba2d60e01b815260040160405180910390fd5b6001600160a01b0387165f9081526009602052604090205460ff1661171157604051634b16fc2d60e11b815260040160405180910390fd5b6001600160a01b0385165f9081526009602052604090205460ff1661174957604051634b16fc2d60e11b815260040160405180910390fd5b6001600160a01b038781165f81815260096020526040808220938916825280822090516370a0823160e01b81523060048201529092906370a0823190602401602060405180830381865afa1580156117a3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117c79190613d33565b6040516370a0823160e01b81523060048201529091505f906001600160a01b038a16906370a0823190602401602060405180830381865afa15801561180e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118329190613d33565b905061185b8161184b6003670de0b6b3a7640000613e3b565b611856906001613e5a565b612d5c565b88111561187b5760405163dad25d8560e01b815260040160405180910390fd5b5f611893838660020154848760020154600654611f88565b9050878111156118b65760405163823a9c3760e01b815260040160405180910390fd5b6118ce8386600201548487600201548d600654612bf3565b96508a8711156118f157604051630451d9ed60e31b815260040160405180910390fd5b6118fb8388612fcb565b9250611907828a612ff0565b9150611920838660020154848760020154600654611f88565b95508086101561194357604051636212302360e01b815260040160405180910390fd5b878611156119645760405163823a9c3760e01b815260040160405180910390fd5b61196e878a612f0e565b81111561198e576040516337fb98f960e11b815260040160405180910390fd5b60408051888152602081018b90526001600160a01b03808d1692908f169133917f908fb5ee8f16c6bc9bc3690973819f32a4d4b10188134543c88706e0e1d43378910160405180910390a46119e48c3389612fb6565b6119ef8a338b613028565b50505050506119ff5f801b612ddf565b9550959350505050565b6040515f90819033906001600160e01b031983351690611a2c9084903690613e6d565b60405180910390a25f80516020613f088339815191525c15611a615760405163d56a08b560e01b815260040160405180910390fd5b611a6b6001612ddf565b60075460ff16611a8e57604051632e41ba2d60e01b815260040160405180910390fd5b6001600160a01b0387165f9081526009602052604090205460ff16611ac657604051634b16fc2d60e11b815260040160405180910390fd5b6001600160a01b0385165f9081526009602052604090205460ff16611afe57604051634b16fc2d60e11b815260040160405180910390fd5b6001600160a01b038781165f81815260096020526040808220938916825280822090516370a0823160e01b81523060048201529092906370a0823190602401602060405180830381865afa158015611b58573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b7c9190613d33565b6040516370a0823160e01b81523060048201529091505f906001600160a01b038a16906370a0823190602401602060405180830381865afa158015611bc3573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611be79190613d33565b9050611bfb826706f05b59d3b20000612d5c565b8a1115611c1b5760405163558fcd9160e11b815260040160405180910390fd5b5f611c33838660020154848760020154600654611f88565b905087811115611c565760405163823a9c3760e01b815260040160405180910390fd5b611c6e8386600201548487600201548f600654612281565b965088871015611c915760405163d6ac339560e01b815260040160405180910390fd5b611c9b838c612fcb565b9250611ca78288612ff0565b9150611cc0838660020154848760020154600654611f88565b955080861015611ce357604051636212302360e01b815260040160405180910390fd5b87861115611d045760405163823a9c3760e01b815260040160405180910390fd5b611d0e8b88612f0e565b811115611d2e576040516337fb98f960e11b815260040160405180910390fd5b604080518c8152602081018990526001600160a01b03808d1692908f169133917f908fb5ee8f16c6bc9bc3690973819f32a4d4b10188134543c88706e0e1d43378910160405180910390a4611d848c338d612fb6565b6119ef8a3389613028565b61090264e8d4a51000670de0b6b3a7640000613e3b565b336001600160a01b03165f356001600160e01b0319166001600160e01b0319165f36604051611dd6929190613e6d565b60405180910390a25f80516020613f088339815191525c15611e0b5760405163d56a08b560e01b815260040160405180910390fd5b611e156001612ddf565b6005546001600160a01b03163314611e4057604051634f0f549960e11b815260040160405180910390fd5b6001600160a01b038116611e67576040516351a9e5c560e01b815260040160405180910390fd5b600580546001600160a01b0319166001600160a01b03831617905561126f5f612ddf565b5f5f80516020613f088339815191525c15611eb95760405163d56a08b560e01b815260040160405180910390fd5b50600a5490565b610902670de0b6b3a76400006064613d1c565b5f5f80516020613f088339815191525c15611f015760405163d56a08b560e01b815260040160405180910390fd5b6001600160a01b0382165f9081526009602052604090205460ff16611f3957604051634b16fc2d60e11b815260040160405180910390fd5b506001600160a01b0381165f908152600960205260409020600201545b919050565b60606004805461085590613cd0565b611f7d6003670de0b6b3a7640000613e3b565b610902906001613e5a565b5f80611f948787612f0e565b90505f611fa18686612f0e565b90505f611fae8383612f0e565b90505f611fd4670de0b6b3a7640000611fcf670de0b6b3a764000089612ff0565b612f0e565b9050611fe08282612d5c565b9a9950505050505050505050565b5f336108e3818585612cff565b336001600160a01b03165f356001600160e01b0319166001600160e01b0319165f3660405161202b929190613e6d565b60405180910390a25f80516020613f088339815191525c156120605760405163d56a08b560e01b815260040160405180910390fd5b61206a6001612ddf565b60075460ff1661208d57604051632e41ba2d60e01b815260040160405180910390fd5b5f61209760025490565b90505f6120a4855f612d5c565b90505f6120b18683612ff0565b90505f6120be8285612f0e565b9050805f036120e057604051630c499f4760e01b815260040160405180910390fd5b6120ea338861303c565b6121147f000000000000000000000000000000000000000000000000000000000000000084612dfc565b61211d82613046565b6008545f5b81811015612270575f6008828154811061213e5761213e613eae565b5f9182526020822001546040516370a0823160e01b81523060048201526001600160a01b03909116925082906370a0823190602401602060405180830381865afa15801561218e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121b29190613d33565b90505f6121bf8683612d5c565b9050805f036121e157604051634b4ae51b60e11b815260040160405180910390fd5b8a8a858181106121f3576121f3613eae565b9050602002013581101561221a5760405163341a1f3360e11b815260040160405180910390fd5b6040518181526001600160a01b0384169033907fe74c91552b64c2e2e7bd255639e004e693bd3e1d01cc33e65610b86afcc1ffed9060200160405180910390a3612265833383613028565b505050600101612122565b5050505050506115eb5f801b612ddf565b5f8061228d8786612f0e565b90505f6122a2670de0b6b3a764000085612ff0565b90506122ae8582612d5c565b90505f6122bf8a611fcf8c85612fcb565b90505f6122cc8285613050565b90505f6122e1670de0b6b3a764000083612ff0565b90506122ed8a82612d5c565b9c9b505050505050505050505050565b612312620f4240670de0b6b3a7640000613e3b565b61090290670de0b6b3a7640000613e9b565b6001612339670de0b6b3a76400006002613d1c565b6109029190613e9b565b60605f80516020613f088339815191525c156123725760405163d56a08b560e01b815260040160405180910390fd5b60075460ff1661239557604051632e41ba2d60e01b815260040160405180910390fd5b60088054806020026020016040519081016040528092919081815260200182805480156108cc57602002820191905f5260205f20905b81546001600160a01b031681526001909101906020018083116123cb575050505050905090565b60605f80516020613f088339815191525c156123955760405163d56a08b560e01b815260040160405180910390fd5b336001600160a01b03165f356001600160e01b0319166001600160e01b0319165f36604051612451929190613e6d565b60405180910390a25f80516020613f088339815191525c156124865760405163d56a08b560e01b815260040160405180910390fd5b6124906001612ddf565b6005546001600160a01b031633146124bb57604051634f0f549960e11b815260040160405180910390fd5b60075460ff16156124df5760405163056f633d60e21b815260040160405180910390fd5b6001600160a01b0381165f9081526009602052604090205460ff1661251757604051634b16fc2d60e11b815260040160405180910390fd5b600a546001600160a01b0382165f9081526009602052604090206002015461253f9190612ff0565b600a556001600160a01b0381165f90815260096020526040812060019081015460085490929161256e91613e9b565b90506008818154811061258357612583613eae565b5f91825260209091200154600880546001600160a01b0390921691849081106125ae576125ae613eae565b905f5260205f20015f6101000a8154816001600160a01b0302191690836001600160a01b031602179055508160095f600885815481106125f0576125f0613eae565b5f9182526020808320909101546001600160a01b03168352820192909252604001902060010155600880548061262857612628613ec2565b5f82815260208082205f19908401810180546001600160a01b0319169055909201909255604080516060810182528381528083018481528183018581526001600160a01b0389168087526009909552948390209151825460ff1916901515178255516001820155925160029093019290925590516370a0823160e01b81523060048201526127029185913391906370a0823190602401602060405180830381865afa1580156126d9573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126fd9190613d33565b613028565b5061126f90505f612ddf565b5f5f80516020613f088339815191525c1561273c5760405163d56a08b560e01b815260040160405180910390fd5b5060065490565b335f8181526001602090815260408083206001600160a01b0387168452909152812054909161277991859061163a908690613e5a565b50600192915050565b336001600160a01b03165f356001600160e01b0319166001600160e01b0319165f366040516127b2929190613e6d565b60405180910390a25f80516020613f088339815191525c156127e75760405163d56a08b560e01b815260040160405180910390fd5b6127f16001612ddf565b6005546001600160a01b0316331461281c57604051634f0f549960e11b815260040160405180910390fd5b60075460ff16156128405760405163056f633d60e21b815260040160405180910390fd5b6001600160a01b0383165f9081526009602052604090205460ff161561287957604051636b1ed1b760e11b815260040160405180910390fd5b600880541061289b5760405163c47f9e9360e01b815260040160405180910390fd5b670de0b6b3a76400008110156128c4576040516342eb024360e01b815260040160405180910390fd5b6128d7670de0b6b3a76400006032613d1c565b8111156128f757604051630cbe784360e11b815260040160405180910390fd5b61290e64e8d4a51000670de0b6b3a7640000613e3b565b82101561292e57604051638968448b60e01b815260040160405180910390fd5b61293a600a5482612fcb565b600a55612950670de0b6b3a76400006032613d1c565b600a541115612972576040516342f71f0b60e01b815260040160405180910390fd5b6040805160608101825260018082526008805460208085019182528486018781526001600160a01b038a165f81815260099093529682209551865460ff19169015151786559151858501559051600290940193909355805491820181559091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30180546001600160a01b0319169091179055612a10833384612fb6565b6115eb5f612ddf565b5f80516020613f088339815191525c15612a465760405163d56a08b560e01b815260040160405180910390fd5b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614612a8f5760405163bf84897760e01b815260040160405180910390fd5b61126f81612ddf565b5f5f80516020613f088339815191525c15612ac65760405163d56a08b560e01b815260040160405180910390fd5b6001600160a01b0382165f9081526009602052604090205460ff16612afe57604051634b16fc2d60e11b815260040160405180910390fd5b6001600160a01b0382165f90815260096020526040902060020154600a54610da3908290612f0e565b5f5f80516020613f088339815191525c15612b555760405163d56a08b560e01b815260040160405180910390fd5b6001600160a01b0382165f9081526009602052604090205460ff16612b8d57604051634b16fc2d60e11b815260040160405180910390fd5b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015612bcf573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108e99190613d33565b5f80612bff8588612f0e565b90505f612c0c8786612ff0565b90505f612c198883612f0e565b90505f612c268285613050565b9050612c3a81670de0b6b3a7640000612ff0565b9050612c4e670de0b6b3a764000087612ff0565b9450612c63612c5d8c83612d5c565b86612f0e565b9b9a5050505050505050505050565b6115eb8383836001613105565b6001600160a01b038381165f908152600160209081526040808320938616835292905220545f198114612cf95781811015612ceb57604051637dc7a0d960e11b81526001600160a01b038416600482015260248101829052604481018390526064015b60405180910390fd5b612cf984848484035f613105565b50505050565b6001600160a01b038316612d2857604051634b637e8f60e11b81525f6004820152602401612ce2565b6001600160a01b038216612d515760405163ec442f0560e01b81525f6004820152602401612ce2565b6115eb8383836131d7565b5f8282028315801590612d7e575082848281612d7a57612d7a613e27565b0414155b15612d9c5760405163202e377f60e01b815260040160405180910390fd5b6706f05b59d3b20000810181811015612dc85760405163202e377f60e01b815260040160405180910390fd5b5f670de0b6b3a7640000825b049695505050505050565b805f80516020613f088339815191525d50565b61126f30826132fd565b612e068282613331565b5050565b6008545f5b81811015612e7357612e6b7f00000000000000000000000000000000000000000000000000000000000000005f1960088481548110612e5057612e50613eae565b5f918252602090912001546001600160a01b0316919061333c565b600101612e0f565b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166352b8cb636040518163ffffffff1660e01b81526004015f604051808303815f87803b158015612ecc575f80fd5b505af1925050508015612edd575060015b61126f5760405130907f0d03834d0d86c7f57e877af40e26f176dc31bd637535d4ba153d1ac9de88a7ea905f90a250565b5f815f03612f2f5760405163abcf2e7560e01b815260040160405180910390fd5b670de0b6b3a764000083028315801590612f605750670de0b6b3a7640000848281612f5c57612f5c613e27565b0414155b15612f7e576040516394fb03d760e01b815260040160405180910390fd5b600183901c810181811015612fa6576040516394fb03d760e01b815260040160405180910390fd5b5f848281612dd457612dd4613e27565b6115eb6001600160a01b0384168330846133f9565b5f82820183811015610da35760405163e468448f60e01b815260040160405180910390fd5b5f805f612ffd8585613432565b91509150801561302057604051630a5c778b60e31b815260040160405180910390fd5b509392505050565b6115eb6001600160a01b0384168383613455565b612e068282613486565b61126f3082613491565b5f600183101561307357604051635567969f60e11b815260040160405180910390fd5b671bc16d674ec7ffff83111561309c57604051638554775f60e01b815260040160405180910390fd5b670de0b6b3a7640000808304025f6130b48483612ff0565b90505f6130cb86670de0b6b3a764000085046134c5565b9050815f036130de5792506108e9915050565b5f6130ee87846305f5e10061351d565b90506130fa8282612d5c565b979650505050505050565b6001600160a01b03841661312e5760405163e602df0560e01b81525f6004820152602401612ce2565b6001600160a01b03831661315757604051634a1406b160e11b81525f6004820152602401612ce2565b6001600160a01b038085165f9081526001602090815260408083209387168352929052208290558015612cf957826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516131c991815260200190565b60405180910390a350505050565b6001600160a01b038316613201578060025f8282546131f69190613e5a565b909155506132719050565b6001600160a01b0383165f90815260208190526040902054818110156132535760405163391434e360e21b81526001600160a01b03851660048201526024810182905260448101839052606401612ce2565b6001600160a01b0384165f9081526020819052604090209082900390555b6001600160a01b03821661328d576002805482900390556132ab565b6001600160a01b0382165f9081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516132f091815260200190565b60405180910390a3505050565b6001600160a01b0382166133265760405163ec442f0560e01b81525f6004820152602401612ce2565b612e065f83836131d7565b612e06308383612cff565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b17905261338d84826135f9565b612cf9576040516001600160a01b0384811660248301525f60448301526133ef91869182169063095ea7b3906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050613696565b612cf98482613696565b6040516001600160a01b038481166024830152838116604483015260648201839052612cf99186918216906323b872dd906084016133bd565b5f808284106134465750508082035f61344e565b505081810360015b9250929050565b6040516001600160a01b038381166024830152604482018390526115eb91859182169063a9059cbb906064016133bd565b612e06823083612cff565b6001600160a01b0382166134ba57604051634b637e8f60e11b81525f6004820152602401612ce2565b612e06825f836131d7565b5f80600283065f036134df57670de0b6b3a76400006134e1565b835b90506002830492505b8215610da3576134fa8485612d5c565b935060028306156135125761350f8185612d5c565b90505b6002830492506134ea565b5f82818061353387670de0b6b3a7640000613432565b9092509050670de0b6b3a7640000805f60015b8884106135ea575f670de0b6b3a7640000820290505f806135788a61357385670de0b6b3a7640000612ff0565b613432565b9150915061358a87611856848c612d5c565b96506135968784612f0e565b9650865f036135a7575050506135ea565b87156135b1579315935b80156135bb579315935b84156135d2576135cb8688612ff0565b95506135df565b6135dc8688612fcb565b95505b505050600101613546565b50909998505050505050505050565b5f805f846001600160a01b0316846040516136149190613ed6565b5f604051808303815f865af19150503d805f811461364d576040519150601f19603f3d011682016040523d82523d5f602084013e613652565b606091505b509150915081801561367c57508051158061367c57508080602001905181019061367c9190613eec565b8015610a9b5750505050506001600160a01b03163b151590565b5f6136aa6001600160a01b038416836136f7565b905080515f141580156136ce5750808060200190518101906136cc9190613eec565b155b156115eb57604051635274afe760e01b81526001600160a01b0384166004820152602401612ce2565b6060610da383835f845f80856001600160a01b0316848660405161371b9190613ed6565b5f6040518083038185875af1925050503d805f8114613755576040519150601f19603f3d011682016040523d82523d5f602084013e61375a565b606091505b509150915061376a868383613774565b9695505050505050565b60608261378957613784826137d0565b610da3565b81511580156137a057506001600160a01b0384163b155b156137c957604051639996b31560e01b81526001600160a01b0385166004820152602401612ce2565b5080610da3565b8051156137e05780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b6001600160a01b038116811461126f575f80fd5b8035611f568161382e565b5f806040838503121561385e575f80fd5b82356138698161382e565b946020939093013593505050565b5f8060408385031215613888575f80fd5b82356138938161382e565b915060208301356138a38161382e565b809150509250929050565b634e487b7160e01b5f52604160045260245ffd5b604051610180810167ffffffffffffffff811182821017156138e6576138e66138ae565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715613915576139156138ae565b604052919050565b5f806040838503121561392e575f80fd5b8235915060208084013567ffffffffffffffff8082111561394d575f80fd5b818601915086601f830112613960575f80fd5b813581811115613972576139726138ae565b613984601f8201601f191685016138ec565b91508082528784828501011115613999575f80fd5b80848401858401375f848284010152508093505050509250929050565b5f805f606084860312156139c8575f80fd5b83356139d38161382e565b925060208401356139e38161382e565b929592945050506040919091013590565b63ffffffff8116811461126f575f80fd5b8035611f56816139f4565b801515811461126f575f80fd5b8035611f5681613a10565b5f6101808284031215613a39575f80fd5b613a416138c2565b613a4a83613842565b8152613a5860208401613842565b6020820152613a6960408401613842565b60408201526060830135606082015260808301356080820152613a8e60a08401613a05565b60a082015260c083013560c082015260e083013560e0820152610100808401358183015250610120613ac1818501613a1d565b908201526101408381013590820152610160928301359281019290925250919050565b5f60208284031215613af4575f80fd5b8135610da38161382e565b5f60208284031215613b0f575f80fd5b5035919050565b5f805f60408486031215613b28575f80fd5b83359250602084013567ffffffffffffffff80821115613b46575f80fd5b818601915086601f830112613b59575f80fd5b813581811115613b67575f80fd5b8760208260051b8501011115613b7b575f80fd5b6020830194508093505050509250925092565b5f805f805f60a08688031215613ba2575f80fd5b8535613bad8161382e565b9450602086013593506040860135613bc48161382e565b94979396509394606081013594506080013592915050565b5f805f805f60a08688031215613bf0575f80fd5b505083359560208501359550604085013594606081013594506080013592509050565b5f805f805f8060c08789031215613c28575f80fd5b505084359660208601359650604086013595606081013595506080810135945060a0013592509050565b602080825282518282018190525f9190848201906040850190845b81811015613c925783516001600160a01b031683529284019291840191600101613c6d565b50909695505050505050565b5f805f60608486031215613cb0575f80fd5b8335613cbb8161382e565b95602085013595506040909401359392505050565b600181811c90821680613ce457607f821691505b602082108103613d0257634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52601160045260245ffd5b80820281158282048414176108e9576108e9613d08565b5f60208284031215613d43575f80fd5b5051919050565b8051611f568161382e565b8051611f56816139f4565b8051611f5681613a10565b5f6101808284031215613d7c575f80fd5b613d846138c2565b613d8d83613d4a565b8152613d9b60208401613d4a565b6020820152613dac60408401613d4a565b60408201526060830151606082015260808301516080820152613dd160a08401613d55565b60a082015260c083015160c082015260e083015160e0820152610100808401518183015250610120613e04818501613d60565b908201526101408381015190820152610160928301519281019290925250919050565b634e487b7160e01b5f52601260045260245ffd5b5f82613e5557634e487b7160e01b5f52601260045260245ffd5b500490565b808201808211156108e9576108e9613d08565b60208152816020820152818360408301375f818301604090810191909152601f909201601f19160101919050565b818103818111156108e9576108e9613d08565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52603160045260245ffd5b5f82518060208501845e5f920191825250919050565b5f60208284031215613efc575f80fd5b8151610da381613a1056fe3f8f4c536ce1b925b469af1b09a44da237dab5bbc584585648c12be1ca25a8c4a26469706673582212201c2ab66e24826998fe1115ecda27a1ca1f02b6dd605dfec58cf6ededc7327f0764736f6c63430008190033a2646970667358221220d96d5f31f034eaa8368c9c67131bf5f91bde789b0b870d0a9def6b1531e8c34e64736f6c63430008190033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000009008d19f58aabd9ed0d60971565aa8510560ab41362e5182440b52aa8fffe70a251550fbbcbca424740fe5a14f59bf0c1b06fe1d
-----Decoded View---------------
Arg [0] : solutionSettler (address): 0x9008D19f58AAbD9eD0D60971565AA8510560ab41
Arg [1] : appData (bytes32): 0x362e5182440b52aa8fffe70a251550fbbcbca424740fe5a14f59bf0c1b06fe1d
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000009008d19f58aabd9ed0d60971565aa8510560ab41
Arg [1] : 362e5182440b52aa8fffe70a251550fbbcbca424740fe5a14f59bf0c1b06fe1d
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.