Source Code
More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 909 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Approve | 397005126 | 81 days ago | IN | 0 ETH | 0.00000026 | ||||
| Approve | 396837045 | 82 days ago | IN | 0 ETH | 0.00000159 | ||||
| Approve | 396412515 | 83 days ago | IN | 0 ETH | 0.00001099 | ||||
| Approve | 396334350 | 83 days ago | IN | 0 ETH | 0.00000025 | ||||
| Approve | 385778214 | 114 days ago | IN | 0 ETH | 0.00000025 | ||||
| Approve | 379725700 | 131 days ago | IN | 0 ETH | 0.00000028 | ||||
| Approve | 379411321 | 132 days ago | IN | 0 ETH | 0.00000028 | ||||
| Approve | 374211536 | 147 days ago | IN | 0 ETH | 0.00000025 | ||||
| Exit Pool | 362538721 | 181 days ago | IN | 0 ETH | 0.00000835 | ||||
| Exit Pool | 352726104 | 209 days ago | IN | 0 ETH | 0.00000171 | ||||
| Exit Pool | 338299674 | 251 days ago | IN | 0 ETH | 0.00000154 | ||||
| Exit Pool | 329447476 | 277 days ago | IN | 0 ETH | 0.00000361 | ||||
| Exit Pool | 329438313 | 277 days ago | IN | 0 ETH | 0.00001639 | ||||
| Exit Pool | 329432742 | 277 days ago | IN | 0 ETH | 0.00000926 | ||||
| Exit Pool | 329422464 | 277 days ago | IN | 0 ETH | 0.00002271 | ||||
| Exit Pool | 329402937 | 277 days ago | IN | 0 ETH | 0.00001794 | ||||
| Exit Pool | 329393454 | 277 days ago | IN | 0 ETH | 0.00011677 | ||||
| Exit Pool | 328717984 | 279 days ago | IN | 0 ETH | 0.00000597 | ||||
| Exit Pool | 328671801 | 279 days ago | IN | 0 ETH | 0.00000134 | ||||
| Exit Pool | 323165977 | 295 days ago | IN | 0 ETH | 0.00000134 | ||||
| Approve | 311075634 | 330 days ago | IN | 0 ETH | 0.00000028 | ||||
| Approve | 310478215 | 332 days ago | IN | 0 ETH | 0.00000223 | ||||
| Approve | 304895663 | 348 days ago | IN | 0 ETH | 0.00000062 | ||||
| Exit Pool | 300961382 | 360 days ago | IN | 0 ETH | 0.0000016 | ||||
| Approve | 300765286 | 360 days ago | IN | 0 ETH | 0.00000034 |
Latest 1 internal transaction
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 249675450 | 509 days ago | Contract Creation | 0 ETH |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
BCoWPool
Compiler Version
v0.8.25+commit.b61c2a91
Contract Source Code (Solidity Standard Json-Input format)
// 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 virtual 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;
/**
* @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 {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 {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 {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: 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: 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: 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: 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/",
"halmos-cheatcodes/=node_modules/halmos-cheatcodes/",
"@crytic/=node_modules/@crytic/",
"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/",
"halmos-cheatcodes/=node_modules/halmos-cheatcodes/",
"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",
"abi"
]
}
},
"evmVersion": "cancun",
"viaIR": false,
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"cowSolutionSettler","type":"address"},{"internalType":"bytes32","name":"appData","type":"bytes32"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"AppDataDoesNotMatch","type":"error"},{"inputs":[],"name":"BCoWPool_FeeMustBeZero","type":"error"},{"inputs":[],"name":"BCoWPool_InvalidBalanceMarker","type":"error"},{"inputs":[],"name":"BCoWPool_InvalidOperation","type":"error"},{"inputs":[],"name":"BCoWPool_OrderValidityTooLong","type":"error"},{"inputs":[],"name":"BCoWPool_ReceiverIsNotBCoWPool","type":"error"},{"inputs":[],"name":"BNum_AddOverflow","type":"error"},{"inputs":[],"name":"BNum_BPowBaseTooHigh","type":"error"},{"inputs":[],"name":"BNum_BPowBaseTooLow","type":"error"},{"inputs":[],"name":"BNum_DivInternal","type":"error"},{"inputs":[],"name":"BNum_DivZero","type":"error"},{"inputs":[],"name":"BNum_MulOverflow","type":"error"},{"inputs":[],"name":"BNum_SubUnderflow","type":"error"},{"inputs":[],"name":"BPool_AddressZero","type":"error"},{"inputs":[],"name":"BPool_BalanceBelowMinimum","type":"error"},{"inputs":[],"name":"BPool_CallerIsNotController","type":"error"},{"inputs":[],"name":"BPool_FeeAboveMaximum","type":"error"},{"inputs":[],"name":"BPool_FeeBelowMinimum","type":"error"},{"inputs":[],"name":"BPool_InvalidPoolAmountIn","type":"error"},{"inputs":[],"name":"BPool_InvalidPoolRatio","type":"error"},{"inputs":[],"name":"BPool_InvalidTokenAmountIn","type":"error"},{"inputs":[],"name":"BPool_InvalidTokenAmountOut","type":"error"},{"inputs":[],"name":"BPool_PoolAmountInAboveMaxPoolAmountIn","type":"error"},{"inputs":[],"name":"BPool_PoolAmountOutBelowMinPoolAmountOut","type":"error"},{"inputs":[],"name":"BPool_PoolIsFinalized","type":"error"},{"inputs":[],"name":"BPool_PoolNotFinalized","type":"error"},{"inputs":[],"name":"BPool_Reentrancy","type":"error"},{"inputs":[],"name":"BPool_SpotPriceAboveMaxPrice","type":"error"},{"inputs":[],"name":"BPool_SpotPriceAfterBelowSpotPriceBefore","type":"error"},{"inputs":[],"name":"BPool_SpotPriceBeforeAboveTokenRatio","type":"error"},{"inputs":[],"name":"BPool_TokenAlreadyBound","type":"error"},{"inputs":[],"name":"BPool_TokenAmountInAboveMaxAmountIn","type":"error"},{"inputs":[],"name":"BPool_TokenAmountInAboveMaxRatio","type":"error"},{"inputs":[],"name":"BPool_TokenAmountOutAboveMaxOut","type":"error"},{"inputs":[],"name":"BPool_TokenAmountOutBelowMinAmountOut","type":"error"},{"inputs":[],"name":"BPool_TokenAmountOutBelowMinOut","type":"error"},{"inputs":[],"name":"BPool_TokenNotBound","type":"error"},{"inputs":[],"name":"BPool_TokensAboveMaximum","type":"error"},{"inputs":[],"name":"BPool_TokensBelowMinimum","type":"error"},{"inputs":[],"name":"BPool_TotalWeightAboveMaximum","type":"error"},{"inputs":[],"name":"BPool_WeightAboveMaximum","type":"error"},{"inputs":[],"name":"BPool_WeightBelowMinimum","type":"error"},{"inputs":[],"name":"CommitOutsideOfSettlement","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC20InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC20InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC20InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"ERC20InvalidSpender","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"OrderDoesNotMatchCommitmentHash","type":"error"},{"inputs":[],"name":"OrderDoesNotMatchMessageHash","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"bCoWPool","type":"address"}],"name":"COWAMMPoolCreated","type":"event"},{"anonymous":true,"inputs":[{"indexed":true,"internalType":"bytes4","name":"sig","type":"bytes4"},{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"LOG_CALL","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"tokenOut","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenAmountOut","type":"uint256"}],"name":"LOG_EXIT","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"tokenIn","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenAmountIn","type":"uint256"}],"name":"LOG_JOIN","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"tokenIn","type":"address"},{"indexed":true,"internalType":"address","name":"tokenOut","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenAmountIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokenAmountOut","type":"uint256"}],"name":"LOG_SWAP","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"APP_DATA","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BONE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BPOW_PRECISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EXIT_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FACTORY","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"INIT_POOL_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_BOUND_TOKENS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_BPOW_BASE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_IN_RATIO","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_ORDER_DURATION","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_OUT_RATIO","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_TOTAL_WEIGHT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_WEIGHT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_BALANCE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_BOUND_TOKENS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_BPOW_BASE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_WEIGHT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SOLUTION_SETTLER","outputs":[{"internalType":"contract ISettlement","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SOLUTION_SETTLER_DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VAULT_RELAYER","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"denorm","type":"uint256"}],"name":"bind","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenBalanceIn","type":"uint256"},{"internalType":"uint256","name":"tokenWeightIn","type":"uint256"},{"internalType":"uint256","name":"tokenBalanceOut","type":"uint256"},{"internalType":"uint256","name":"tokenWeightOut","type":"uint256"},{"internalType":"uint256","name":"tokenAmountOut","type":"uint256"},{"internalType":"uint256","name":"swapFee","type":"uint256"}],"name":"calcInGivenOut","outputs":[{"internalType":"uint256","name":"tokenAmountIn","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenBalanceIn","type":"uint256"},{"internalType":"uint256","name":"tokenWeightIn","type":"uint256"},{"internalType":"uint256","name":"tokenBalanceOut","type":"uint256"},{"internalType":"uint256","name":"tokenWeightOut","type":"uint256"},{"internalType":"uint256","name":"tokenAmountIn","type":"uint256"},{"internalType":"uint256","name":"swapFee","type":"uint256"}],"name":"calcOutGivenIn","outputs":[{"internalType":"uint256","name":"tokenAmountOut","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenBalanceIn","type":"uint256"},{"internalType":"uint256","name":"tokenWeightIn","type":"uint256"},{"internalType":"uint256","name":"tokenBalanceOut","type":"uint256"},{"internalType":"uint256","name":"tokenWeightOut","type":"uint256"},{"internalType":"uint256","name":"swapFee","type":"uint256"}],"name":"calcSpotPrice","outputs":[{"internalType":"uint256","name":"spotPrice","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"name":"commit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"decreaseApproval","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"poolAmountIn","type":"uint256"},{"internalType":"uint256[]","name":"minAmountsOut","type":"uint256[]"}],"name":"exitPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"finalize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"getBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getController","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentTokens","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"getDenormalizedWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFinalTokens","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"getNormalizedWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNumTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"}],"name":"getSpotPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"}],"name":"getSpotPriceSansFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSwapFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalDenormalizedWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"increaseApproval","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"isBound","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isFinalized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"orderHash","type":"bytes32"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"isValidSignature","outputs":[{"internalType":"bytes4","name":"magicValue","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"poolAmountOut","type":"uint256"},{"internalType":"uint256[]","name":"maxAmountsIn","type":"uint256[]"}],"name":"joinPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newController","type":"address"}],"name":"setController","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"swapFee","type":"uint256"}],"name":"setSwapFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"uint256","name":"tokenAmountIn","type":"uint256"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"minAmountOut","type":"uint256"},{"internalType":"uint256","name":"maxPrice","type":"uint256"}],"name":"swapExactAmountIn","outputs":[{"internalType":"uint256","name":"tokenAmountOut","type":"uint256"},{"internalType":"uint256","name":"spotPriceAfter","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"uint256","name":"maxAmountIn","type":"uint256"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"tokenAmountOut","type":"uint256"},{"internalType":"uint256","name":"maxPrice","type":"uint256"}],"name":"swapExactAmountOut","outputs":[{"internalType":"uint256","name":"tokenAmountIn","type":"uint256"},{"internalType":"uint256","name":"spotPriceAfter","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"unbind","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"sellToken","type":"address"},{"internalType":"contract IERC20","name":"buyToken","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"sellAmount","type":"uint256"},{"internalType":"uint256","name":"buyAmount","type":"uint256"},{"internalType":"uint32","name":"validTo","type":"uint32"},{"internalType":"bytes32","name":"appData","type":"bytes32"},{"internalType":"uint256","name":"feeAmount","type":"uint256"},{"internalType":"bytes32","name":"kind","type":"bytes32"},{"internalType":"bool","name":"partiallyFillable","type":"bool"},{"internalType":"bytes32","name":"sellTokenBalance","type":"bytes32"},{"internalType":"bytes32","name":"buyTokenBalance","type":"bytes32"}],"internalType":"struct GPv2Order.Data","name":"order","type":"tuple"}],"name":"verify","outputs":[],"stateMutability":"view","type":"function"}]Contract Creation Code
610120604052348015610010575f80fd5b5060405161440938038061440983398101604081905261002f91610233565b81818181818160036100418382610330565b50600461004e8282610330565b5050600580546001600160a01b03191633908117909155608052506100829150620f42409050670de0b6b3a76400006103ef565b60065550506007805460ff191690556001600160a01b03841660e08190526040805163f698da2560e01b8152905163f698da25916004808201926020929091908290030181865afa1580156100d9573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100fd919061040e565b60c08181525050836001600160a01b0316639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610140573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101649190610425565b6001600160a01b031660a05250506101005250610445565b80516001600160a01b0381168114610192575f80fd5b919050565b634e487b7160e01b5f52604160045260245ffd5b5f82601f8301126101ba575f80fd5b81516001600160401b03808211156101d4576101d4610197565b604051601f8301601f19908116603f011681019082821181831017156101fc576101fc610197565b81604052838152866020858801011115610214575f80fd5b8360208701602083015e5f602085830101528094505050505092915050565b5f805f8060808587031215610246575f80fd5b61024f8561017c565b6020860151604087015191955093506001600160401b0380821115610272575f80fd5b61027e888389016101ab565b93506060870151915080821115610293575f80fd5b506102a0878288016101ab565b91505092959194509250565b600181811c908216806102c057607f821691505b6020821081036102de57634e487b7160e01b5f52602260045260245ffd5b50919050565b601f82111561032b57805f5260205f20601f840160051c810160208510156103095750805b601f840160051c820191505b81811015610328575f8155600101610315565b50505b505050565b81516001600160401b0381111561034957610349610197565b61035d8161035784546102ac565b846102e4565b602080601f831160018114610390575f84156103795750858301515b5f19600386901b1c1916600185901b1785556103e7565b5f85815260208120601f198616915b828110156103be5788860151825594840194600190910190840161039f565b50858210156103db57878501515f19600388901b60f8161c191681555b505060018460011b0185555b505050505050565b5f8261040957634e487b7160e01b5f52601260045260245ffd5b500490565b5f6020828403121561041e575f80fd5b5051919050565b5f60208284031215610435575f80fd5b61043e8261017c565b9392505050565b60805160a05160c05160e05161010051613f5d6104ac5f395f81816105800152610c5601525f818161061a0152612a5101525f818161077e0152610cd601525f81816104820152612e1c01525f81816104d6015281816120ef0152612e760152613f5d5ff3fe608060405234801561000f575f80fd5b506004361061039e575f3560e01c80639381cd2b116101ea578063c36596a611610114578063dd62ed3e116100a9578063f14fcbc811610079578063f14fcbc8146107fa578063f1b8a9b71461080d578063f8b2cb4f14610820578063f8d6aed414610833575f80fd5b8063dd62ed3e146107a0578063e4a28a52146103e3578063e4e1e538146107d8578063ec093021146107eb575f80fd5b8063cf5e7bd3116100e4578063cf5e7bd31461074b578063d4cadf681461075e578063d73dd62314610766578063da08c4dc14610779575f80fd5b8063c36596a61461045b578063c6580d1214610734578063cc77828d1461073b578063cd2ed8fb14610743575f80fd5b8063b02f0b731161018a578063ba9530a61161015a578063ba9530a6146106fc578063bc063e1a1461070f578063bc694ea214610717578063be3bbd2e1461071f575f80fd5b8063b02f0b73146106d1578063b0e0d136146106e4578063b7b800a4146106ec578063ba019dab146106f4575f80fd5b8063981a160b116101c5578063981a160b14610685578063992e2a92146106a3578063a221ee49146106ab578063a9059cbb146106be575f80fd5b80639381cd2b14610662578063948d8ce61461066a57806395d89b411461067d575f80fd5b8063313ce567116102cb57806376c7a3c71161026b5780638b54ab1f1161023b5780638b54ab1f146106155780638d4e40831461063c57806392eefe9b14610647578063936c34771461065a575f80fd5b806376c7a3c7146105ca5780637c5e9ea4146105d25780638201aa3f146105fa578063867378c51461060d575f80fd5b80634f69c0d4116102a65780634f69c0d41461055557806366188463146105685780636dbc88131461057b57806370a08231146105a2575f80fd5b8063313ce5671461052b57806334e199071461053a5780634bb278f31461054d575f80fd5b8063189d00ca1161034157806328bd64431161031157806328bd6443146104bc5780632dd31000146104d15780632f37b624146104f85780633018205f14610523575f80fd5b8063189d00ca14610453578063218b53821461045b57806323b872dd1461046a5780632626f2941461047d575f80fd5b80631446a7ff1161037c5780631446a7ff146103f957806315e84af91461040c5780631626ba7e1461041f57806318160ddd1461044b575f80fd5b806306fdde03146103a2578063095ea7b3146103c057806309a3bbe4146103e3575b5f80fd5b6103aa610846565b6040516103b791906137f9565b60405180910390f35b6103d36103ce36600461384d565b6108d6565b60405190151581526020016103b7565b6103eb6108ef565b6040519081526020016103b7565b6103eb610407366004613877565b610905565b6103eb61041a366004613877565b610aa4565b61043261042d36600461391d565b610c3c565b6040516001600160e01b031990911681526020016103b7565b6002546103eb565b6103eb610d6e565b6103eb670de0b6b3a764000081565b6103d36104783660046139b6565b610d85565b6104a47f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016103b7565b6104cf6104ca366004613a28565b610daa565b005b6104a47f000000000000000000000000000000000000000000000000000000000000000081565b6103d3610506366004613ae4565b6001600160a01b03165f9081526009602052604090205460ff1690565b6104a46110e9565b604051601281526020016103b7565b6104cf610548366004613aff565b611127565b6104cf611272565b6104cf610563366004613b16565b6113ab565b6103d361057636600461384d565b6115f0565b6103eb7f000000000000000000000000000000000000000000000000000000000000000081565b6103eb6105b0366004613ae4565b6001600160a01b03165f9081526020819052604090205490565b6103eb61163f565b6105e56105e0366004613b8e565b611654565b604080519283526020830191909152016103b7565b6105e5610608366004613b8e565b611a09565b6103eb611d8f565b6104a47f000000000000000000000000000000000000000000000000000000000000000081565b60075460ff166103d3565b6104cf610655366004613ae4565b611da6565b6103eb611e8b565b6103eb611ec0565b6103eb610678366004613ae4565b611ed3565b6103aa611f5b565b61068e61012c81565b60405163ffffffff90911681526020016103b7565b6103eb611f6a565b6103eb6106b9366004613bdc565b611f88565b6103d36106cc36600461384d565b611fee565b6104cf6106df366004613b16565b611ffb565b6103eb600881565b6103eb600281565b6103eb600181565b6103eb61070a366004613c13565b612281565b6103eb6122fd565b6103eb612324565b610727612343565b6040516103b79190613c52565b6103eb5f81565b6107276123f2565b6008546103eb565b6104cf610759366004613ae4565b612421565b6103eb61270e565b6103d361077436600461384d565b612743565b6103eb7f000000000000000000000000000000000000000000000000000000000000000081565b6103eb6107ae366004613877565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205490565b6104cf6107e6366004613c9e565b612782565b6103eb6706f05b59d3b2000081565b6104cf610808366004613aff565b612a19565b6103eb61081b366004613ae4565b612a98565b6103eb61082e366004613ae4565b612b27565b6103eb610841366004613c13565b612bf3565b60606003805461085590613cd0565b80601f016020809104026020016040519081016040528092919081815260200182805461088190613cd0565b80156108cc5780601f106108a3576101008083540402835291602001916108cc565b820191905f5260205f20905b8154815290600101906020018083116108af57829003601f168201915b5050505050905090565b5f336108e3818585612c72565b60019150505b92915050565b610902670de0b6b3a76400006032613d1c565b81565b5f5f80516020613f088339815191525c156109335760405163d56a08b560e01b815260040160405180910390fd5b6001600160a01b0383165f9081526009602052604090205460ff1661096b57604051634b16fc2d60e11b815260040160405180910390fd5b6001600160a01b0382165f9081526009602052604090205460ff166109a357604051634b16fc2d60e11b815260040160405180910390fd5b6001600160a01b038381165f8181526009602052604080822093861682529081902090516370a0823160e01b81523060048201529091610a9b916370a0823190602401602060405180830381865afa158015610a01573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a259190613d33565b60028401546040516370a0823160e01b81523060048201526001600160a01b038816906370a0823190602401602060405180830381865afa158015610a6c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a909190613d33565b84600201545f611f88565b95945050505050565b5f5f80516020613f088339815191525c15610ad25760405163d56a08b560e01b815260040160405180910390fd5b6001600160a01b0383165f9081526009602052604090205460ff16610b0a57604051634b16fc2d60e11b815260040160405180910390fd5b6001600160a01b0382165f9081526009602052604090205460ff16610b4257604051634b16fc2d60e11b815260040160405180910390fd5b6001600160a01b038381165f8181526009602052604080822093861682529081902090516370a0823160e01b81523060048201529091610a9b916370a0823190602401602060405180830381865afa158015610ba0573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bc49190613d33565b60028401546040516370a0823160e01b81523060048201526001600160a01b038816906370a0823190602401602060405180830381865afa158015610c0b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c2f9190613d33565b8460020154600654611f88565b5f8082806020019051810190610c529190613d6b565b90507f00000000000000000000000000000000000000000000000000000000000000008160c0015114610c9857604051630e1a1b6360e41b815260040160405180910390fd5b601f19810180517fd5a25ba2e97094ad7d83dc28a6572da797d6b3e7fc6663bd93efb789fc17e48982526101a08220915260405161190160f01b81527f00000000000000000000000000000000000000000000000000000000000000006002820152602281019190915260429020848114610d265760405163593fcacd60e01b815260040160405180910390fd5b5f80516020613f088339815191525c8114610d545760405163dafbdd1f60e01b815260040160405180910390fd5b610d5d82610daa565b50630b135d3f60e11b949350505050565b6109026402540be400670de0b6b3a7640000613e3b565b5f33610d92858285612c7f565b610d9d858585612cff565b60019150505b9392505050565b6020808201516001600160a01b039081165f90815260098084526040808320815160608082018452825460ff90811615158352600180850154848b0152600294850154848701528a519098168752948852948390208351958601845280549094161515855294830154958401959095529301549281019290925280519091901580610e3457508051155b15610e5257604051634b16fc2d60e11b815260040160405180910390fd5b60408301516001600160a01b031615610e7d57604051623c9da560e61b815260040160405180910390fd5b610e8961012c42613e5a565b8360a0015163ffffffff161115610eb35760405163326389f960e11b815260040160405180910390fd5b60e083015115610ed557604051620e5bdf60e41b815260040160405180910390fd5b7ff3b277728b3fee749481eb3e0b3b48980dbbab78658fc419025cb16eee34677583610100015114610f1a57604051632c9634af60e01b815260040160405180910390fd5b7f5a28e9363bb942b639270062aa6bb295f434bcdfc42c97267bf003f272060dc9836101600151141580610f7357507f5a28e9363bb942b639270062aa6bb295f434bcdfc42c97267bf003f272060dc983610140015114155b15610f91576040516397a2328160e01b815260040160405180910390fd5b60208301516040516370a0823160e01b81523060048201525f916001600160a01b0316906370a0823190602401602060405180830381865afa158015610fd9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ffd9190613d33565b9050611011816706f05b59d3b20000612d5c565b846080015111156110355760405163558fcd9160e11b815260040160405180910390fd5b604080840151855191516370a0823160e01b81523060048201525f926110bb92859290916001600160a01b0316906370a0823190602401602060405180830381865afa158015611087573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110ab9190613d33565b866040015189608001515f612281565b905084606001518110156110e25760405163d6ac339560e01b815260040160405180910390fd5b5050505050565b5f5f80516020613f088339815191525c156111175760405163d56a08b560e01b815260040160405180910390fd5b506005546001600160a01b031690565b336001600160a01b03165f356001600160e01b0319166001600160e01b0319165f36604051611157929190613e6d565b60405180910390a25f80516020613f088339815191525c1561118c5760405163d56a08b560e01b815260040160405180910390fd5b6111966001612ddf565b6005546001600160a01b031633146111c157604051634f0f549960e11b815260040160405180910390fd5b60075460ff16156111e55760405163056f633d60e21b815260040160405180910390fd5b6111fa620f4240670de0b6b3a7640000613e3b565b81101561121a57604051633b46575d60e01b815260040160405180910390fd5b61122f620f4240670de0b6b3a7640000613e3b565b61124190670de0b6b3a7640000613e9b565b81111561126157604051630f71fbbf60e11b815260040160405180910390fd5b600681905561126f5f612ddf565b50565b336001600160a01b03165f356001600160e01b0319166001600160e01b0319165f366040516112a2929190613e6d565b60405180910390a25f80516020613f088339815191525c156112d75760405163d56a08b560e01b815260040160405180910390fd5b6112e16001612ddf565b6005546001600160a01b0316331461130c57604051634f0f549960e11b815260040160405180910390fd5b60075460ff16156113305760405163056f633d60e21b815260040160405180910390fd5b600854600211156113545760405163af785ec560e01b815260040160405180910390fd5b6007805460ff1916600117905561137c611377670de0b6b3a76400006064613d1c565b612df2565b61139833611393670de0b6b3a76400006064613d1c565b612dfc565b6113a0612e0a565b6113a95f612ddf565b565b336001600160a01b03165f356001600160e01b0319166001600160e01b0319165f366040516113db929190613e6d565b60405180910390a25f80516020613f088339815191525c156114105760405163d56a08b560e01b815260040160405180910390fd5b61141a6001612ddf565b60075460ff1661143d57604051632e41ba2d60e01b815260040160405180910390fd5b5f61144760025490565b90505f6114548583612f0e565b9050805f0361147657604051630c499f4760e01b815260040160405180910390fd5b6008545f5b818110156115c9575f6008828154811061149757611497613eae565b5f9182526020822001546040516370a0823160e01b81523060048201526001600160a01b03909116925082906370a0823190602401602060405180830381865afa1580156114e7573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061150b9190613d33565b90505f6115188683612d5c565b9050805f0361153a57604051635b00df6960e11b815260040160405180910390fd5b88888581811061154c5761154c613eae565b9050602002013581111561157357604051630451d9ed60e31b815260040160405180910390fd5b6040518181526001600160a01b0384169033907f63982df10efd8dfaaaa0fcc7f50b2d93b7cba26ccc48adee2873220d485dc39a9060200160405180910390a36115be833383612fb6565b50505060010161147b565b506115d386612df2565b6115dd3387612dfc565b5050506115eb5f801b612ddf565b505050565b335f9081526001602090815260408083206001600160a01b03861684529091528120548083111561162b5761162633855f612c72565b6108e3565b6108e3338561163a8685613e9b565b612c72565b610902620f4240670de0b6b3a7640000613e3b565b6040515f90819033906001600160e01b0319833516906116779084903690613e6d565b60405180910390a25f80516020613f088339815191525c156116ac5760405163d56a08b560e01b815260040160405180910390fd5b6116b66001612ddf565b60075460ff166116d957604051632e41ba2d60e01b815260040160405180910390fd5b6001600160a01b0387165f9081526009602052604090205460ff1661171157604051634b16fc2d60e11b815260040160405180910390fd5b6001600160a01b0385165f9081526009602052604090205460ff1661174957604051634b16fc2d60e11b815260040160405180910390fd5b6001600160a01b038781165f81815260096020526040808220938916825280822090516370a0823160e01b81523060048201529092906370a0823190602401602060405180830381865afa1580156117a3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117c79190613d33565b6040516370a0823160e01b81523060048201529091505f906001600160a01b038a16906370a0823190602401602060405180830381865afa15801561180e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118329190613d33565b905061185b8161184b6003670de0b6b3a7640000613e3b565b611856906001613e5a565b612d5c565b88111561187b5760405163dad25d8560e01b815260040160405180910390fd5b5f611893838660020154848760020154600654611f88565b9050878111156118b65760405163823a9c3760e01b815260040160405180910390fd5b6118ce8386600201548487600201548d600654612bf3565b96508a8711156118f157604051630451d9ed60e31b815260040160405180910390fd5b6118fb8388612fcb565b9250611907828a612ff0565b9150611920838660020154848760020154600654611f88565b95508086101561194357604051636212302360e01b815260040160405180910390fd5b878611156119645760405163823a9c3760e01b815260040160405180910390fd5b61196e878a612f0e565b81111561198e576040516337fb98f960e11b815260040160405180910390fd5b60408051888152602081018b90526001600160a01b03808d1692908f169133917f908fb5ee8f16c6bc9bc3690973819f32a4d4b10188134543c88706e0e1d43378910160405180910390a46119e48c3389612fb6565b6119ef8a338b613028565b50505050506119ff5f801b612ddf565b9550959350505050565b6040515f90819033906001600160e01b031983351690611a2c9084903690613e6d565b60405180910390a25f80516020613f088339815191525c15611a615760405163d56a08b560e01b815260040160405180910390fd5b611a6b6001612ddf565b60075460ff16611a8e57604051632e41ba2d60e01b815260040160405180910390fd5b6001600160a01b0387165f9081526009602052604090205460ff16611ac657604051634b16fc2d60e11b815260040160405180910390fd5b6001600160a01b0385165f9081526009602052604090205460ff16611afe57604051634b16fc2d60e11b815260040160405180910390fd5b6001600160a01b038781165f81815260096020526040808220938916825280822090516370a0823160e01b81523060048201529092906370a0823190602401602060405180830381865afa158015611b58573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b7c9190613d33565b6040516370a0823160e01b81523060048201529091505f906001600160a01b038a16906370a0823190602401602060405180830381865afa158015611bc3573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611be79190613d33565b9050611bfb826706f05b59d3b20000612d5c565b8a1115611c1b5760405163558fcd9160e11b815260040160405180910390fd5b5f611c33838660020154848760020154600654611f88565b905087811115611c565760405163823a9c3760e01b815260040160405180910390fd5b611c6e8386600201548487600201548f600654612281565b965088871015611c915760405163d6ac339560e01b815260040160405180910390fd5b611c9b838c612fcb565b9250611ca78288612ff0565b9150611cc0838660020154848760020154600654611f88565b955080861015611ce357604051636212302360e01b815260040160405180910390fd5b87861115611d045760405163823a9c3760e01b815260040160405180910390fd5b611d0e8b88612f0e565b811115611d2e576040516337fb98f960e11b815260040160405180910390fd5b604080518c8152602081018990526001600160a01b03808d1692908f169133917f908fb5ee8f16c6bc9bc3690973819f32a4d4b10188134543c88706e0e1d43378910160405180910390a4611d848c338d612fb6565b6119ef8a3389613028565b61090264e8d4a51000670de0b6b3a7640000613e3b565b336001600160a01b03165f356001600160e01b0319166001600160e01b0319165f36604051611dd6929190613e6d565b60405180910390a25f80516020613f088339815191525c15611e0b5760405163d56a08b560e01b815260040160405180910390fd5b611e156001612ddf565b6005546001600160a01b03163314611e4057604051634f0f549960e11b815260040160405180910390fd5b6001600160a01b038116611e67576040516351a9e5c560e01b815260040160405180910390fd5b600580546001600160a01b0319166001600160a01b03831617905561126f5f612ddf565b5f5f80516020613f088339815191525c15611eb95760405163d56a08b560e01b815260040160405180910390fd5b50600a5490565b610902670de0b6b3a76400006064613d1c565b5f5f80516020613f088339815191525c15611f015760405163d56a08b560e01b815260040160405180910390fd5b6001600160a01b0382165f9081526009602052604090205460ff16611f3957604051634b16fc2d60e11b815260040160405180910390fd5b506001600160a01b0381165f908152600960205260409020600201545b919050565b60606004805461085590613cd0565b611f7d6003670de0b6b3a7640000613e3b565b610902906001613e5a565b5f80611f948787612f0e565b90505f611fa18686612f0e565b90505f611fae8383612f0e565b90505f611fd4670de0b6b3a7640000611fcf670de0b6b3a764000089612ff0565b612f0e565b9050611fe08282612d5c565b9a9950505050505050505050565b5f336108e3818585612cff565b336001600160a01b03165f356001600160e01b0319166001600160e01b0319165f3660405161202b929190613e6d565b60405180910390a25f80516020613f088339815191525c156120605760405163d56a08b560e01b815260040160405180910390fd5b61206a6001612ddf565b60075460ff1661208d57604051632e41ba2d60e01b815260040160405180910390fd5b5f61209760025490565b90505f6120a4855f612d5c565b90505f6120b18683612ff0565b90505f6120be8285612f0e565b9050805f036120e057604051630c499f4760e01b815260040160405180910390fd5b6120ea338861303c565b6121147f000000000000000000000000000000000000000000000000000000000000000084612dfc565b61211d82613046565b6008545f5b81811015612270575f6008828154811061213e5761213e613eae565b5f9182526020822001546040516370a0823160e01b81523060048201526001600160a01b03909116925082906370a0823190602401602060405180830381865afa15801561218e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121b29190613d33565b90505f6121bf8683612d5c565b9050805f036121e157604051634b4ae51b60e11b815260040160405180910390fd5b8a8a858181106121f3576121f3613eae565b9050602002013581101561221a5760405163341a1f3360e11b815260040160405180910390fd5b6040518181526001600160a01b0384169033907fe74c91552b64c2e2e7bd255639e004e693bd3e1d01cc33e65610b86afcc1ffed9060200160405180910390a3612265833383613028565b505050600101612122565b5050505050506115eb5f801b612ddf565b5f8061228d8786612f0e565b90505f6122a2670de0b6b3a764000085612ff0565b90506122ae8582612d5c565b90505f6122bf8a611fcf8c85612fcb565b90505f6122cc8285613050565b90505f6122e1670de0b6b3a764000083612ff0565b90506122ed8a82612d5c565b9c9b505050505050505050505050565b612312620f4240670de0b6b3a7640000613e3b565b61090290670de0b6b3a7640000613e9b565b6001612339670de0b6b3a76400006002613d1c565b6109029190613e9b565b60605f80516020613f088339815191525c156123725760405163d56a08b560e01b815260040160405180910390fd5b60075460ff1661239557604051632e41ba2d60e01b815260040160405180910390fd5b60088054806020026020016040519081016040528092919081815260200182805480156108cc57602002820191905f5260205f20905b81546001600160a01b031681526001909101906020018083116123cb575050505050905090565b60605f80516020613f088339815191525c156123955760405163d56a08b560e01b815260040160405180910390fd5b336001600160a01b03165f356001600160e01b0319166001600160e01b0319165f36604051612451929190613e6d565b60405180910390a25f80516020613f088339815191525c156124865760405163d56a08b560e01b815260040160405180910390fd5b6124906001612ddf565b6005546001600160a01b031633146124bb57604051634f0f549960e11b815260040160405180910390fd5b60075460ff16156124df5760405163056f633d60e21b815260040160405180910390fd5b6001600160a01b0381165f9081526009602052604090205460ff1661251757604051634b16fc2d60e11b815260040160405180910390fd5b600a546001600160a01b0382165f9081526009602052604090206002015461253f9190612ff0565b600a556001600160a01b0381165f90815260096020526040812060019081015460085490929161256e91613e9b565b90506008818154811061258357612583613eae565b5f91825260209091200154600880546001600160a01b0390921691849081106125ae576125ae613eae565b905f5260205f20015f6101000a8154816001600160a01b0302191690836001600160a01b031602179055508160095f600885815481106125f0576125f0613eae565b5f9182526020808320909101546001600160a01b03168352820192909252604001902060010155600880548061262857612628613ec2565b5f82815260208082205f19908401810180546001600160a01b0319169055909201909255604080516060810182528381528083018481528183018581526001600160a01b0389168087526009909552948390209151825460ff1916901515178255516001820155925160029093019290925590516370a0823160e01b81523060048201526127029185913391906370a0823190602401602060405180830381865afa1580156126d9573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126fd9190613d33565b613028565b5061126f90505f612ddf565b5f5f80516020613f088339815191525c1561273c5760405163d56a08b560e01b815260040160405180910390fd5b5060065490565b335f8181526001602090815260408083206001600160a01b0387168452909152812054909161277991859061163a908690613e5a565b50600192915050565b336001600160a01b03165f356001600160e01b0319166001600160e01b0319165f366040516127b2929190613e6d565b60405180910390a25f80516020613f088339815191525c156127e75760405163d56a08b560e01b815260040160405180910390fd5b6127f16001612ddf565b6005546001600160a01b0316331461281c57604051634f0f549960e11b815260040160405180910390fd5b60075460ff16156128405760405163056f633d60e21b815260040160405180910390fd5b6001600160a01b0383165f9081526009602052604090205460ff161561287957604051636b1ed1b760e11b815260040160405180910390fd5b600880541061289b5760405163c47f9e9360e01b815260040160405180910390fd5b670de0b6b3a76400008110156128c4576040516342eb024360e01b815260040160405180910390fd5b6128d7670de0b6b3a76400006032613d1c565b8111156128f757604051630cbe784360e11b815260040160405180910390fd5b61290e64e8d4a51000670de0b6b3a7640000613e3b565b82101561292e57604051638968448b60e01b815260040160405180910390fd5b61293a600a5482612fcb565b600a55612950670de0b6b3a76400006032613d1c565b600a541115612972576040516342f71f0b60e01b815260040160405180910390fd5b6040805160608101825260018082526008805460208085019182528486018781526001600160a01b038a165f81815260099093529682209551865460ff19169015151786559151858501559051600290940193909355805491820181559091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30180546001600160a01b0319169091179055612a10833384612fb6565b6115eb5f612ddf565b5f80516020613f088339815191525c15612a465760405163d56a08b560e01b815260040160405180910390fd5b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614612a8f5760405163bf84897760e01b815260040160405180910390fd5b61126f81612ddf565b5f5f80516020613f088339815191525c15612ac65760405163d56a08b560e01b815260040160405180910390fd5b6001600160a01b0382165f9081526009602052604090205460ff16612afe57604051634b16fc2d60e11b815260040160405180910390fd5b6001600160a01b0382165f90815260096020526040902060020154600a54610da3908290612f0e565b5f5f80516020613f088339815191525c15612b555760405163d56a08b560e01b815260040160405180910390fd5b6001600160a01b0382165f9081526009602052604090205460ff16612b8d57604051634b16fc2d60e11b815260040160405180910390fd5b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015612bcf573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108e99190613d33565b5f80612bff8588612f0e565b90505f612c0c8786612ff0565b90505f612c198883612f0e565b90505f612c268285613050565b9050612c3a81670de0b6b3a7640000612ff0565b9050612c4e670de0b6b3a764000087612ff0565b9450612c63612c5d8c83612d5c565b86612f0e565b9b9a5050505050505050505050565b6115eb8383836001613105565b6001600160a01b038381165f908152600160209081526040808320938616835292905220545f198114612cf95781811015612ceb57604051637dc7a0d960e11b81526001600160a01b038416600482015260248101829052604481018390526064015b60405180910390fd5b612cf984848484035f613105565b50505050565b6001600160a01b038316612d2857604051634b637e8f60e11b81525f6004820152602401612ce2565b6001600160a01b038216612d515760405163ec442f0560e01b81525f6004820152602401612ce2565b6115eb8383836131d7565b5f8282028315801590612d7e575082848281612d7a57612d7a613e27565b0414155b15612d9c5760405163202e377f60e01b815260040160405180910390fd5b6706f05b59d3b20000810181811015612dc85760405163202e377f60e01b815260040160405180910390fd5b5f670de0b6b3a7640000825b049695505050505050565b805f80516020613f088339815191525d50565b61126f30826132fd565b612e068282613331565b5050565b6008545f5b81811015612e7357612e6b7f00000000000000000000000000000000000000000000000000000000000000005f1960088481548110612e5057612e50613eae565b5f918252602090912001546001600160a01b0316919061333c565b600101612e0f565b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166352b8cb636040518163ffffffff1660e01b81526004015f604051808303815f87803b158015612ecc575f80fd5b505af1925050508015612edd575060015b61126f5760405130907f0d03834d0d86c7f57e877af40e26f176dc31bd637535d4ba153d1ac9de88a7ea905f90a250565b5f815f03612f2f5760405163abcf2e7560e01b815260040160405180910390fd5b670de0b6b3a764000083028315801590612f605750670de0b6b3a7640000848281612f5c57612f5c613e27565b0414155b15612f7e576040516394fb03d760e01b815260040160405180910390fd5b600183901c810181811015612fa6576040516394fb03d760e01b815260040160405180910390fd5b5f848281612dd457612dd4613e27565b6115eb6001600160a01b0384168330846133f9565b5f82820183811015610da35760405163e468448f60e01b815260040160405180910390fd5b5f805f612ffd8585613432565b91509150801561302057604051630a5c778b60e31b815260040160405180910390fd5b509392505050565b6115eb6001600160a01b0384168383613455565b612e068282613486565b61126f3082613491565b5f600183101561307357604051635567969f60e11b815260040160405180910390fd5b671bc16d674ec7ffff83111561309c57604051638554775f60e01b815260040160405180910390fd5b670de0b6b3a7640000808304025f6130b48483612ff0565b90505f6130cb86670de0b6b3a764000085046134c5565b9050815f036130de5792506108e9915050565b5f6130ee87846305f5e10061351d565b90506130fa8282612d5c565b979650505050505050565b6001600160a01b03841661312e5760405163e602df0560e01b81525f6004820152602401612ce2565b6001600160a01b03831661315757604051634a1406b160e11b81525f6004820152602401612ce2565b6001600160a01b038085165f9081526001602090815260408083209387168352929052208290558015612cf957826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516131c991815260200190565b60405180910390a350505050565b6001600160a01b038316613201578060025f8282546131f69190613e5a565b909155506132719050565b6001600160a01b0383165f90815260208190526040902054818110156132535760405163391434e360e21b81526001600160a01b03851660048201526024810182905260448101839052606401612ce2565b6001600160a01b0384165f9081526020819052604090209082900390555b6001600160a01b03821661328d576002805482900390556132ab565b6001600160a01b0382165f9081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516132f091815260200190565b60405180910390a3505050565b6001600160a01b0382166133265760405163ec442f0560e01b81525f6004820152602401612ce2565b612e065f83836131d7565b612e06308383612cff565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b17905261338d84826135f9565b612cf9576040516001600160a01b0384811660248301525f60448301526133ef91869182169063095ea7b3906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050613696565b612cf98482613696565b6040516001600160a01b038481166024830152838116604483015260648201839052612cf99186918216906323b872dd906084016133bd565b5f808284106134465750508082035f61344e565b505081810360015b9250929050565b6040516001600160a01b038381166024830152604482018390526115eb91859182169063a9059cbb906064016133bd565b612e06823083612cff565b6001600160a01b0382166134ba57604051634b637e8f60e11b81525f6004820152602401612ce2565b612e06825f836131d7565b5f80600283065f036134df57670de0b6b3a76400006134e1565b835b90506002830492505b8215610da3576134fa8485612d5c565b935060028306156135125761350f8185612d5c565b90505b6002830492506134ea565b5f82818061353387670de0b6b3a7640000613432565b9092509050670de0b6b3a7640000805f60015b8884106135ea575f670de0b6b3a7640000820290505f806135788a61357385670de0b6b3a7640000612ff0565b613432565b9150915061358a87611856848c612d5c565b96506135968784612f0e565b9650865f036135a7575050506135ea565b87156135b1579315935b80156135bb579315935b84156135d2576135cb8688612ff0565b95506135df565b6135dc8688612fcb565b95505b505050600101613546565b50909998505050505050505050565b5f805f846001600160a01b0316846040516136149190613ed6565b5f604051808303815f865af19150503d805f811461364d576040519150601f19603f3d011682016040523d82523d5f602084013e613652565b606091505b509150915081801561367c57508051158061367c57508080602001905181019061367c9190613eec565b8015610a9b5750505050506001600160a01b03163b151590565b5f6136aa6001600160a01b038416836136f7565b905080515f141580156136ce5750808060200190518101906136cc9190613eec565b155b156115eb57604051635274afe760e01b81526001600160a01b0384166004820152602401612ce2565b6060610da383835f845f80856001600160a01b0316848660405161371b9190613ed6565b5f6040518083038185875af1925050503d805f8114613755576040519150601f19603f3d011682016040523d82523d5f602084013e61375a565b606091505b509150915061376a868383613774565b9695505050505050565b60608261378957613784826137d0565b610da3565b81511580156137a057506001600160a01b0384163b155b156137c957604051639996b31560e01b81526001600160a01b0385166004820152602401612ce2565b5080610da3565b8051156137e05780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b6001600160a01b038116811461126f575f80fd5b8035611f568161382e565b5f806040838503121561385e575f80fd5b82356138698161382e565b946020939093013593505050565b5f8060408385031215613888575f80fd5b82356138938161382e565b915060208301356138a38161382e565b809150509250929050565b634e487b7160e01b5f52604160045260245ffd5b604051610180810167ffffffffffffffff811182821017156138e6576138e66138ae565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715613915576139156138ae565b604052919050565b5f806040838503121561392e575f80fd5b8235915060208084013567ffffffffffffffff8082111561394d575f80fd5b818601915086601f830112613960575f80fd5b813581811115613972576139726138ae565b613984601f8201601f191685016138ec565b91508082528784828501011115613999575f80fd5b80848401858401375f848284010152508093505050509250929050565b5f805f606084860312156139c8575f80fd5b83356139d38161382e565b925060208401356139e38161382e565b929592945050506040919091013590565b63ffffffff8116811461126f575f80fd5b8035611f56816139f4565b801515811461126f575f80fd5b8035611f5681613a10565b5f6101808284031215613a39575f80fd5b613a416138c2565b613a4a83613842565b8152613a5860208401613842565b6020820152613a6960408401613842565b60408201526060830135606082015260808301356080820152613a8e60a08401613a05565b60a082015260c083013560c082015260e083013560e0820152610100808401358183015250610120613ac1818501613a1d565b908201526101408381013590820152610160928301359281019290925250919050565b5f60208284031215613af4575f80fd5b8135610da38161382e565b5f60208284031215613b0f575f80fd5b5035919050565b5f805f60408486031215613b28575f80fd5b83359250602084013567ffffffffffffffff80821115613b46575f80fd5b818601915086601f830112613b59575f80fd5b813581811115613b67575f80fd5b8760208260051b8501011115613b7b575f80fd5b6020830194508093505050509250925092565b5f805f805f60a08688031215613ba2575f80fd5b8535613bad8161382e565b9450602086013593506040860135613bc48161382e565b94979396509394606081013594506080013592915050565b5f805f805f60a08688031215613bf0575f80fd5b505083359560208501359550604085013594606081013594506080013592509050565b5f805f805f8060c08789031215613c28575f80fd5b505084359660208601359650604086013595606081013595506080810135945060a0013592509050565b602080825282518282018190525f9190848201906040850190845b81811015613c925783516001600160a01b031683529284019291840191600101613c6d565b50909695505050505050565b5f805f60608486031215613cb0575f80fd5b8335613cbb8161382e565b95602085013595506040909401359392505050565b600181811c90821680613ce457607f821691505b602082108103613d0257634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52601160045260245ffd5b80820281158282048414176108e9576108e9613d08565b5f60208284031215613d43575f80fd5b5051919050565b8051611f568161382e565b8051611f56816139f4565b8051611f5681613a10565b5f6101808284031215613d7c575f80fd5b613d846138c2565b613d8d83613d4a565b8152613d9b60208401613d4a565b6020820152613dac60408401613d4a565b60408201526060830151606082015260808301516080820152613dd160a08401613d55565b60a082015260c083015160c082015260e083015160e0820152610100808401518183015250610120613e04818501613d60565b908201526101408381015190820152610160928301519281019290925250919050565b634e487b7160e01b5f52601260045260245ffd5b5f82613e5557634e487b7160e01b5f52601260045260245ffd5b500490565b808201808211156108e9576108e9613d08565b60208152816020820152818360408301375f818301604090810191909152601f909201601f19160101919050565b818103818111156108e9576108e9613d08565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52603160045260245ffd5b5f82518060208501845e5f920191825250919050565b5f60208284031215613efc575f80fd5b8151610da381613a1056fe3f8f4c536ce1b925b469af1b09a44da237dab5bbc584585648c12be1ca25a8c4a26469706673582212203618b9f7655c1be46da20cd07ebac82e300887c0c44726db647af911fa07e50c64736f6c634300081900330000000000000000000000009008d19f58aabd9ed0d60971565aa8510560ab41362e5182440b52aa8fffe70a251550fbbcbca424740fe5a14f59bf0c1b06fe1d000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000001f42616c616e63657220436f5720414d4d20353020415242203530205745544800000000000000000000000000000000000000000000000000000000000000001142436f572d35304152422d353057455448000000000000000000000000000000
Deployed Bytecode
0x608060405234801561000f575f80fd5b506004361061039e575f3560e01c80639381cd2b116101ea578063c36596a611610114578063dd62ed3e116100a9578063f14fcbc811610079578063f14fcbc8146107fa578063f1b8a9b71461080d578063f8b2cb4f14610820578063f8d6aed414610833575f80fd5b8063dd62ed3e146107a0578063e4a28a52146103e3578063e4e1e538146107d8578063ec093021146107eb575f80fd5b8063cf5e7bd3116100e4578063cf5e7bd31461074b578063d4cadf681461075e578063d73dd62314610766578063da08c4dc14610779575f80fd5b8063c36596a61461045b578063c6580d1214610734578063cc77828d1461073b578063cd2ed8fb14610743575f80fd5b8063b02f0b731161018a578063ba9530a61161015a578063ba9530a6146106fc578063bc063e1a1461070f578063bc694ea214610717578063be3bbd2e1461071f575f80fd5b8063b02f0b73146106d1578063b0e0d136146106e4578063b7b800a4146106ec578063ba019dab146106f4575f80fd5b8063981a160b116101c5578063981a160b14610685578063992e2a92146106a3578063a221ee49146106ab578063a9059cbb146106be575f80fd5b80639381cd2b14610662578063948d8ce61461066a57806395d89b411461067d575f80fd5b8063313ce567116102cb57806376c7a3c71161026b5780638b54ab1f1161023b5780638b54ab1f146106155780638d4e40831461063c57806392eefe9b14610647578063936c34771461065a575f80fd5b806376c7a3c7146105ca5780637c5e9ea4146105d25780638201aa3f146105fa578063867378c51461060d575f80fd5b80634f69c0d4116102a65780634f69c0d41461055557806366188463146105685780636dbc88131461057b57806370a08231146105a2575f80fd5b8063313ce5671461052b57806334e199071461053a5780634bb278f31461054d575f80fd5b8063189d00ca1161034157806328bd64431161031157806328bd6443146104bc5780632dd31000146104d15780632f37b624146104f85780633018205f14610523575f80fd5b8063189d00ca14610453578063218b53821461045b57806323b872dd1461046a5780632626f2941461047d575f80fd5b80631446a7ff1161037c5780631446a7ff146103f957806315e84af91461040c5780631626ba7e1461041f57806318160ddd1461044b575f80fd5b806306fdde03146103a2578063095ea7b3146103c057806309a3bbe4146103e3575b5f80fd5b6103aa610846565b6040516103b791906137f9565b60405180910390f35b6103d36103ce36600461384d565b6108d6565b60405190151581526020016103b7565b6103eb6108ef565b6040519081526020016103b7565b6103eb610407366004613877565b610905565b6103eb61041a366004613877565b610aa4565b61043261042d36600461391d565b610c3c565b6040516001600160e01b031990911681526020016103b7565b6002546103eb565b6103eb610d6e565b6103eb670de0b6b3a764000081565b6103d36104783660046139b6565b610d85565b6104a47f000000000000000000000000c92e8bdf79f0507f65a392b0ab4667716bfe011081565b6040516001600160a01b0390911681526020016103b7565b6104cf6104ca366004613a28565b610daa565b005b6104a47f000000000000000000000000e0e2ba143ee5268da87d529949a252111598730281565b6103d3610506366004613ae4565b6001600160a01b03165f9081526009602052604090205460ff1690565b6104a46110e9565b604051601281526020016103b7565b6104cf610548366004613aff565b611127565b6104cf611272565b6104cf610563366004613b16565b6113ab565b6103d361057636600461384d565b6115f0565b6103eb7f362e5182440b52aa8fffe70a251550fbbcbca424740fe5a14f59bf0c1b06fe1d81565b6103eb6105b0366004613ae4565b6001600160a01b03165f9081526020819052604090205490565b6103eb61163f565b6105e56105e0366004613b8e565b611654565b604080519283526020830191909152016103b7565b6105e5610608366004613b8e565b611a09565b6103eb611d8f565b6104a47f0000000000000000000000009008d19f58aabd9ed0d60971565aa8510560ab4181565b60075460ff166103d3565b6104cf610655366004613ae4565b611da6565b6103eb611e8b565b6103eb611ec0565b6103eb610678366004613ae4565b611ed3565b6103aa611f5b565b61068e61012c81565b60405163ffffffff90911681526020016103b7565b6103eb611f6a565b6103eb6106b9366004613bdc565b611f88565b6103d36106cc36600461384d565b611fee565b6104cf6106df366004613b16565b611ffb565b6103eb600881565b6103eb600281565b6103eb600181565b6103eb61070a366004613c13565b612281565b6103eb6122fd565b6103eb612324565b610727612343565b6040516103b79190613c52565b6103eb5f81565b6107276123f2565b6008546103eb565b6104cf610759366004613ae4565b612421565b6103eb61270e565b6103d361077436600461384d565b612743565b6103eb7f69d78e7a7cafcaf924483f99f65e8f4e303a99a446db7ab319f9d40e940bced281565b6103eb6107ae366004613877565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205490565b6104cf6107e6366004613c9e565b612782565b6103eb6706f05b59d3b2000081565b6104cf610808366004613aff565b612a19565b6103eb61081b366004613ae4565b612a98565b6103eb61082e366004613ae4565b612b27565b6103eb610841366004613c13565b612bf3565b60606003805461085590613cd0565b80601f016020809104026020016040519081016040528092919081815260200182805461088190613cd0565b80156108cc5780601f106108a3576101008083540402835291602001916108cc565b820191905f5260205f20905b8154815290600101906020018083116108af57829003601f168201915b5050505050905090565b5f336108e3818585612c72565b60019150505b92915050565b610902670de0b6b3a76400006032613d1c565b81565b5f5f80516020613f088339815191525c156109335760405163d56a08b560e01b815260040160405180910390fd5b6001600160a01b0383165f9081526009602052604090205460ff1661096b57604051634b16fc2d60e11b815260040160405180910390fd5b6001600160a01b0382165f9081526009602052604090205460ff166109a357604051634b16fc2d60e11b815260040160405180910390fd5b6001600160a01b038381165f8181526009602052604080822093861682529081902090516370a0823160e01b81523060048201529091610a9b916370a0823190602401602060405180830381865afa158015610a01573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a259190613d33565b60028401546040516370a0823160e01b81523060048201526001600160a01b038816906370a0823190602401602060405180830381865afa158015610a6c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a909190613d33565b84600201545f611f88565b95945050505050565b5f5f80516020613f088339815191525c15610ad25760405163d56a08b560e01b815260040160405180910390fd5b6001600160a01b0383165f9081526009602052604090205460ff16610b0a57604051634b16fc2d60e11b815260040160405180910390fd5b6001600160a01b0382165f9081526009602052604090205460ff16610b4257604051634b16fc2d60e11b815260040160405180910390fd5b6001600160a01b038381165f8181526009602052604080822093861682529081902090516370a0823160e01b81523060048201529091610a9b916370a0823190602401602060405180830381865afa158015610ba0573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bc49190613d33565b60028401546040516370a0823160e01b81523060048201526001600160a01b038816906370a0823190602401602060405180830381865afa158015610c0b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c2f9190613d33565b8460020154600654611f88565b5f8082806020019051810190610c529190613d6b565b90507f362e5182440b52aa8fffe70a251550fbbcbca424740fe5a14f59bf0c1b06fe1d8160c0015114610c9857604051630e1a1b6360e41b815260040160405180910390fd5b601f19810180517fd5a25ba2e97094ad7d83dc28a6572da797d6b3e7fc6663bd93efb789fc17e48982526101a08220915260405161190160f01b81527f69d78e7a7cafcaf924483f99f65e8f4e303a99a446db7ab319f9d40e940bced26002820152602281019190915260429020848114610d265760405163593fcacd60e01b815260040160405180910390fd5b5f80516020613f088339815191525c8114610d545760405163dafbdd1f60e01b815260040160405180910390fd5b610d5d82610daa565b50630b135d3f60e11b949350505050565b6109026402540be400670de0b6b3a7640000613e3b565b5f33610d92858285612c7f565b610d9d858585612cff565b60019150505b9392505050565b6020808201516001600160a01b039081165f90815260098084526040808320815160608082018452825460ff90811615158352600180850154848b0152600294850154848701528a519098168752948852948390208351958601845280549094161515855294830154958401959095529301549281019290925280519091901580610e3457508051155b15610e5257604051634b16fc2d60e11b815260040160405180910390fd5b60408301516001600160a01b031615610e7d57604051623c9da560e61b815260040160405180910390fd5b610e8961012c42613e5a565b8360a0015163ffffffff161115610eb35760405163326389f960e11b815260040160405180910390fd5b60e083015115610ed557604051620e5bdf60e41b815260040160405180910390fd5b7ff3b277728b3fee749481eb3e0b3b48980dbbab78658fc419025cb16eee34677583610100015114610f1a57604051632c9634af60e01b815260040160405180910390fd5b7f5a28e9363bb942b639270062aa6bb295f434bcdfc42c97267bf003f272060dc9836101600151141580610f7357507f5a28e9363bb942b639270062aa6bb295f434bcdfc42c97267bf003f272060dc983610140015114155b15610f91576040516397a2328160e01b815260040160405180910390fd5b60208301516040516370a0823160e01b81523060048201525f916001600160a01b0316906370a0823190602401602060405180830381865afa158015610fd9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ffd9190613d33565b9050611011816706f05b59d3b20000612d5c565b846080015111156110355760405163558fcd9160e11b815260040160405180910390fd5b604080840151855191516370a0823160e01b81523060048201525f926110bb92859290916001600160a01b0316906370a0823190602401602060405180830381865afa158015611087573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110ab9190613d33565b866040015189608001515f612281565b905084606001518110156110e25760405163d6ac339560e01b815260040160405180910390fd5b5050505050565b5f5f80516020613f088339815191525c156111175760405163d56a08b560e01b815260040160405180910390fd5b506005546001600160a01b031690565b336001600160a01b03165f356001600160e01b0319166001600160e01b0319165f36604051611157929190613e6d565b60405180910390a25f80516020613f088339815191525c1561118c5760405163d56a08b560e01b815260040160405180910390fd5b6111966001612ddf565b6005546001600160a01b031633146111c157604051634f0f549960e11b815260040160405180910390fd5b60075460ff16156111e55760405163056f633d60e21b815260040160405180910390fd5b6111fa620f4240670de0b6b3a7640000613e3b565b81101561121a57604051633b46575d60e01b815260040160405180910390fd5b61122f620f4240670de0b6b3a7640000613e3b565b61124190670de0b6b3a7640000613e9b565b81111561126157604051630f71fbbf60e11b815260040160405180910390fd5b600681905561126f5f612ddf565b50565b336001600160a01b03165f356001600160e01b0319166001600160e01b0319165f366040516112a2929190613e6d565b60405180910390a25f80516020613f088339815191525c156112d75760405163d56a08b560e01b815260040160405180910390fd5b6112e16001612ddf565b6005546001600160a01b0316331461130c57604051634f0f549960e11b815260040160405180910390fd5b60075460ff16156113305760405163056f633d60e21b815260040160405180910390fd5b600854600211156113545760405163af785ec560e01b815260040160405180910390fd5b6007805460ff1916600117905561137c611377670de0b6b3a76400006064613d1c565b612df2565b61139833611393670de0b6b3a76400006064613d1c565b612dfc565b6113a0612e0a565b6113a95f612ddf565b565b336001600160a01b03165f356001600160e01b0319166001600160e01b0319165f366040516113db929190613e6d565b60405180910390a25f80516020613f088339815191525c156114105760405163d56a08b560e01b815260040160405180910390fd5b61141a6001612ddf565b60075460ff1661143d57604051632e41ba2d60e01b815260040160405180910390fd5b5f61144760025490565b90505f6114548583612f0e565b9050805f0361147657604051630c499f4760e01b815260040160405180910390fd5b6008545f5b818110156115c9575f6008828154811061149757611497613eae565b5f9182526020822001546040516370a0823160e01b81523060048201526001600160a01b03909116925082906370a0823190602401602060405180830381865afa1580156114e7573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061150b9190613d33565b90505f6115188683612d5c565b9050805f0361153a57604051635b00df6960e11b815260040160405180910390fd5b88888581811061154c5761154c613eae565b9050602002013581111561157357604051630451d9ed60e31b815260040160405180910390fd5b6040518181526001600160a01b0384169033907f63982df10efd8dfaaaa0fcc7f50b2d93b7cba26ccc48adee2873220d485dc39a9060200160405180910390a36115be833383612fb6565b50505060010161147b565b506115d386612df2565b6115dd3387612dfc565b5050506115eb5f801b612ddf565b505050565b335f9081526001602090815260408083206001600160a01b03861684529091528120548083111561162b5761162633855f612c72565b6108e3565b6108e3338561163a8685613e9b565b612c72565b610902620f4240670de0b6b3a7640000613e3b565b6040515f90819033906001600160e01b0319833516906116779084903690613e6d565b60405180910390a25f80516020613f088339815191525c156116ac5760405163d56a08b560e01b815260040160405180910390fd5b6116b66001612ddf565b60075460ff166116d957604051632e41ba2d60e01b815260040160405180910390fd5b6001600160a01b0387165f9081526009602052604090205460ff1661171157604051634b16fc2d60e11b815260040160405180910390fd5b6001600160a01b0385165f9081526009602052604090205460ff1661174957604051634b16fc2d60e11b815260040160405180910390fd5b6001600160a01b038781165f81815260096020526040808220938916825280822090516370a0823160e01b81523060048201529092906370a0823190602401602060405180830381865afa1580156117a3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117c79190613d33565b6040516370a0823160e01b81523060048201529091505f906001600160a01b038a16906370a0823190602401602060405180830381865afa15801561180e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118329190613d33565b905061185b8161184b6003670de0b6b3a7640000613e3b565b611856906001613e5a565b612d5c565b88111561187b5760405163dad25d8560e01b815260040160405180910390fd5b5f611893838660020154848760020154600654611f88565b9050878111156118b65760405163823a9c3760e01b815260040160405180910390fd5b6118ce8386600201548487600201548d600654612bf3565b96508a8711156118f157604051630451d9ed60e31b815260040160405180910390fd5b6118fb8388612fcb565b9250611907828a612ff0565b9150611920838660020154848760020154600654611f88565b95508086101561194357604051636212302360e01b815260040160405180910390fd5b878611156119645760405163823a9c3760e01b815260040160405180910390fd5b61196e878a612f0e565b81111561198e576040516337fb98f960e11b815260040160405180910390fd5b60408051888152602081018b90526001600160a01b03808d1692908f169133917f908fb5ee8f16c6bc9bc3690973819f32a4d4b10188134543c88706e0e1d43378910160405180910390a46119e48c3389612fb6565b6119ef8a338b613028565b50505050506119ff5f801b612ddf565b9550959350505050565b6040515f90819033906001600160e01b031983351690611a2c9084903690613e6d565b60405180910390a25f80516020613f088339815191525c15611a615760405163d56a08b560e01b815260040160405180910390fd5b611a6b6001612ddf565b60075460ff16611a8e57604051632e41ba2d60e01b815260040160405180910390fd5b6001600160a01b0387165f9081526009602052604090205460ff16611ac657604051634b16fc2d60e11b815260040160405180910390fd5b6001600160a01b0385165f9081526009602052604090205460ff16611afe57604051634b16fc2d60e11b815260040160405180910390fd5b6001600160a01b038781165f81815260096020526040808220938916825280822090516370a0823160e01b81523060048201529092906370a0823190602401602060405180830381865afa158015611b58573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b7c9190613d33565b6040516370a0823160e01b81523060048201529091505f906001600160a01b038a16906370a0823190602401602060405180830381865afa158015611bc3573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611be79190613d33565b9050611bfb826706f05b59d3b20000612d5c565b8a1115611c1b5760405163558fcd9160e11b815260040160405180910390fd5b5f611c33838660020154848760020154600654611f88565b905087811115611c565760405163823a9c3760e01b815260040160405180910390fd5b611c6e8386600201548487600201548f600654612281565b965088871015611c915760405163d6ac339560e01b815260040160405180910390fd5b611c9b838c612fcb565b9250611ca78288612ff0565b9150611cc0838660020154848760020154600654611f88565b955080861015611ce357604051636212302360e01b815260040160405180910390fd5b87861115611d045760405163823a9c3760e01b815260040160405180910390fd5b611d0e8b88612f0e565b811115611d2e576040516337fb98f960e11b815260040160405180910390fd5b604080518c8152602081018990526001600160a01b03808d1692908f169133917f908fb5ee8f16c6bc9bc3690973819f32a4d4b10188134543c88706e0e1d43378910160405180910390a4611d848c338d612fb6565b6119ef8a3389613028565b61090264e8d4a51000670de0b6b3a7640000613e3b565b336001600160a01b03165f356001600160e01b0319166001600160e01b0319165f36604051611dd6929190613e6d565b60405180910390a25f80516020613f088339815191525c15611e0b5760405163d56a08b560e01b815260040160405180910390fd5b611e156001612ddf565b6005546001600160a01b03163314611e4057604051634f0f549960e11b815260040160405180910390fd5b6001600160a01b038116611e67576040516351a9e5c560e01b815260040160405180910390fd5b600580546001600160a01b0319166001600160a01b03831617905561126f5f612ddf565b5f5f80516020613f088339815191525c15611eb95760405163d56a08b560e01b815260040160405180910390fd5b50600a5490565b610902670de0b6b3a76400006064613d1c565b5f5f80516020613f088339815191525c15611f015760405163d56a08b560e01b815260040160405180910390fd5b6001600160a01b0382165f9081526009602052604090205460ff16611f3957604051634b16fc2d60e11b815260040160405180910390fd5b506001600160a01b0381165f908152600960205260409020600201545b919050565b60606004805461085590613cd0565b611f7d6003670de0b6b3a7640000613e3b565b610902906001613e5a565b5f80611f948787612f0e565b90505f611fa18686612f0e565b90505f611fae8383612f0e565b90505f611fd4670de0b6b3a7640000611fcf670de0b6b3a764000089612ff0565b612f0e565b9050611fe08282612d5c565b9a9950505050505050505050565b5f336108e3818585612cff565b336001600160a01b03165f356001600160e01b0319166001600160e01b0319165f3660405161202b929190613e6d565b60405180910390a25f80516020613f088339815191525c156120605760405163d56a08b560e01b815260040160405180910390fd5b61206a6001612ddf565b60075460ff1661208d57604051632e41ba2d60e01b815260040160405180910390fd5b5f61209760025490565b90505f6120a4855f612d5c565b90505f6120b18683612ff0565b90505f6120be8285612f0e565b9050805f036120e057604051630c499f4760e01b815260040160405180910390fd5b6120ea338861303c565b6121147f000000000000000000000000e0e2ba143ee5268da87d529949a252111598730284612dfc565b61211d82613046565b6008545f5b81811015612270575f6008828154811061213e5761213e613eae565b5f9182526020822001546040516370a0823160e01b81523060048201526001600160a01b03909116925082906370a0823190602401602060405180830381865afa15801561218e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121b29190613d33565b90505f6121bf8683612d5c565b9050805f036121e157604051634b4ae51b60e11b815260040160405180910390fd5b8a8a858181106121f3576121f3613eae565b9050602002013581101561221a5760405163341a1f3360e11b815260040160405180910390fd5b6040518181526001600160a01b0384169033907fe74c91552b64c2e2e7bd255639e004e693bd3e1d01cc33e65610b86afcc1ffed9060200160405180910390a3612265833383613028565b505050600101612122565b5050505050506115eb5f801b612ddf565b5f8061228d8786612f0e565b90505f6122a2670de0b6b3a764000085612ff0565b90506122ae8582612d5c565b90505f6122bf8a611fcf8c85612fcb565b90505f6122cc8285613050565b90505f6122e1670de0b6b3a764000083612ff0565b90506122ed8a82612d5c565b9c9b505050505050505050505050565b612312620f4240670de0b6b3a7640000613e3b565b61090290670de0b6b3a7640000613e9b565b6001612339670de0b6b3a76400006002613d1c565b6109029190613e9b565b60605f80516020613f088339815191525c156123725760405163d56a08b560e01b815260040160405180910390fd5b60075460ff1661239557604051632e41ba2d60e01b815260040160405180910390fd5b60088054806020026020016040519081016040528092919081815260200182805480156108cc57602002820191905f5260205f20905b81546001600160a01b031681526001909101906020018083116123cb575050505050905090565b60605f80516020613f088339815191525c156123955760405163d56a08b560e01b815260040160405180910390fd5b336001600160a01b03165f356001600160e01b0319166001600160e01b0319165f36604051612451929190613e6d565b60405180910390a25f80516020613f088339815191525c156124865760405163d56a08b560e01b815260040160405180910390fd5b6124906001612ddf565b6005546001600160a01b031633146124bb57604051634f0f549960e11b815260040160405180910390fd5b60075460ff16156124df5760405163056f633d60e21b815260040160405180910390fd5b6001600160a01b0381165f9081526009602052604090205460ff1661251757604051634b16fc2d60e11b815260040160405180910390fd5b600a546001600160a01b0382165f9081526009602052604090206002015461253f9190612ff0565b600a556001600160a01b0381165f90815260096020526040812060019081015460085490929161256e91613e9b565b90506008818154811061258357612583613eae565b5f91825260209091200154600880546001600160a01b0390921691849081106125ae576125ae613eae565b905f5260205f20015f6101000a8154816001600160a01b0302191690836001600160a01b031602179055508160095f600885815481106125f0576125f0613eae565b5f9182526020808320909101546001600160a01b03168352820192909252604001902060010155600880548061262857612628613ec2565b5f82815260208082205f19908401810180546001600160a01b0319169055909201909255604080516060810182528381528083018481528183018581526001600160a01b0389168087526009909552948390209151825460ff1916901515178255516001820155925160029093019290925590516370a0823160e01b81523060048201526127029185913391906370a0823190602401602060405180830381865afa1580156126d9573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126fd9190613d33565b613028565b5061126f90505f612ddf565b5f5f80516020613f088339815191525c1561273c5760405163d56a08b560e01b815260040160405180910390fd5b5060065490565b335f8181526001602090815260408083206001600160a01b0387168452909152812054909161277991859061163a908690613e5a565b50600192915050565b336001600160a01b03165f356001600160e01b0319166001600160e01b0319165f366040516127b2929190613e6d565b60405180910390a25f80516020613f088339815191525c156127e75760405163d56a08b560e01b815260040160405180910390fd5b6127f16001612ddf565b6005546001600160a01b0316331461281c57604051634f0f549960e11b815260040160405180910390fd5b60075460ff16156128405760405163056f633d60e21b815260040160405180910390fd5b6001600160a01b0383165f9081526009602052604090205460ff161561287957604051636b1ed1b760e11b815260040160405180910390fd5b600880541061289b5760405163c47f9e9360e01b815260040160405180910390fd5b670de0b6b3a76400008110156128c4576040516342eb024360e01b815260040160405180910390fd5b6128d7670de0b6b3a76400006032613d1c565b8111156128f757604051630cbe784360e11b815260040160405180910390fd5b61290e64e8d4a51000670de0b6b3a7640000613e3b565b82101561292e57604051638968448b60e01b815260040160405180910390fd5b61293a600a5482612fcb565b600a55612950670de0b6b3a76400006032613d1c565b600a541115612972576040516342f71f0b60e01b815260040160405180910390fd5b6040805160608101825260018082526008805460208085019182528486018781526001600160a01b038a165f81815260099093529682209551865460ff19169015151786559151858501559051600290940193909355805491820181559091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30180546001600160a01b0319169091179055612a10833384612fb6565b6115eb5f612ddf565b5f80516020613f088339815191525c15612a465760405163d56a08b560e01b815260040160405180910390fd5b336001600160a01b037f0000000000000000000000009008d19f58aabd9ed0d60971565aa8510560ab411614612a8f5760405163bf84897760e01b815260040160405180910390fd5b61126f81612ddf565b5f5f80516020613f088339815191525c15612ac65760405163d56a08b560e01b815260040160405180910390fd5b6001600160a01b0382165f9081526009602052604090205460ff16612afe57604051634b16fc2d60e11b815260040160405180910390fd5b6001600160a01b0382165f90815260096020526040902060020154600a54610da3908290612f0e565b5f5f80516020613f088339815191525c15612b555760405163d56a08b560e01b815260040160405180910390fd5b6001600160a01b0382165f9081526009602052604090205460ff16612b8d57604051634b16fc2d60e11b815260040160405180910390fd5b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015612bcf573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108e99190613d33565b5f80612bff8588612f0e565b90505f612c0c8786612ff0565b90505f612c198883612f0e565b90505f612c268285613050565b9050612c3a81670de0b6b3a7640000612ff0565b9050612c4e670de0b6b3a764000087612ff0565b9450612c63612c5d8c83612d5c565b86612f0e565b9b9a5050505050505050505050565b6115eb8383836001613105565b6001600160a01b038381165f908152600160209081526040808320938616835292905220545f198114612cf95781811015612ceb57604051637dc7a0d960e11b81526001600160a01b038416600482015260248101829052604481018390526064015b60405180910390fd5b612cf984848484035f613105565b50505050565b6001600160a01b038316612d2857604051634b637e8f60e11b81525f6004820152602401612ce2565b6001600160a01b038216612d515760405163ec442f0560e01b81525f6004820152602401612ce2565b6115eb8383836131d7565b5f8282028315801590612d7e575082848281612d7a57612d7a613e27565b0414155b15612d9c5760405163202e377f60e01b815260040160405180910390fd5b6706f05b59d3b20000810181811015612dc85760405163202e377f60e01b815260040160405180910390fd5b5f670de0b6b3a7640000825b049695505050505050565b805f80516020613f088339815191525d50565b61126f30826132fd565b612e068282613331565b5050565b6008545f5b81811015612e7357612e6b7f000000000000000000000000c92e8bdf79f0507f65a392b0ab4667716bfe01105f1960088481548110612e5057612e50613eae565b5f918252602090912001546001600160a01b0316919061333c565b600101612e0f565b507f000000000000000000000000e0e2ba143ee5268da87d529949a25211159873026001600160a01b03166352b8cb636040518163ffffffff1660e01b81526004015f604051808303815f87803b158015612ecc575f80fd5b505af1925050508015612edd575060015b61126f5760405130907f0d03834d0d86c7f57e877af40e26f176dc31bd637535d4ba153d1ac9de88a7ea905f90a250565b5f815f03612f2f5760405163abcf2e7560e01b815260040160405180910390fd5b670de0b6b3a764000083028315801590612f605750670de0b6b3a7640000848281612f5c57612f5c613e27565b0414155b15612f7e576040516394fb03d760e01b815260040160405180910390fd5b600183901c810181811015612fa6576040516394fb03d760e01b815260040160405180910390fd5b5f848281612dd457612dd4613e27565b6115eb6001600160a01b0384168330846133f9565b5f82820183811015610da35760405163e468448f60e01b815260040160405180910390fd5b5f805f612ffd8585613432565b91509150801561302057604051630a5c778b60e31b815260040160405180910390fd5b509392505050565b6115eb6001600160a01b0384168383613455565b612e068282613486565b61126f3082613491565b5f600183101561307357604051635567969f60e11b815260040160405180910390fd5b671bc16d674ec7ffff83111561309c57604051638554775f60e01b815260040160405180910390fd5b670de0b6b3a7640000808304025f6130b48483612ff0565b90505f6130cb86670de0b6b3a764000085046134c5565b9050815f036130de5792506108e9915050565b5f6130ee87846305f5e10061351d565b90506130fa8282612d5c565b979650505050505050565b6001600160a01b03841661312e5760405163e602df0560e01b81525f6004820152602401612ce2565b6001600160a01b03831661315757604051634a1406b160e11b81525f6004820152602401612ce2565b6001600160a01b038085165f9081526001602090815260408083209387168352929052208290558015612cf957826001600160a01b0316846001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040516131c991815260200190565b60405180910390a350505050565b6001600160a01b038316613201578060025f8282546131f69190613e5a565b909155506132719050565b6001600160a01b0383165f90815260208190526040902054818110156132535760405163391434e360e21b81526001600160a01b03851660048201526024810182905260448101839052606401612ce2565b6001600160a01b0384165f9081526020819052604090209082900390555b6001600160a01b03821661328d576002805482900390556132ab565b6001600160a01b0382165f9081526020819052604090208054820190555b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516132f091815260200190565b60405180910390a3505050565b6001600160a01b0382166133265760405163ec442f0560e01b81525f6004820152602401612ce2565b612e065f83836131d7565b612e06308383612cff565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b17905261338d84826135f9565b612cf9576040516001600160a01b0384811660248301525f60448301526133ef91869182169063095ea7b3906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050613696565b612cf98482613696565b6040516001600160a01b038481166024830152838116604483015260648201839052612cf99186918216906323b872dd906084016133bd565b5f808284106134465750508082035f61344e565b505081810360015b9250929050565b6040516001600160a01b038381166024830152604482018390526115eb91859182169063a9059cbb906064016133bd565b612e06823083612cff565b6001600160a01b0382166134ba57604051634b637e8f60e11b81525f6004820152602401612ce2565b612e06825f836131d7565b5f80600283065f036134df57670de0b6b3a76400006134e1565b835b90506002830492505b8215610da3576134fa8485612d5c565b935060028306156135125761350f8185612d5c565b90505b6002830492506134ea565b5f82818061353387670de0b6b3a7640000613432565b9092509050670de0b6b3a7640000805f60015b8884106135ea575f670de0b6b3a7640000820290505f806135788a61357385670de0b6b3a7640000612ff0565b613432565b9150915061358a87611856848c612d5c565b96506135968784612f0e565b9650865f036135a7575050506135ea565b87156135b1579315935b80156135bb579315935b84156135d2576135cb8688612ff0565b95506135df565b6135dc8688612fcb565b95505b505050600101613546565b50909998505050505050505050565b5f805f846001600160a01b0316846040516136149190613ed6565b5f604051808303815f865af19150503d805f811461364d576040519150601f19603f3d011682016040523d82523d5f602084013e613652565b606091505b509150915081801561367c57508051158061367c57508080602001905181019061367c9190613eec565b8015610a9b5750505050506001600160a01b03163b151590565b5f6136aa6001600160a01b038416836136f7565b905080515f141580156136ce5750808060200190518101906136cc9190613eec565b155b156115eb57604051635274afe760e01b81526001600160a01b0384166004820152602401612ce2565b6060610da383835f845f80856001600160a01b0316848660405161371b9190613ed6565b5f6040518083038185875af1925050503d805f8114613755576040519150601f19603f3d011682016040523d82523d5f602084013e61375a565b606091505b509150915061376a868383613774565b9695505050505050565b60608261378957613784826137d0565b610da3565b81511580156137a057506001600160a01b0384163b155b156137c957604051639996b31560e01b81526001600160a01b0385166004820152602401612ce2565b5080610da3565b8051156137e05780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b6001600160a01b038116811461126f575f80fd5b8035611f568161382e565b5f806040838503121561385e575f80fd5b82356138698161382e565b946020939093013593505050565b5f8060408385031215613888575f80fd5b82356138938161382e565b915060208301356138a38161382e565b809150509250929050565b634e487b7160e01b5f52604160045260245ffd5b604051610180810167ffffffffffffffff811182821017156138e6576138e66138ae565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715613915576139156138ae565b604052919050565b5f806040838503121561392e575f80fd5b8235915060208084013567ffffffffffffffff8082111561394d575f80fd5b818601915086601f830112613960575f80fd5b813581811115613972576139726138ae565b613984601f8201601f191685016138ec565b91508082528784828501011115613999575f80fd5b80848401858401375f848284010152508093505050509250929050565b5f805f606084860312156139c8575f80fd5b83356139d38161382e565b925060208401356139e38161382e565b929592945050506040919091013590565b63ffffffff8116811461126f575f80fd5b8035611f56816139f4565b801515811461126f575f80fd5b8035611f5681613a10565b5f6101808284031215613a39575f80fd5b613a416138c2565b613a4a83613842565b8152613a5860208401613842565b6020820152613a6960408401613842565b60408201526060830135606082015260808301356080820152613a8e60a08401613a05565b60a082015260c083013560c082015260e083013560e0820152610100808401358183015250610120613ac1818501613a1d565b908201526101408381013590820152610160928301359281019290925250919050565b5f60208284031215613af4575f80fd5b8135610da38161382e565b5f60208284031215613b0f575f80fd5b5035919050565b5f805f60408486031215613b28575f80fd5b83359250602084013567ffffffffffffffff80821115613b46575f80fd5b818601915086601f830112613b59575f80fd5b813581811115613b67575f80fd5b8760208260051b8501011115613b7b575f80fd5b6020830194508093505050509250925092565b5f805f805f60a08688031215613ba2575f80fd5b8535613bad8161382e565b9450602086013593506040860135613bc48161382e565b94979396509394606081013594506080013592915050565b5f805f805f60a08688031215613bf0575f80fd5b505083359560208501359550604085013594606081013594506080013592509050565b5f805f805f8060c08789031215613c28575f80fd5b505084359660208601359650604086013595606081013595506080810135945060a0013592509050565b602080825282518282018190525f9190848201906040850190845b81811015613c925783516001600160a01b031683529284019291840191600101613c6d565b50909695505050505050565b5f805f60608486031215613cb0575f80fd5b8335613cbb8161382e565b95602085013595506040909401359392505050565b600181811c90821680613ce457607f821691505b602082108103613d0257634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52601160045260245ffd5b80820281158282048414176108e9576108e9613d08565b5f60208284031215613d43575f80fd5b5051919050565b8051611f568161382e565b8051611f56816139f4565b8051611f5681613a10565b5f6101808284031215613d7c575f80fd5b613d846138c2565b613d8d83613d4a565b8152613d9b60208401613d4a565b6020820152613dac60408401613d4a565b60408201526060830151606082015260808301516080820152613dd160a08401613d55565b60a082015260c083015160c082015260e083015160e0820152610100808401518183015250610120613e04818501613d60565b908201526101408381015190820152610160928301519281019290925250919050565b634e487b7160e01b5f52601260045260245ffd5b5f82613e5557634e487b7160e01b5f52601260045260245ffd5b500490565b808201808211156108e9576108e9613d08565b60208152816020820152818360408301375f818301604090810191909152601f909201601f19160101919050565b818103818111156108e9576108e9613d08565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52603160045260245ffd5b5f82518060208501845e5f920191825250919050565b5f60208284031215613efc575f80fd5b8151610da381613a1056fe3f8f4c536ce1b925b469af1b09a44da237dab5bbc584585648c12be1ca25a8c4a26469706673582212203618b9f7655c1be46da20cd07ebac82e300887c0c44726db647af911fa07e50c64736f6c63430008190033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000009008d19f58aabd9ed0d60971565aa8510560ab41362e5182440b52aa8fffe70a251550fbbcbca424740fe5a14f59bf0c1b06fe1d000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000001f42616c616e63657220436f5720414d4d20353020415242203530205745544800000000000000000000000000000000000000000000000000000000000000001142436f572d35304152422d353057455448000000000000000000000000000000
-----Decoded View---------------
Arg [0] : cowSolutionSettler (address): 0x9008D19f58AAbD9eD0D60971565AA8510560ab41
Arg [1] : appData (bytes32): 0x362e5182440b52aa8fffe70a251550fbbcbca424740fe5a14f59bf0c1b06fe1d
Arg [2] : name (string): Balancer CoW AMM 50 ARB 50 WETH
Arg [3] : symbol (string): BCoW-50ARB-50WETH
-----Encoded View---------------
8 Constructor Arguments found :
Arg [0] : 0000000000000000000000009008d19f58aabd9ed0d60971565aa8510560ab41
Arg [1] : 362e5182440b52aa8fffe70a251550fbbcbca424740fe5a14f59bf0c1b06fe1d
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000080
Arg [3] : 00000000000000000000000000000000000000000000000000000000000000c0
Arg [4] : 000000000000000000000000000000000000000000000000000000000000001f
Arg [5] : 42616c616e63657220436f5720414d4d20353020415242203530205745544800
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000011
Arg [7] : 42436f572d35304152422d353057455448000000000000000000000000000000
Deployed Bytecode Sourcemap
2470:4284:16:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2074:89:8;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;4293:186;;;;;;:::i;:::-;;:::i;:::-;;;1220:14:27;;1213:22;1195:41;;1183:2;1168:18;4293:186:8;1055:187:27;1070:52:17;;;:::i;:::-;;;1393:25:27;;;1381:2;1366:18;1070:52:17;1247:177:27;11368:555:20;;;;;;:::i;:::-;;:::i;10784:::-;;;;;;:::i;:::-;;:::i;3733:720:16:-;;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;;3489:33:27;;;3471:52;;3459:2;3444:18;3733:720:16;3327:202:27;3144:97:8;3222:12;;3144:97;;1678:56:17;;;:::i;853:41::-;;270:8;853:41;;5039:244:8;;;;;;:::i;:::-;;:::i;2630:38:16:-;;;;;;;;-1:-1:-1;;;;;4159:55:27;;;4141:74;;4129:2;4114:18;2630:38:16;3995:226:27;4485:1440:16;;;;;;:::i;:::-;;:::i;:::-;;606:32:20;;;;;12061:100;;;;;;:::i;:::-;-1:-1:-1;;;;;12135:15:20;12116:4;12135:15;;;:8;:15;;;;;:21;;;;12061:100;13599:97;;;:::i;3002:82:8:-;;;3075:2;6256:36:27;;6244:2;6229:18;3002:82:8;6114:184:27;2373:263:20;;;;;;:::i;:::-;;:::i;2894:303::-;;;:::i;4758:883::-;;;;;;:::i;:::-;;:::i;1051:315:21:-;;;;;;:::i;:::-;;:::i;2870:33:16:-;;;;;3299:116:8;;;;;;:::i;:::-;-1:-1:-1;;;;;3390:18:8;3364:7;3390:18;;;;;;;;;;;;3299:116;552:48:17;;;:::i;8762:1993:20:-;;;;;;:::i;:::-;;:::i;:::-;;;;8131:25:27;;;8187:2;8172:18;;8165:34;;;;8104:18;8762:1993:20;7957:248:27;6744:1989:20;;;;;;:::i;:::-;;:::i;1184:53:17:-;;;:::i;2792:45:16:-;;;;;11952:80:20;12017:10;;;;11952:80;;2665:200;;;;;;:::i;:::-;;:::i;12819:111::-;;;:::i;1330:53:17:-;;;:::i;12585:205:20:-;;;;;;:::i;:::-;;:::i;2276:93:8:-;;;:::i;366:53:15:-;;410:9;366:53;;;;;8635:10:27;8623:23;;;8605:42;;8593:2;8578:18;366:53:15;8461:192:27;1946:58:17;;;:::i;1280:459:18:-;;;;;;:::i;:::-;;:::i;3610:178:8:-;;;;;;:::i;:::-;;:::i;5670:1045:20:-;;;;;;:::i;:::-;;:::i;451:44:17:-;;494:1;451:44;;343;;386:1;343:44;;1451:45;;1491:5;1451:45;;2699:620:18;;;;;;:::i;:::-;;:::i;656:48:17:-;;;:::i;1563:58::-;;;:::i;12441:115:20:-;;;:::i;:::-;;;;;;;:::i;756:36:17:-;;791:1;756:36;;12307:105:20;;;:::i;12190:88::-;12259:7;:14;12190:88;;4085:644;;;;;;:::i;:::-;;:::i;13479:91::-;;;:::i;603:192:21:-;;;;;;:::i;:::-;;:::i;2701:58:16:-;;;;;3846:140:8;;;;;;:::i;:::-;-1:-1:-1;;;;;3952:18:8;;;3926:7;3952:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;3846:140;3226:830:20;;;;;;:::i;:::-;;:::i;1816:48:17:-;;1855:9;1816:48;;3419:184:16;;;;;;:::i;:::-;;:::i;12959:252:20:-;;;;;;:::i;:::-;;:::i;13240:210::-;;;;;;:::i;:::-;;:::i;4335:606:18:-;;;;;;:::i;:::-;;:::i;2074:89:8:-;2119:13;2151:5;2144:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2074:89;:::o;4293:186::-;4366:4;735:10:14;4420:31:8;735:10:14;4436:7:8;4445:5;4420:8;:31::i;:::-;4468:4;4461:11;;;4293:186;;;;;:::o;1070:52:17:-;1113:9;270:8;1120:2;1113:9;:::i;:::-;1070:52;:::o;11368:555:20:-;11466:7;-1:-1:-1;;;;;;;;;;;16490:36:20;1521:25;1517:71;;1563:18;;-1:-1:-1;;;1563:18:20;;;;;;;;;;;1517:71;-1:-1:-1;;;;;11486:17:20;::::1;;::::0;;;:8:::1;:17;::::0;;;;:23;::::1;;11481:73;;11526:21;;-1:-1:-1::0;;;11526:21:20::1;;;;;;;;;;;11481:73;-1:-1:-1::0;;;;;11564:18:20;::::1;;::::0;;;:8:::1;:18;::::0;;;;:24;::::1;;11559:74;;11605:21;;-1:-1:-1::0;;;11605:21:20::1;;;;;;;;;;;11559:74;-1:-1:-1::0;;;;;11664:17:20;;::::1;11638:23;11664:17:::0;;;:8:::1;:17;::::0;;;;;11714:18;;::::1;::::0;;;;;;11767:40;;-1:-1:-1;;;11767:40:20;;11801:4:::1;11767:40;::::0;::::1;4141:74:27::0;11714:18:20;;11746:172:::1;::::0;11767:25:::1;::::0;4114:18:27;;11767:40:20::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;11815:15;::::0;::::1;::::0;11838:41:::1;::::0;-1:-1:-1;;;11838:41:20;;11873:4:::1;11838:41;::::0;::::1;4141:74:27::0;-1:-1:-1;;;;;11838:26:20;::::1;::::0;::::1;::::0;4114:18:27;;11838:41:20::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;11887:9;:16;;;11911:1;11746:13;:172::i;:::-;11739:179:::0;11368:555;-1:-1:-1;;;;;11368:555:20:o;10784:::-;10875:7;-1:-1:-1;;;;;;;;;;;16490:36:20;1521:25;1517:71;;1563:18;;-1:-1:-1;;;1563:18:20;;;;;;;;;;;1517:71;-1:-1:-1;;;;;10895:17:20;::::1;;::::0;;;:8:::1;:17;::::0;;;;:23;::::1;;10890:73;;10935:21;;-1:-1:-1::0;;;10935:21:20::1;;;;;;;;;;;10890:73;-1:-1:-1::0;;;;;10973:18:20;::::1;;::::0;;;:8:::1;:18;::::0;;;;:24;::::1;;10968:74;;11014:21;;-1:-1:-1::0;;;11014:21:20::1;;;;;;;;;;;10968:74;-1:-1:-1::0;;;;;11073:17:20;;::::1;11047:23;11073:17:::0;;;:8:::1;:17;::::0;;;;;11123:18;;::::1;::::0;;;;;;11176:40;;-1:-1:-1;;;11176:40:20;;11210:4:::1;11176:40;::::0;::::1;4141:74:27::0;11123:18:20;;11155:179:::1;::::0;11176:25:::1;::::0;4114:18:27;;11176:40:20::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;11224:15;::::0;::::1;::::0;11247:41:::1;::::0;-1:-1:-1;;;11247:41:20;;11282:4:::1;11247:41;::::0;::::1;4141:74:27::0;-1:-1:-1;;;;;11247:26:20;::::1;::::0;::::1;::::0;4114:18:27;;11247:41:20::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;11296:9;:16;;;11320:8;;11155:13;:179::i;3733:720:16:-:0;3825:17;3851:27;3893:9;3882:39;;;;;;;;;;;;:::i;:::-;3850:71;;3949:8;3932:5;:13;;;:25;3928:74;;3974:21;;-1:-1:-1;;;3974:21:16;;;;;;;;;;;3928:74;-1:-1:-1;;5401:14:3;;5440:16;;5487:9;5469:28;;5545:3;5524:25;;5562:23;;6143:4;6137:11;-1:-1:-1;;;6161:37:3;;4040:33:16;6241:1:3;6218:25;;6211:50;6304:2;6281:26;;6274:46;;;;6377:2;6348:32;;4098:9:16;4084:10;:23;4080:81;;4124:30;;-1:-1:-1;;;4124:30:16;;;;;;;;;;;4080:81;-1:-1:-1;;;;;;;;;;;16490:36:20;4171:10:16;:24;4167:85;;4212:33;;-1:-1:-1;;;4212:33:16;;;;;;;;;;;4167:85;4258:13;4265:5;4258:6;:13::i;:::-;-1:-1:-1;;;;4418:30:16;3733:720;-1:-1:-1;;;;3733:720:16:o;1678:56:17:-;1719:15;1726:8;270;1719:15;:::i;5039:244:8:-;5126:4;735:10:14;5182:37:8;5198:4;735:10:14;5213:5:8;5182:15;:37::i;:::-;5229:26;5239:4;5245:2;5249:5;5229:9;:26::i;:::-;5272:4;5265:11;;;5039:244;;;;;;:::o;4485:1440:16:-;4598:14;;;;;-1:-1:-1;;;;;4581:33:16;;;4556:22;4581:33;;;:8;:33;;;;;;;4556:58;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4663:15;;4646:34;;;;;;;;;;;;4620:60;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4692:14;;4556:58;;4620:60;4691:15;;:35;;-1:-1:-1;4711:15:16;;4710:16;4691:35;4687:84;;;4743:21;;-1:-1:-1;;;4743:21:16;;;;;;;;;;;4687:84;4780:14;;;;-1:-1:-1;;;;;4780:50:16;;4776:110;;4847:32;;-1:-1:-1;;;4847:32:16;;;;;;;;;;;4776:110;4911:36;410:9:15;4911:15:16;:36;:::i;:::-;4895:5;:13;;;:52;;;4891:111;;;4964:31;;-1:-1:-1;;;4964:31:16;;;;;;;;;;;4891:111;5011:15;;;;:20;5007:72;;5048:24;;-1:-1:-1;;;5048:24:16;;;;;;;;;;;5007:72;5102:19;5088:5;:10;;;:33;5084:88;;5138:27;;-1:-1:-1;;;5138:27:16;;;;;;;;;;;5084:88;5206:23;5181:5;:21;;;:48;;:101;;;;5259:23;5233:5;:22;;;:49;;5181:101;5177:160;;;5299:31;;-1:-1:-1;;;5299:31:16;;;;;;;;;;;5177:160;5369:14;;;;:39;;-1:-1:-1;;;5369:39:16;;5402:4;5369:39;;;4141:74:27;5343:23:16;;-1:-1:-1;;;;;5369:24:16;;;;4114:18:27;;5369:39:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5343:65;-1:-1:-1;5436:35:16;5343:65;1855:9:17;5436:4:16;:35::i;:::-;5418:5;:15;;;:53;5414:115;;;5488:34;;-1:-1:-1;;;5488:34:16;;;;;;;;;;;5414:115;5637:15;;;;;5677;;:40;;-1:-1:-1;;;5677:40:16;;5711:4;5677:40;;;4141:74:27;5535:22:16;;5560:260;;5599:15;;5637;;-1:-1:-1;;;;;5677:25:16;;;;4114:18:27;;5677:40:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5741:9;:16;;;5780:5;:15;;;5812:1;5560:14;:260::i;:::-;5535:285;;5848:5;:16;;;5831:14;:33;5827:94;;;5881:33;;-1:-1:-1;;;5881:33:16;;;;;;;;;;;5827:94;4550:1375;;;;4485:1440;:::o;13599:97:20:-;13658:7;-1:-1:-1;;;;;;;;;;;16490:36:20;1521:25;1517:71;;1563:18;;-1:-1:-1;;;1563:18:20;;;;;;;;;;;1517:71;-1:-1:-1;13680:11:20::1;::::0;-1:-1:-1;;;;;13680:11:20::1;13599:97:::0;:::o;2373:263::-;1152:10;-1:-1:-1;;;;;1134:39:20;1143:7;;-1:-1:-1;;;;;;1143:7:20;-1:-1:-1;;;;;1134:39:20;;1164:8;;1134:39;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;;;;;;;;;;;16490:36:20;1270:25;1266:71:::1;;1312:18;;-1:-1:-1::0;;;1312:18:20::1;;;;;;;;;;;1266:71;1342:22;2676:1:17;1342:8:20;:22::i;:::-;2035:11:::2;::::0;-1:-1:-1;;;;;2035:11:20::2;2021:10;:25;2017:82;;2063:29;;-1:-1:-1::0;;;2063:29:20::2;;;;;;;;;;;2017:82;1846:10:::3;::::0;::::3;;1842:61;;;1873:23;;-1:-1:-1::0;;;1873:23:20::3;;;;;;;;;;;1842:61;586:14:17::4;593:7;270:8;586:14;:::i;:::-;2471:7:20;:17;2467:68;;;2505:23;;-1:-1:-1::0;;;2505:23:20::4;;;;;;;;;;;2467:68;586:14:17;593:7;270:8;586:14;:::i;:::-;690;::::0;270:8:::4;690:14;:::i;:::-;2544:7:20;:17;2540:68;;;2578:23;;-1:-1:-1::0;;;2578:23:20::4;;;;;;;;;;;2540:68;2613:8;:18:::0;;;1377:21:::1;2546:1:17;1377:8:20;:21::i;:::-;2373:263:::0;:::o;2894:303::-;1152:10;-1:-1:-1;;;;;1134:39:20;1143:7;;-1:-1:-1;;;;;;1143:7:20;-1:-1:-1;;;;;1134:39:20;;1164:8;;1134:39;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;;;;;;;;;;;16490:36:20;1270:25;1266:71:::1;;1312:18;;-1:-1:-1::0;;;1312:18:20::1;;;;;;;;;;;1266:71;1342:22;2676:1:17;1342:8:20;:22::i;:::-;2035:11:::2;::::0;-1:-1:-1;;;;;2035:11:20::2;2021:10;:25;2017:82;;2063:29;;-1:-1:-1::0;;;2063:29:20::2;;;;;;;;;;;2017:82;1846:10:::3;::::0;::::3;;1842:61;;;1873:23;;-1:-1:-1::0;;;1873:23:20::3;;;;;;;;;;;1842:61;2975:7:::4;:14:::0;386:1:17::4;-1:-1:-1::0;2971:87:20::4;;;3025:26;;-1:-1:-1::0;;;3025:26:20::4;;;;;;;;;;;2971:87;3064:10;:17:::0;;-1:-1:-1;;3064:17:20::4;3077:4;3064:17;::::0;;3088:32:::4;1373:10:17;270:8;1380:3;1373:10;:::i;:::-;3088:14:20;:32::i;:::-;3126:44;3141:10;1373::17;270:8;1380:3;1373:10;:::i;:::-;3126:14:20;:44::i;:::-;3176:16;:14;:16::i;:::-;1377:21:::1;2546:1:17;1377:8:20;:21::i;:::-;2894:303::o:0;4758:883::-;1152:10;-1:-1:-1;;;;;1134:39:20;1143:7;;-1:-1:-1;;;;;;1143:7:20;-1:-1:-1;;;;;1134:39:20;;1164:8;;1134:39;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;;;;;;;;;;;16490:36:20;1270:25;1266:71:::1;;1312:18;;-1:-1:-1::0;;;1312:18:20::1;;;;;;;;;;;1266:71;1342:22;2676:1:17;1342:8:20;:22::i;:::-;1689:10:::2;::::0;::::2;;1684:63;;1716:24;;-1:-1:-1::0;;;1716:24:20::2;;;;;;;;;;;1684:63;4873:17:::3;4893:13;3222:12:8::0;;;3144:97;4893:13:20::3;4873:33;;4912:13;4928:30;4933:13;4948:9;4928:4;:30::i;:::-;4912:46;;4968:5;4977:1;4968:10:::0;4964:62:::3;;4995:24;;-1:-1:-1::0;;;4995:24:20::3;;;;;;;;;;;4964:62;5055:7;:14:::0;5032:20:::3;5075:480;5099:12;5095:1;:16;5075:480;;;5126:9;5138:7;5146:1;5138:10;;;;;;;;:::i;:::-;;::::0;;;::::3;::::0;;::::3;::::0;5170:34:::3;::::0;-1:-1:-1;;;5170:34:20;;5198:4:::3;5170:34;::::0;::::3;4141:74:27::0;-1:-1:-1;;;;;5138:10:20;;::::3;::::0;-1:-1:-1;5138:10:20;;5170:19:::3;::::0;4114:18:27;;5170:34:20::3;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5156:48;;5212:21;5236:16;5241:5;5248:3;5236:4;:16::i;:::-;5212:40;;5264:13;5281:1;5264:18:::0;5260:78:::3;;5301:28;;-1:-1:-1::0;;;5301:28:20::3;;;;;;;;;;;5260:78;5365:12;;5378:1;5365:15;;;;;;;:::i;:::-;;;;;;;5349:13;:31;5345:100;;;5399:37;;-1:-1:-1::0;;;5399:37:20::3;;;;;;;;;;;5345:100;5457:38;::::0;1393:25:27;;;-1:-1:-1;;;;;5457:38:20;::::3;::::0;5466:10:::3;::::0;5457:38:::3;::::0;1381:2:27;1366:18;5457:38:20::3;;;;;;;5503:45;5519:1;5522:10;5534:13;5503:15;:45::i;:::-;-1:-1:-1::0;;;5113:3:20::3;;5075:480;;;;5560:29;5575:13;5560:14;:29::i;:::-;5595:41;5610:10;5622:13;5595:14;:41::i;:::-;4867:774;;;1377:21:::1;2546:1:17;2530:19:::0;::::1;1377:8:20;:21::i;:::-;4758:883:::0;;;:::o;1051:315:21:-;1177:10;1128:12;3952:18:8;;;:11;:18;;;;;;;;-1:-1:-1;;;;;3952:27:8;;;;;;;;;;1216:8:21;1207:6;:17;1203:139;;;1234:32;1243:10;1255:7;1264:1;1234:8;:32::i;:::-;1203:139;;;1287:48;1296:10;1308:7;1317:17;1328:6;1317:8;:17;:::i;:::-;1287:8;:48::i;552::17:-;586:14;593:7;270:8;586:14;:::i;8762:1993:20:-;1134:39;;8956:21;;;;1152:10;;-1:-1:-1;;;;;;1143:7:20;;;;1134:39;;8956:21;;1164:8;;1134:39;:::i;:::-;;;;;;;;-1:-1:-1;;;;;;;;;;;16490:36:20;1270:25;1266:71:::1;;1312:18;;-1:-1:-1::0;;;1312:18:20::1;;;;;;;;;;;1266:71;1342:22;2676:1:17;1342:8:20;:22::i;:::-;1689:10:::2;::::0;::::2;;1684:63;;1716:24;;-1:-1:-1::0;;;1716:24:20::2;;;;;;;;;;;1684:63;-1:-1:-1::0;;;;;9014:17:20;::::3;;::::0;;;:8:::3;:17;::::0;;;;:23;::::3;;9009:73;;9054:21;;-1:-1:-1::0;;;9054:21:20::3;;;;;;;;;;;9009:73;-1:-1:-1::0;;;;;9092:18:20;::::3;;::::0;;;:8:::3;:18;::::0;;;;:24;::::3;;9087:74;;9133:21;;-1:-1:-1::0;;;9133:21:20::3;;;;;;;;;;;9087:74;-1:-1:-1::0;;;;;9193:26:20;;::::3;9167:23;9193:26:::0;;;:8:::3;:26;::::0;;;;;9252:27;;::::3;::::0;;;;;9311:40;;-1:-1:-1;;;9311:40:20;;9345:4:::3;9311:40;::::0;::::3;4141:74:27::0;9252:27:20;;9193:26;9311:25:::3;::::0;4114:18:27;;9311:40:20::3;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;9383:41;::::0;-1:-1:-1;;;9383:41:20;;9418:4:::3;9383:41;::::0;::::3;4141:74:27::0;9286:65:20;;-1:-1:-1;9357:23:20::3;::::0;-1:-1:-1;;;;;9383:26:20;::::3;::::0;::::3;::::0;4114:18:27;;9383:41:20::3;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;9357:67:::0;-1:-1:-1;9452:36:20::3;9357:67:::0;1987:8:17::3;1994:1;270:8;1987;:::i;:::-;1986:18;::::0;1999:5:::3;1986:18;:::i;:::-;9452:4:20;:36::i;:::-;9435:14;:53;9431:114;;;9505:33;;-1:-1:-1::0;;;9505:33:20::3;;;;;;;;;;;9431:114;9551:23;9583:91;9597:14;9613:8;:15;;;9630;9647:9;:16;;;9665:8;;9583:13;:91::i;:::-;9551:123;;9702:8;9684:15;:26;9680:84;;;9727:30;;-1:-1:-1::0;;;9727:30:20::3;;;;;;;;;;;9680:84;9792:108;9807:14;9823:8;:15;;;9840;9857:9;:16;;;9875:14;9891:8;;9792:14;:108::i;:::-;9770:130;;9926:11;9910:13;:27;9906:92;;;9954:37;;-1:-1:-1::0;;;9954:37:20::3;;;;;;;;;;;9906:92;10021:35;10026:14;10042:13;10021:4;:35::i;:::-;10004:52;;10080:37;10085:15;10102:14;10080:4;:37::i;:::-;10062:55;;10141:91;10155:14;10171:8;:15;;;10188;10205:9;:16;;;10223:8;;10141:13;:91::i;:::-;10124:108;;10259:15;10242:14;:32;10238:102;;;10291:42;;-1:-1:-1::0;;;10291:42:20::3;;;;;;;;;;;10238:102;10366:8;10349:14;:25;10345:83;;;10391:30;;-1:-1:-1::0;;;10391:30:20::3;;;;;;;;;;;10345:83;10455:35;10460:13;10475:14;10455:4;:35::i;:::-;10437:15;:53;10433:119;;;10507:38;;-1:-1:-1::0;;;10507:38:20::3;;;;;;;;;;;10433:119;10563:70;::::0;;8131:25:27;;;8187:2;8172:18;;8165:34;;;-1:-1:-1;;;;;10563:70:20;;::::3;::::0;;;::::3;::::0;10572:10:::3;::::0;10563:70:::3;::::0;8104:18:27;10563:70:20::3;;;;;;;10640:51;10656:7;10665:10;10677:13;10640:15;:51::i;:::-;10697:53;10713:8;10723:10;10735:14;10697:15;:53::i;:::-;9003:1752;;;;;1377:21:::1;2546:1:17;2530:19:::0;::::1;1377:8:20;:21::i;:::-;8762:1993:::0;;;;;;;;:::o;6744:1989::-;1134:39;;6937:22;;;;1152:10;;-1:-1:-1;;;;;;1143:7:20;;;;1134:39;;6937:22;;1164:8;;1134:39;:::i;:::-;;;;;;;;-1:-1:-1;;;;;;;;;;;16490:36:20;1270:25;1266:71:::1;;1312:18;;-1:-1:-1::0;;;1312:18:20::1;;;;;;;;;;;1266:71;1342:22;2676:1:17;1342:8:20;:22::i;:::-;1689:10:::2;::::0;::::2;;1684:63;;1716:24;;-1:-1:-1::0;;;1716:24:20::2;;;;;;;;;;;1684:63;-1:-1:-1::0;;;;;6996:17:20;::::3;;::::0;;;:8:::3;:17;::::0;;;;:23;::::3;;6991:73;;7036:21;;-1:-1:-1::0;;;7036:21:20::3;;;;;;;;;;;6991:73;-1:-1:-1::0;;;;;7074:18:20;::::3;;::::0;;;:8:::3;:18;::::0;;;;:24;::::3;;7069:74;;7115:21;;-1:-1:-1::0;;;7115:21:20::3;;;;;;;;;;;7069:74;-1:-1:-1::0;;;;;7175:26:20;;::::3;7149:23;7175:26:::0;;;:8:::3;:26;::::0;;;;;7234:27;;::::3;::::0;;;;;7293:40;;-1:-1:-1;;;7293:40:20;;7327:4:::3;7293:40;::::0;::::3;4141:74:27::0;7234:27:20;;7175:26;7293:25:::3;::::0;4114:18:27;;7293:40:20::3;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;7365:41;::::0;-1:-1:-1;;;7365:41:20;;7400:4:::3;7365:41;::::0;::::3;4141:74:27::0;7268:65:20;;-1:-1:-1;7339:23:20::3;::::0;-1:-1:-1;;;;;7365:26:20;::::3;::::0;::::3;::::0;4114:18:27;;7365:41:20::3;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;7339:67:::0;-1:-1:-1;7433:34:20::3;7438:14:::0;1855:9:17;7433:4:20::3;:34::i;:::-;7417:13;:50;7413:112;;;7484:34;;-1:-1:-1::0;;;7484:34:20::3;;;;;;;;;;;7413:112;7531:23;7563:91;7577:14;7593:8;:15;;;7610;7627:9;:16;;;7645:8;;7563:13;:91::i;:::-;7531:123;;7682:8;7664:15;:26;7660:84;;;7707:30;;-1:-1:-1::0;;;7707:30:20::3;;;;;;;;;;;7660:84;7773:107;7788:14;7804:8;:15;;;7821;7838:9;:16;;;7856:13;7871:8;;7773:14;:107::i;:::-;7750:130;;7907:12;7890:14;:29;7886:90;;;7936:33;;-1:-1:-1::0;;;7936:33:20::3;;;;;;;;;;;7886:90;7999:35;8004:14;8020:13;7999:4;:35::i;:::-;7982:52;;8058:37;8063:15;8080:14;8058:4;:37::i;:::-;8040:55;;8119:91;8133:14;8149:8;:15;;;8166;8183:9;:16;;;8201:8;;8119:13;:91::i;:::-;8102:108;;8237:15;8220:14;:32;8216:102;;;8269:42;;-1:-1:-1::0;;;8269:42:20::3;;;;;;;;;;;8216:102;8344:8;8327:14;:25;8323:83;;;8369:30;;-1:-1:-1::0;;;8369:30:20::3;;;;;;;;;;;8323:83;8433:35;8438:13;8453:14;8433:4;:35::i;:::-;8415:15;:53;8411:119;;;8485:38;;-1:-1:-1::0;;;8485:38:20::3;;;;;;;;;;;8411:119;8541:70;::::0;;8131:25:27;;;8187:2;8172:18;;8165:34;;;-1:-1:-1;;;;;8541:70:20;;::::3;::::0;;;::::3;::::0;8550:10:::3;::::0;8541:70:::3;::::0;8104:18:27;8541:70:20::3;;;;;;;8618:51;8634:7;8643:10;8655:13;8618:15;:51::i;:::-;8675:53;8691:8;8701:10;8713:14;8675:15;:53::i;1184::17:-:0;1222:15;1229:8;270;1222:15;:::i;2665:200:20:-;1152:10;-1:-1:-1;;;;;1134:39:20;1143:7;;-1:-1:-1;;;;;;1143:7:20;-1:-1:-1;;;;;1134:39:20;;1164:8;;1134:39;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;;;;;;;;;;;16490:36:20;1270:25;1266:71:::1;;1312:18;;-1:-1:-1::0;;;1312:18:20::1;;;;;;;;;;;1266:71;1342:22;2676:1:17;1342:8:20;:22::i;:::-;2035:11:::2;::::0;-1:-1:-1;;;;;2035:11:20::2;2021:10;:25;2017:82;;2063:29;;-1:-1:-1::0;;;2063:29:20::2;;;;;;;;;;;2017:82;-1:-1:-1::0;;;;;2757:27:20;::::3;2753:74;;2801:19;;-1:-1:-1::0;;;2801:19:20::3;;;;;;;;;;;2753:74;2833:11;:27:::0;;-1:-1:-1;;;;;;2833:27:20::3;-1:-1:-1::0;;;;;2833:27:20;::::3;;::::0;;1377:21:::1;-1:-1:-1::0;1377:8:20::1;:21::i;12819:111::-:0;12891:7;-1:-1:-1;;;;;;;;;;;16490:36:20;1521:25;1517:71;;1563:18;;-1:-1:-1;;;1563:18:20;;;;;;;;;;;1517:71;-1:-1:-1;12913:12:20::1;::::0;12819:111;:::o;1330:53:17:-;1373:10;270:8;1380:3;1373:10;:::i;12585:205:20:-;12665:7;-1:-1:-1;;;;;;;;;;;16490:36:20;1521:25;1517:71;;1563:18;;-1:-1:-1;;;1563:18:20;;;;;;;;;;;1517:71;-1:-1:-1;;;;;12685:15:20;::::1;;::::0;;;:8:::1;:15;::::0;;;;:21;::::1;;12680:71;;12723:21;;-1:-1:-1::0;;;12723:21:20::1;;;;;;;;;;;12680:71;-1:-1:-1::0;;;;;;12763:15:20;::::1;;::::0;;;:8:::1;:15;::::0;;;;:22:::1;;::::0;1593:1:::1;12585:205:::0;;;:::o;2276:93:8:-;2323:13;2355:7;2348:14;;;;;:::i;1946:58:17:-;1987:8;1994:1;270:8;1987;:::i;:::-;1986:18;;1999:5;1986:18;:::i;1280:459:18:-;1461:17;1486:13;1502:35;1507:14;1523:13;1502:4;:35::i;:::-;1486:51;;1543:13;1559:37;1564:15;1581:14;1559:4;:37::i;:::-;1543:53;;1602:13;1618:18;1623:5;1630;1618:4;:18::i;:::-;1602:34;;1642:13;1658:31;270:8:17;1669:19:18;270:8:17;1680:7:18;1669:4;:19::i;:::-;1658:4;:31::i;:::-;1642:47;;1715:18;1720:5;1727;1715:4;:18::i;:::-;1703:30;1280:459;-1:-1:-1;;;;;;;;;;1280:459:18:o;3610:178:8:-;3679:4;735:10:14;3733:27:8;735:10:14;3750:2:8;3754:5;3733:9;:27::i;5670:1045:20:-;1152:10;-1:-1:-1;;;;;1134:39:20;1143:7;;-1:-1:-1;;;;;;1143:7:20;-1:-1:-1;;;;;1134:39:20;;1164:8;;1134:39;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;;;;;;;;;;;16490:36:20;1270:25;1266:71:::1;;1312:18;;-1:-1:-1::0;;;1312:18:20::1;;;;;;;;;;;1266:71;1342:22;2676:1:17;1342:8:20;:22::i;:::-;1689:10:::2;::::0;::::2;;1684:63;;1716:24;;-1:-1:-1::0;;;1716:24:20::2;;;;;;;;;;;1684:63;5785:17:::3;5805:13;3222:12:8::0;;;3144:97;5805:13:20::3;5785:33;;5824:15;5842:28;5847:12;791:1:17;5842:4:20;:28::i;:::-;5824:46;;5876:23;5902:27;5907:12;5921:7;5902:4;:27::i;:::-;5876:53;;5935:13;5951:32;5956:15;5973:9;5951:4;:32::i;:::-;5935:48;;5993:5;6002:1;5993:10:::0;5989:62:::3;;6020:24;;-1:-1:-1::0;;;6020:24:20::3;;;;;;;;;;;5989:62;6057:40;6072:10;6084:12;6057:14;:40::i;:::-;6103:32;6118:7;6127;6103:14;:32::i;:::-;6141:31;6156:15;6141:14;:31::i;:::-;6202:7;:14:::0;6179:20:::3;6222:489;6246:12;6242:1;:16;6222:489;;;6273:9;6285:7;6293:1;6285:10;;;;;;;;:::i;:::-;;::::0;;;::::3;::::0;;::::3;::::0;6317:34:::3;::::0;-1:-1:-1;;;6317:34:20;;6345:4:::3;6317:34;::::0;::::3;4141:74:27::0;-1:-1:-1;;;;;6285:10:20;;::::3;::::0;-1:-1:-1;6285:10:20;;6317:19:::3;::::0;4114:18:27;;6317:34:20::3;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;6303:48;;6359:22;6384:16;6389:5;6396:3;6384:4;:16::i;:::-;6359:41;;6412:14;6430:1;6412:19:::0;6408:80:::3;;6450:29;;-1:-1:-1::0;;;6450:29:20::3;;;;;;;;;;;6408:80;6516:13;;6530:1;6516:16;;;;;;;:::i;:::-;;;;;;;6499:14;:33;6495:104;;;6551:39;;-1:-1:-1::0;;;6551:39:20::3;;;;;;;;;;;6495:104;6611:39;::::0;1393:25:27;;;-1:-1:-1;;;;;6611:39:20;::::3;::::0;6620:10:::3;::::0;6611:39:::3;::::0;1381:2:27;1366:18;6611:39:20::3;;;;;;;6658:46;6674:1;6677:10;6689:14;6658:15;:46::i;:::-;-1:-1:-1::0;;;6260:3:20::3;;6222:489;;;;5779:936;;;;;1377:21:::1;2546:1:17;2530:19:::0;::::1;1377:8:20;:21::i;2699:620:18:-:0;2908:22;2938:19;2960:35;2965:13;2980:14;2960:4;:35::i;:::-;2938:57;;3001:18;3022:19;270:8:17;3033:7:18;3022:4;:19::i;:::-;3001:40;;3060:31;3065:13;3080:10;3060:4;:31::i;:::-;3047:44;;3097:9;3109:54;3114:14;3130:32;3135:14;3151:10;3130:4;:32::i;3109:54::-;3097:66;;3169:11;3183:20;3188:1;3191:11;3183:4;:20::i;:::-;3169:34;;3209:11;3223:15;270:8:17;3234:3:18;3223:4;:15::i;:::-;3209:29;;3261:26;3266:15;3283:3;3261:4;:26::i;:::-;3244:43;2699:620;-1:-1:-1;;;;;;;;;;;;2699:620:18:o;656:48:17:-;586:14;593:7;270:8;586:14;:::i;:::-;690;;270:8;690:14;:::i;1563:58::-;1616:5;1604:8;270;1604:1;:8;:::i;:::-;1603:18;;;;:::i;12441:115:20:-;12513:16;-1:-1:-1;;;;;;;;;;;16490:36:20;1521:25;1517:71;;1563:18;;-1:-1:-1;;;1563:18:20;;;;;;;;;;;1517:71;1689:10:::1;::::0;::::1;;1684:63;;1716:24;;-1:-1:-1::0;;;1716:24:20::1;;;;;;;;;;;1684:63;12544:7:::2;12537:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;;-1:-1:-1;;;;;12537:14:20::2;::::0;;;;;::::2;::::0;::::2;;::::0;;::::2;;;;;;;;;;12441:115:::0;:::o;12307:105::-;12369:16;-1:-1:-1;;;;;;;;;;;16490:36:20;1521:25;1517:71;;1563:18;;-1:-1:-1;;;1563:18:20;;;;;;;;;;;4085:644;1152:10;-1:-1:-1;;;;;1134:39:20;1143:7;;-1:-1:-1;;;;;;1143:7:20;-1:-1:-1;;;;;1134:39:20;;1164:8;;1134:39;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;;;;;;;;;;;16490:36:20;1270:25;1266:71:::1;;1312:18;;-1:-1:-1::0;;;1312:18:20::1;;;;;;;;;;;1266:71;1342:22;2676:1:17;1342:8:20;:22::i;:::-;2035:11:::2;::::0;-1:-1:-1;;;;;2035:11:20::2;2021:10;:25;2017:82;;2063:29;;-1:-1:-1::0;;;2063:29:20::2;;;;;;;;;;;2017:82;1846:10:::3;::::0;::::3;;1842:61;;;1873:23;;-1:-1:-1::0;;;1873:23:20::3;;;;;;;;;;;1842:61;-1:-1:-1::0;;;;;4178:15:20;::::4;;::::0;;;:8:::4;:15;::::0;;;;:21;::::4;;4173:71;;4216:21;;-1:-1:-1::0;;;4216:21:20::4;;;;;;;;;;;4173:71;4270:12;::::0;-1:-1:-1;;;;;4284:15:20;::::4;;::::0;;;:8:::4;:15;::::0;;;;:22:::4;;::::0;4265:42:::4;::::0;4270:12;4265:4:::4;:42::i;:::-;4250:12;:57:::0;-1:-1:-1;;;;;4417:15:20;::::4;4401:13;4417:15:::0;;;:8:::4;:15;::::0;;;;:21:::4;::::0;;::::4;::::0;4459:7:::4;:14:::0;4417:21;;4401:13;4459:18:::4;::::0;::::4;:::i;:::-;4444:33;;4500:7;4508:4;4500:13;;;;;;;;:::i;:::-;;::::0;;;::::4;::::0;;;::::4;::::0;4483:7:::4;:14:::0;;-1:-1:-1;;;;;4500:13:20;;::::4;::::0;4491:5;;4483:14;::::4;;;;;:::i;:::-;;;;;;;;;:30;;;;;-1:-1:-1::0;;;;;4483:30:20::4;;;;;-1:-1:-1::0;;;;;4483:30:20::4;;;;;;4552:5;4519:8;:24;4528:7;4536:5;4528:14;;;;;;;;:::i;:::-;;::::0;;;::::4;::::0;;;;;::::4;::::0;-1:-1:-1;;;;;4528:14:20::4;4519:24:::0;;;::::4;::::0;;;;;;;;4528:14;4519:30:::4;:38:::0;4563:7:::4;:13:::0;;;::::4;;;;:::i;:::-;;::::0;;;::::4;::::0;;;-1:-1:-1;;4563:13:20;;;;;;;-1:-1:-1;;;;;;4563:13:20::4;::::0;;;;;;;;4600:43:::4;::::0;;::::4;::::0;::::4;::::0;;;;;;;::::4;::::0;;;;;;;;;-1:-1:-1;;;;;4582:15:20;::::4;::::0;;;:8:::4;:15:::0;;;;;;;:61;;;;-1:-1:-1;;4582:61:20::4;::::0;::::4;;;::::0;;;-1:-1:-1;4582:61:20;::::4;::::0;;;::::4;::::0;;::::4;::::0;;;;4685:38;;-1:-1:-1;;;4685:38:20;;4717:4:::4;4685:38;::::0;::::4;4141:74:27::0;4650::20::4;::::0;4582:15;;4673:10:::4;::::0;4582:15;4685:23:::4;::::0;4114:18:27;;4685:38:20::4;;;;;;;;;;;;;;;;;::::0;::::4;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;4650:15;:74::i;:::-;-1:-1:-1::0;1377:21:20::1;::::0;-1:-1:-1;2546:1:17::1;1377:8:20;:21::i;13479:91::-:0;13535:7;-1:-1:-1;;;;;;;;;;;16490:36:20;1521:25;1517:71;;1563:18;;-1:-1:-1;;;1563:18:20;;;;;;;;;;;1517:71;-1:-1:-1;13557:8:20::1;::::0;13479:91;:::o;603:192:21:-;709:10;680:12;3952:18:8;;;:11;:18;;;;;;;;-1:-1:-1;;;;;3952:27:8;;;;;;;;;;680:12:21;;700:70;;3952:27:8;;730:39:21;;763:6;;730:39;:::i;700:70::-;-1:-1:-1;786:4:21;;603:192;-1:-1:-1;;603:192:21:o;3226:830:20:-;1152:10;-1:-1:-1;;;;;1134:39:20;1143:7;;-1:-1:-1;;;;;;1143:7:20;-1:-1:-1;;;;;1134:39:20;;1164:8;;1134:39;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;;;;;;;;;;;16490:36:20;1270:25;1266:71:::1;;1312:18;;-1:-1:-1::0;;;1312:18:20::1;;;;;;;;;;;1266:71;1342:22;2676:1:17;1342:8:20;:22::i;:::-;2035:11:::2;::::0;-1:-1:-1;;;;;2035:11:20::2;2021:10;:25;2017:82;;2063:29;;-1:-1:-1::0;;;2063:29:20::2;;;;;;;;;;;2017:82;1846:10:::3;::::0;::::3;;1842:61;;;1873:23;;-1:-1:-1::0;;;1873:23:20::3;;;;;;;;;;;1842:61;-1:-1:-1::0;;;;;3349:15:20;::::4;;::::0;;;:8:::4;:15;::::0;;;;:21;::::4;;3345:74;;;3387:25;;-1:-1:-1::0;;;3387:25:20::4;;;;;;;;;;;3345:74;494:1:17;3428:14:20::0;;:34:::4;3424:88;;3479:26;;-1:-1:-1::0;;;3479:26:20::4;;;;;;;;;;;3424:88;270:8:17;3521:6:20;:19;3517:73;;;3557:26;;-1:-1:-1::0;;;3557:26:20::4;;;;;;;;;;;3517:73;991:9:17;270:8;998:2;991:9;:::i;:::-;3599:6:20;:19;3595:73;;;3635:26;;-1:-1:-1::0;;;3635:26:20::4;;;;;;;;;;;3595:73;1222:15:17;1229:8;270;1222:15;:::i;:::-;3677:7:20;:21;3673:76;;;3715:27;;-1:-1:-1::0;;;3715:27:20::4;;;;;;;;;;;3673:76;3770:26;3775:12;;3789:6;3770:4;:26::i;:::-;3755:12;:41:::0;1113:9:17::4;270:8;1120:2;1113:9;:::i;:::-;3806:12:20;;:31;3802:90;;;3854:31;;-1:-1:-1::0;;;3854:31:20::4;;;;;;;;;;;3802:90;3916:60;::::0;;::::4;::::0;::::4;::::0;;3931:4:::4;3916:60:::0;;;3944:7:::4;:14:::0;;3916:60:::4;::::0;;::::4;::::0;;;;;;;;;-1:-1:-1;;;;;3898:15:20;::::4;-1:-1:-1::0;3898:15:20;;;:8:::4;:15:::0;;;;;;:78;;;;-1:-1:-1;;3898:78:20::4;::::0;::::4;;;::::0;;;;;;::::4;::::0;;;::::4;::::0;;::::4;::::0;;;;3982:19;;;;::::4;::::0;;;;;;::::4;::::0;;-1:-1:-1;;;;;;3982:19:20::4;::::0;;::::4;::::0;;4008:43:::4;3898:15:::0;4031:10:::4;4043:7:::0;4008:15:::4;:43::i;:::-;1377:21:::1;2546:1:17;1377:8:20;:21::i;3419:184:16:-:0;-1:-1:-1;;;;;;;;;;;16490:36:20;1521:25;1517:71;;1563:18;;-1:-1:-1;;;1563:18:20;;;;;;;;;;;1517:71;3484:10:16::1;-1:-1:-1::0;;;;;3506:16:16::1;3484:39;;3480:94;;3540:27;;-1:-1:-1::0;;;3540:27:16::1;;;;;;;;;;;3480:94;3579:19;3588:9;3579:8;:19::i;12959:252:20:-:0;13037:7;-1:-1:-1;;;;;;;;;;;16490:36:20;1521:25;1517:71;;1563:18;;-1:-1:-1;;;1563:18:20;;;;;;;;;;;1517:71;-1:-1:-1;;;;;13057:15:20;::::1;;::::0;;;:8:::1;:15;::::0;;;;:21;::::1;;13052:71;;13095:21;;-1:-1:-1::0;;;13095:21:20::1;;;;;;;;;;;13052:71;-1:-1:-1::0;;;;;13145:15:20;::::1;13128:14;13145:15:::0;;;:8:::1;:15;::::0;;;;:22:::1;;::::0;13193:12:::1;::::0;13180:26:::1;::::0;13145:22;;13180:4:::1;:26::i;13240:210::-:0;13309:7;-1:-1:-1;;;;;;;;;;;16490:36:20;1521:25;1517:71;;1563:18;;-1:-1:-1;;;1563:18:20;;;;;;;;;;;1517:71;-1:-1:-1;;;;;13329:15:20;::::1;;::::0;;;:8:::1;:15;::::0;;;;:21;::::1;;13324:71;;13367:21;;-1:-1:-1::0;;;13367:21:20::1;;;;;;;;;;;13324:71;13407:38;::::0;-1:-1:-1;;;13407:38:20;;13439:4:::1;13407:38;::::0;::::1;4141:74:27::0;-1:-1:-1;;;;;13407:23:20;::::1;::::0;::::1;::::0;4114:18:27;;13407:38:20::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;4335:606:18:-:0;4545:21;4574:19;4596:35;4601:14;4617:13;4596:4;:35::i;:::-;4574:57;;4637:12;4652:37;4657:15;4674:14;4652:4;:37::i;:::-;4637:52;;4695:9;4707:27;4712:15;4729:4;4707;:27::i;:::-;4695:39;;4740:11;4754:20;4759:1;4762:11;4754:4;:20::i;:::-;4740:34;;4786:15;4791:3;270:8:17;4786:4:18;:15::i;:::-;4780:21;;4823:19;270:8:17;4834:7:18;4823:4;:19::i;:::-;4807:35;;4864:46;4869:25;4874:14;4890:3;4869:4;:25::i;:::-;4896:13;4864:4;:46::i;:::-;4848:62;4335:606;-1:-1:-1;;;;;;;;;;;4335:606:18:o;8989:128:8:-;9073:37;9082:5;9089:7;9098:5;9105:4;9073:8;:37::i;10663:477::-;-1:-1:-1;;;;;3952:18:8;;;10762:24;3952:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;-1:-1:-1;;10828:37:8;;10824:310;;10904:5;10885:16;:24;10881:130;;;10936:60;;-1:-1:-1;;;10936:60:8;;-1:-1:-1;;;;;14864:55:27;;10936:60:8;;;14846:74:27;14936:18;;;14929:34;;;14979:18;;;14972:34;;;14819:18;;10936:60:8;;;;;;;;10881:130;11052:57;11061:5;11068:7;11096:5;11077:16;:24;11103:5;11052:8;:57::i;:::-;10752:388;10663:477;;;:::o;5656:300::-;-1:-1:-1;;;;;5739:18:8;;5735:86;;5780:30;;-1:-1:-1;;;5780:30:8;;5807:1;5780:30;;;4141:74:27;4114:18;;5780:30:8;3995:226:27;5735:86:8;-1:-1:-1;;;;;5834:16:8;;5830:86;;5873:32;;-1:-1:-1;;;5873:32:8;;5902:1;5873:32;;;4141:74:27;4114:18;;5873:32:8;3995:226:27;5830:86:8;5925:24;5933:4;5939:2;5943:5;5925:7;:24::i;2053:388:19:-;2112:7;2158:5;;;2175:6;;;;;:21;;;2195:1;2190;2185:2;:6;;;;;:::i;:::-;;:11;;2175:21;2171:71;;;2215:18;;-1:-1:-1;;;2215:18:19;;;;;;;;;;;2171:71;2309:9;2303:16;;2331:7;;;2327:57;;;2357:18;;-1:-1:-1;;;2357:18:19;;;;;;;;;;;2327:57;2391:10;270:8:17;2404:2:19;:9;;;2053:388;-1:-1:-1;;;;;;2053:388:19:o;13985:143:20:-;14112:5;-1:-1:-1;;;;;;;;;;;14074:44:20;13985:143;:::o;15798:96::-;15861:28;15875:4;15882:6;15861:5;:28::i;15590:97::-;15665:17;15671:2;15675:6;15665:5;:17::i;:::-;15590:97;;:::o;6127:625:16:-;6208:7;:14;6185:20;6228:119;6248:12;6244:1;:16;6228:119;;;6275:65;6307:13;-1:-1:-1;;6282:7:16;6290:1;6282:10;;;;;;;;:::i;:::-;;;;;;;;;;;-1:-1:-1;;;;;6282:10:16;;6275:65;:31;:65::i;:::-;6262:3;;6228:119;;;;6647:7;-1:-1:-1;;;;;6634:33:16;;:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6630:118;;6696:45;;6735:4;;6696:45;;;;;2373:263:20;:::o;2445:481:19:-;2504:7;2541:1;2546;2541:6;2537:52;;2566:14;;-1:-1:-1;;;2566:14:19;;;;;;;;;;;2537:52;270:8:17;2609::19;;2629:6;;;;;:24;;;270:8:17;2644:1:19;2639:2;:6;;;;;:::i;:::-;;:14;;2629:24;2625:91;;;2672:18;;-1:-1:-1;;;2672:18:19;;;;;;;;;;;2625:91;2788:1;2783:6;;;2777:13;;2802:7;;;2798:74;;;2828:18;;-1:-1:-1;;;2828:18:19;;;;;;;;;;;2798:74;2879:10;2897:1;2892:2;:6;;;;;:::i;14393:157:20:-;14486:59;-1:-1:-1;;;;;14486:30:20;;14517:4;14531;14538:6;14486:30;:59::i;1414:198:19:-;1473:7;1518:5;;;1535;;;1531:55;;;1559:18;;-1:-1:-1;;;1559:18:19;;;;;;;;;;;1616:220;1675:7;1709:9;1720;1733:14;1742:1;1745;1733:8;:14::i;:::-;1708:39;;;;1759:4;1755:55;;;1782:19;;-1:-1:-1;;;1782:19:19;;;;;;;;;;;1755:55;-1:-1:-1;1824:1:19;1616:220;-1:-1:-1;;;1616:220:19:o;14777:134:20:-;14868:38;-1:-1:-1;;;;;14868:26:20;;14895:2;14899:6;14868:26;:38::i;15320:101::-;15397:19;15403:4;15409:6;15397:5;:19::i;16005:96::-;16068:28;16082:4;16089:6;16068:5;:28::i;3381:566:19:-;3445:7;1491:5:17;3482:4:19;:20;3478:73;;;3521:21;;-1:-1:-1;;;3521:21:19;;;;;;;;;;;3478:73;1603:18:17;3562:20:19;;3558:74;;;3601:22;;-1:-1:-1;;;3601:22:19;;;;;;;;;;;3558:74;270:8:17;1272::19;;;1385:14;3640:13;3692:16;1272:8;1385:14;3692:4;:16::i;:::-;3675:33;-1:-1:-1;3717:16:19;3736:24;3742:4;270:8:17;1272::19;;3736:5;:24::i;:::-;3717:43;;3773:6;3783:1;3773:11;3769:51;;3803:8;-1:-1:-1;3796:15:19;;-1:-1:-1;;3796:15:19;3769:51;3828:21;3852:40;3863:4;3869:6;1719:15:17;3852:10:19;:40::i;:::-;3828:64;;3907:29;3912:8;3922:13;3907:4;:29::i;:::-;3900:36;3381:566;-1:-1:-1;;;;;;;3381:566:19:o;9949:432:8:-;-1:-1:-1;;;;;10061:19:8;;10057:89;;10103:32;;-1:-1:-1;;;10103:32:8;;10132:1;10103:32;;;4141:74:27;4114:18;;10103:32:8;3995:226:27;10057:89:8;-1:-1:-1;;;;;10159:21:8;;10155:90;;10203:31;;-1:-1:-1;;;10203:31:8;;10231:1;10203:31;;;4141:74:27;4114:18;;10203:31:8;3995:226:27;10155:90:8;-1:-1:-1;;;;;10254:18:8;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;:35;;;10299:76;;;;10349:7;-1:-1:-1;;;;;10333:31:8;10342:5;-1:-1:-1;;;;;10333:31:8;;10358:5;10333:31;;;;1393:25:27;;1381:2;1366:18;;1247:177;10333:31:8;;;;;;;;9949:432;;;;:::o;6271:1107::-;-1:-1:-1;;;;;6360:18:8;;6356:540;;6512:5;6496:12;;:21;;;;;;;:::i;:::-;;;;-1:-1:-1;6356:540:8;;-1:-1:-1;6356:540:8;;-1:-1:-1;;;;;6570:15:8;;6548:19;6570:15;;;;;;;;;;;6603:19;;;6599:115;;;6649:50;;-1:-1:-1;;;6649:50:8;;-1:-1:-1;;;;;14864:55:27;;6649:50:8;;;14846:74:27;14936:18;;;14929:34;;;14979:18;;;14972:34;;;14819:18;;6649:50:8;14644:368:27;6599:115:8;-1:-1:-1;;;;;6834:15:8;;:9;:15;;;;;;;;;;6852:19;;;;6834:37;;6356:540;-1:-1:-1;;;;;6910:16:8;;6906:425;;7073:12;:21;;;;;;;6906:425;;;-1:-1:-1;;;;;7284:13:8;;:9;:13;;;;;;;;;;:22;;;;;;6906:425;7361:2;-1:-1:-1;;;;;7346:25:8;7355:4;-1:-1:-1;;;;;7346:25:8;;7365:5;7346:25;;;;1393::27;;1381:2;1366:18;;1247:177;7346:25:8;;;;;;;;6271:1107;;;:::o;7721:208::-;-1:-1:-1;;;;;7791:21:8;;7787:91;;7835:32;;-1:-1:-1;;;7835:32:8;;7864:1;7835:32;;;4141:74:27;4114:18;;7835:32:8;3995:226:27;7787:91:8;7887:35;7903:1;7907:7;7916:5;7887:7;:35::i;1563:107:21:-;1629:36;1647:4;1654:2;1658:6;1629:9;:36::i;3296:380:12:-;3411:47;;;-1:-1:-1;;;;;15209:55:27;;3411:47:12;;;15191:74:27;15281:18;;;;15274:34;;;3411:47:12;;;;;;;;;;15164:18:27;;;;3411:47:12;;;;;;;;-1:-1:-1;;;;;3411:47:12;-1:-1:-1;;;3411:47:12;;;3474:44;3426:13;3411:47;3474:23;:44::i;:::-;3469:201;;3561:43;;-1:-1:-1;;;;;15209:55:27;;;3561:43:12;;;15191:74:27;3601:1:12;15281:18:27;;;15274:34;3534:71:12;;3554:5;;3576:13;;;;;15164:18:27;;3561:43:12;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;3561:43:12;;;;;;;;;;;3534:19;:71::i;:::-;3619:40;3639:5;3646:12;3619:19;:40::i;1702:188::-;1829:53;;-1:-1:-1;;;;;15910:15:27;;;1829:53:12;;;15892:34:27;15962:15;;;15942:18;;;15935:43;15994:18;;;15987:34;;;1802:81:12;;1822:5;;1844:18;;;;;15804::27;;1829:53:12;15629:398:27;1840:209:19;1903:7;1912:4;1951:1;1946;:6;1942:97;;-1:-1:-1;;1972:5:19;;;1979;1964:21;;1942:97;-1:-1:-1;;2018:5:19;;;2025:4;1942:97;1840:209;;;;;:::o;1303:160:12:-;1412:43;;-1:-1:-1;;;;;15209:55:27;;;1412:43:12;;;15191:74:27;15281:18;;;15274:34;;;1385:71:12;;1405:5;;1427:14;;;;;15164:18:27;;1412:43:12;15017:297:27;1871:111:21;1939:38;1949:4;1963;1970:6;1939:9;:38::i;8247:206:8:-;-1:-1:-1;;;;;8317:21:8;;8313:89;;8361:30;;-1:-1:-1;;;8361:30:8;;8388:1;8361:30;;;4141:74:27;4114:18;;8361:30:8;3995:226:27;8313:89:8;8411:35;8419:7;8436:1;8440:5;8411:7;:35::i;2947:286:19:-;3007:7;;3056:1;3052;:5;3061:1;3052:10;:21;;270:8:17;3052:21:19;;;3065:1;3052:21;3040:33;-1:-1:-1;3092:1:19;3087:6;;;;3082:125;3095:6;;3082:125;;3125:10;3130:1;3133;3125:4;:10::i;:::-;3121:14;-1:-1:-1;3154:1:19;3150;:5;:10;3146:53;;3178:10;3183:1;3186;3178:4;:10::i;:::-;3174:14;;3146:53;3108:1;3103:6;;;;3082:125;;3951:993;4040:7;4102:3;4040:7;;4138:20;4147:4;270:8:17;4138::19;:20::i;:::-;4113:45;;-1:-1:-1;4113:45:19;-1:-1:-1;270:8:17;;4166:12:19;4482:1;4465:450;4493:9;4485:4;:17;4465:450;;4519:12;270:8:17;4534:1:19;:8;4519:23;;4553:9;4564;4577:29;4586:1;4589:16;4594:4;270:8:17;4589:4:19;:16::i;:::-;4577:8;:29::i;:::-;4552:54;;;;4623:22;4628:4;4634:10;4639:1;4642;4634:4;:10::i;4623:22::-;4616:29;;4662:16;4667:4;4673;4662;:16::i;:::-;4655:23;;4692:4;4700:1;4692:9;4688:20;;4703:5;;;;;4688:20;4723:4;4719:30;;;4740:9;;;4719:30;4763:4;4759:30;;;4780:9;;;4759:30;4803:8;4799:108;;;4831:15;4836:3;4841:4;4831;:15::i;:::-;4825:21;;4799:108;;;4881:15;4886:3;4891:4;4881;:15::i;:::-;4875:21;;4799:108;-1:-1:-1;;;4504:3:19;;4465:450;;;-1:-1:-1;4930:3:19;;3951:993;-1:-1:-1;;;;;;;;;3951:993:19:o;5189:578:12:-;5272:4;5574:12;5588:23;5623:5;-1:-1:-1;;;;;5615:19:12;5635:4;5615:25;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5573:67;;;;5657:7;:69;;;;-1:-1:-1;5669:17:12;;:22;;:56;;;5706:10;5695:30;;;;;;;;;;;;:::i;:::-;5657:103;;;;-1:-1:-1;;;;;;;;;;5730:26:12;;:30;;;5189:578::o;4059:629::-;4478:23;4504:33;-1:-1:-1;;;;;4504:27:12;;4532:4;4504:27;:33::i;:::-;4478:59;;4551:10;:17;4572:1;4551:22;;:57;;;;;4589:10;4578:30;;;;;;;;;;;;:::i;:::-;4577:31;4551:57;4547:135;;;4631:40;;-1:-1:-1;;;4631:40:12;;-1:-1:-1;;;;;4159:55:27;;4631:40:12;;;4141:74:27;4114:18;;4631:40:12;3995:226:27;2705:151:13;2780:12;2811:38;2833:6;2841:4;2847:1;2780:12;3421;3435:23;3462:6;-1:-1:-1;;;;;3462:11:13;3481:5;3488:4;3462:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3420:73;;;;3510:55;3537:6;3545:7;3554:10;3510:26;:55::i;:::-;3503:62;3180:392;-1:-1:-1;;;;;;3180:392:13:o;4625:582::-;4769:12;4798:7;4793:408;;4821:19;4829:10;4821:7;:19::i;:::-;4793:408;;;5045:17;;:22;:49;;;;-1:-1:-1;;;;;;5071:18:13;;;:23;5045:49;5041:119;;;5121:24;;-1:-1:-1;;;5121:24:13;;-1:-1:-1;;;;;4159:55:27;;5121:24:13;;;4141:74:27;4114:18;;5121:24:13;3995:226:27;5041:119:13;-1:-1:-1;5180:10:13;5173:17;;5743:516;5874:17;;:21;5870:383;;6102:10;6096:17;6158:15;6145:10;6141:2;6137:19;6130:44;5870:383;6225:17;;-1:-1:-1;;;6225:17:13;;;;;;;;;;;14:418:27;163:2;152:9;145:21;126:4;195:6;189:13;238:6;233:2;222:9;218:18;211:34;297:6;292:2;284:6;280:15;275:2;264:9;260:18;254:50;353:1;348:2;339:6;328:9;324:22;320:31;313:42;423:2;416;412:7;407:2;399:6;395:15;391:29;380:9;376:45;372:54;364:62;;;14:418;;;;:::o;437:154::-;-1:-1:-1;;;;;516:5:27;512:54;505:5;502:65;492:93;;581:1;578;571:12;596:134;664:20;;693:31;664:20;693:31;:::i;735:315::-;803:6;811;864:2;852:9;843:7;839:23;835:32;832:52;;;880:1;877;870:12;832:52;919:9;906:23;938:31;963:5;938:31;:::i;:::-;988:5;1040:2;1025:18;;;;1012:32;;-1:-1:-1;;;735:315:27:o;1429:388::-;1497:6;1505;1558:2;1546:9;1537:7;1533:23;1529:32;1526:52;;;1574:1;1571;1564:12;1526:52;1613:9;1600:23;1632:31;1657:5;1632:31;:::i;:::-;1682:5;-1:-1:-1;1739:2:27;1724:18;;1711:32;1752:33;1711:32;1752:33;:::i;:::-;1804:7;1794:17;;;1429:388;;;;;:::o;1822:127::-;1883:10;1878:3;1874:20;1871:1;1864:31;1914:4;1911:1;1904:15;1938:4;1935:1;1928:15;1954:252;2026:2;2020:9;2068:3;2056:16;;2102:18;2087:34;;2123:22;;;2084:62;2081:88;;;2149:18;;:::i;:::-;2185:2;2178:22;1954:252;:::o;2211:275::-;2282:2;2276:9;2347:2;2328:13;;-1:-1:-1;;2324:27:27;2312:40;;2382:18;2367:34;;2403:22;;;2364:62;2361:88;;;2429:18;;:::i;:::-;2465:2;2458:22;2211:275;;-1:-1:-1;2211:275:27:o;2491:831::-;2568:6;2576;2629:2;2617:9;2608:7;2604:23;2600:32;2597:52;;;2645:1;2642;2635:12;2597:52;2681:9;2668:23;2658:33;;2710:2;2763;2752:9;2748:18;2735:32;2786:18;2827:2;2819:6;2816:14;2813:34;;;2843:1;2840;2833:12;2813:34;2881:6;2870:9;2866:22;2856:32;;2926:7;2919:4;2915:2;2911:13;2907:27;2897:55;;2948:1;2945;2938:12;2897:55;2984:2;2971:16;3006:2;3002;2999:10;2996:36;;;3012:18;;:::i;:::-;3054:53;3097:2;3078:13;;-1:-1:-1;;3074:27:27;3070:36;;3054:53;:::i;:::-;3041:66;;3130:2;3123:5;3116:17;3170:7;3165:2;3160;3156;3152:11;3148:20;3145:33;3142:53;;;3191:1;3188;3181:12;3142:53;3246:2;3241;3237;3233:11;3228:2;3221:5;3217:14;3204:45;3290:1;3285:2;3280;3273:5;3269:14;3265:23;3258:34;;3311:5;3301:15;;;;;2491:831;;;;;:::o;3534:456::-;3611:6;3619;3627;3680:2;3668:9;3659:7;3655:23;3651:32;3648:52;;;3696:1;3693;3686:12;3648:52;3735:9;3722:23;3754:31;3779:5;3754:31;:::i;:::-;3804:5;-1:-1:-1;3861:2:27;3846:18;;3833:32;3874:33;3833:32;3874:33;:::i;:::-;3534:456;;3926:7;;-1:-1:-1;;;3980:2:27;3965:18;;;;3952:32;;3534:456::o;4226:121::-;4311:10;4304:5;4300:22;4293:5;4290:33;4280:61;;4337:1;4334;4327:12;4352:132;4419:20;;4448:30;4419:20;4448:30;:::i;4489:118::-;4575:5;4568:13;4561:21;4554:5;4551:32;4541:60;;4597:1;4594;4587:12;4612:128;4677:20;;4706:28;4677:20;4706:28;:::i;4745:1112::-;4825:6;4878:3;4866:9;4857:7;4853:23;4849:33;4846:53;;;4895:1;4892;4885:12;4846:53;4921:22;;:::i;:::-;4966:29;4985:9;4966:29;:::i;:::-;4959:5;4952:44;5028:38;5062:2;5051:9;5047:18;5028:38;:::i;:::-;5023:2;5016:5;5012:14;5005:62;5099:38;5133:2;5122:9;5118:18;5099:38;:::i;:::-;5094:2;5087:5;5083:14;5076:62;5198:2;5187:9;5183:18;5170:32;5165:2;5158:5;5154:14;5147:56;5264:3;5253:9;5249:19;5236:33;5230:3;5223:5;5219:15;5212:58;5303:38;5336:3;5325:9;5321:19;5303:38;:::i;:::-;5297:3;5290:5;5286:15;5279:63;5403:3;5392:9;5388:19;5375:33;5369:3;5362:5;5358:15;5351:58;5470:3;5459:9;5455:19;5442:33;5436:3;5429:5;5425:15;5418:58;5495:3;5558:2;5547:9;5543:18;5530:32;5525:2;5518:5;5514:14;5507:56;;5582:3;5617:35;5648:2;5637:9;5633:18;5617:35;:::i;:::-;5601:14;;;5594:59;5672:3;5720:18;;;5707:32;5691:14;;;5684:56;5759:3;5807:18;;;5794:32;5778:14;;;5771:56;;;;-1:-1:-1;5605:5:27;4745:1112;-1:-1:-1;4745:1112:27:o;5862:247::-;5921:6;5974:2;5962:9;5953:7;5949:23;5945:32;5942:52;;;5990:1;5987;5980:12;5942:52;6029:9;6016:23;6048:31;6073:5;6048:31;:::i;6303:180::-;6362:6;6415:2;6403:9;6394:7;6390:23;6386:32;6383:52;;;6431:1;6428;6421:12;6383:52;-1:-1:-1;6454:23:27;;6303:180;-1:-1:-1;6303:180:27:o;6488:683::-;6583:6;6591;6599;6652:2;6640:9;6631:7;6627:23;6623:32;6620:52;;;6668:1;6665;6658:12;6620:52;6704:9;6691:23;6681:33;;6765:2;6754:9;6750:18;6737:32;6788:18;6829:2;6821:6;6818:14;6815:34;;;6845:1;6842;6835:12;6815:34;6883:6;6872:9;6868:22;6858:32;;6928:7;6921:4;6917:2;6913:13;6909:27;6899:55;;6950:1;6947;6940:12;6899:55;6990:2;6977:16;7016:2;7008:6;7005:14;7002:34;;;7032:1;7029;7022:12;7002:34;7085:7;7080:2;7070:6;7067:1;7063:14;7059:2;7055:23;7051:32;7048:45;7045:65;;;7106:1;7103;7096:12;7045:65;7137:2;7133;7129:11;7119:21;;7159:6;7149:16;;;;;6488:683;;;;;:::o;7358:594::-;7453:6;7461;7469;7477;7485;7538:3;7526:9;7517:7;7513:23;7509:33;7506:53;;;7555:1;7552;7545:12;7506:53;7594:9;7581:23;7613:31;7638:5;7613:31;:::i;:::-;7663:5;-1:-1:-1;7715:2:27;7700:18;;7687:32;;-1:-1:-1;7771:2:27;7756:18;;7743:32;7784:33;7743:32;7784:33;:::i;:::-;7358:594;;;;-1:-1:-1;7836:7:27;;7890:2;7875:18;;7862:32;;-1:-1:-1;7941:3:27;7926:19;7913:33;;7358:594;-1:-1:-1;;7358:594:27:o;8658:454::-;8753:6;8761;8769;8777;8785;8838:3;8826:9;8817:7;8813:23;8809:33;8806:53;;;8855:1;8852;8845:12;8806:53;-1:-1:-1;;8878:23:27;;;8948:2;8933:18;;8920:32;;-1:-1:-1;8999:2:27;8984:18;;8971:32;;9050:2;9035:18;;9022:32;;-1:-1:-1;9101:3:27;9086:19;9073:33;;-1:-1:-1;8658:454:27;-1:-1:-1;8658:454:27:o;9117:523::-;9221:6;9229;9237;9245;9253;9261;9314:3;9302:9;9293:7;9289:23;9285:33;9282:53;;;9331:1;9328;9321:12;9282:53;-1:-1:-1;;9354:23:27;;;9424:2;9409:18;;9396:32;;-1:-1:-1;9475:2:27;9460:18;;9447:32;;9526:2;9511:18;;9498:32;;-1:-1:-1;9577:3:27;9562:19;;9549:33;;-1:-1:-1;9629:3:27;9614:19;9601:33;;-1:-1:-1;9117:523:27;-1:-1:-1;9117:523:27:o;9645:681::-;9816:2;9868:21;;;9938:13;;9841:18;;;9960:22;;;9787:4;;9816:2;10039:15;;;;10013:2;9998:18;;;9787:4;10082:218;10096:6;10093:1;10090:13;10082:218;;;10161:13;;-1:-1:-1;;;;;10157:62:27;10145:75;;10275:15;;;;10240:12;;;;10118:1;10111:9;10082:218;;;-1:-1:-1;10317:3:27;;9645:681;-1:-1:-1;;;;;;9645:681:27:o;10331:383::-;10408:6;10416;10424;10477:2;10465:9;10456:7;10452:23;10448:32;10445:52;;;10493:1;10490;10483:12;10445:52;10532:9;10519:23;10551:31;10576:5;10551:31;:::i;:::-;10601:5;10653:2;10638:18;;10625:32;;-1:-1:-1;10704:2:27;10689:18;;;10676:32;;10331:383;-1:-1:-1;;;10331:383:27:o;10904:380::-;10983:1;10979:12;;;;11026;;;11047:61;;11101:4;11093:6;11089:17;11079:27;;11047:61;11154:2;11146:6;11143:14;11123:18;11120:38;11117:161;;11200:10;11195:3;11191:20;11188:1;11181:31;11235:4;11232:1;11225:15;11263:4;11260:1;11253:15;11117:161;;10904:380;;;:::o;11289:127::-;11350:10;11345:3;11341:20;11338:1;11331:31;11381:4;11378:1;11371:15;11405:4;11402:1;11395:15;11421:168;11494:9;;;11525;;11542:15;;;11536:22;;11522:37;11512:71;;11563:18;;:::i;11594:184::-;11664:6;11717:2;11705:9;11696:7;11692:23;11688:32;11685:52;;;11733:1;11730;11723:12;11685:52;-1:-1:-1;11756:16:27;;11594:184;-1:-1:-1;11594:184:27:o;11783:146::-;11870:13;;11892:31;11870:13;11892:31;:::i;11934:136::-;12012:13;;12034:30;12012:13;12034:30;:::i;12075:132::-;12151:13;;12173:28;12151:13;12173:28;:::i;12212:1153::-;12303:6;12356:3;12344:9;12335:7;12331:23;12327:33;12324:53;;;12373:1;12370;12363:12;12324:53;12399:22;;:::i;:::-;12444:48;12482:9;12444:48;:::i;:::-;12437:5;12430:63;12525:57;12578:2;12567:9;12563:18;12525:57;:::i;:::-;12520:2;12513:5;12509:14;12502:81;12615:57;12668:2;12657:9;12653:18;12615:57;:::i;:::-;12610:2;12603:5;12599:14;12592:81;12726:2;12715:9;12711:18;12705:25;12700:2;12693:5;12689:14;12682:49;12785:3;12774:9;12770:19;12764:26;12758:3;12751:5;12747:15;12740:51;12824:49;12868:3;12857:9;12853:19;12824:49;:::i;:::-;12818:3;12811:5;12807:15;12800:74;12928:3;12917:9;12913:19;12907:26;12901:3;12894:5;12890:15;12883:51;12988:3;12977:9;12973:19;12967:26;12961:3;12954:5;12950:15;12943:51;13013:3;13069:2;13058:9;13054:18;13048:25;13043:2;13036:5;13032:14;13025:49;;13093:3;13128:46;13170:2;13159:9;13155:18;13128:46;:::i;:::-;13112:14;;;13105:70;13194:3;13235:18;;;13229:25;13213:14;;;13206:49;13274:3;13315:18;;;13309:25;13293:14;;;13286:49;;;;-1:-1:-1;13116:5:27;12212:1153;-1:-1:-1;12212:1153:27:o;13370:127::-;13431:10;13426:3;13422:20;13419:1;13412:31;13462:4;13459:1;13452:15;13486:4;13483:1;13476:15;13502:217;13542:1;13568;13558:132;;13612:10;13607:3;13603:20;13600:1;13593:31;13647:4;13644:1;13637:15;13675:4;13672:1;13665:15;13558:132;-1:-1:-1;13704:9:27;;13502:217::o;13724:125::-;13789:9;;;13810:10;;;13807:36;;;13823:18;;:::i;13854:388::-;14011:2;14000:9;13993:21;14050:6;14045:2;14034:9;14030:18;14023:34;14107:6;14099;14094:2;14083:9;14079:18;14066:48;14163:1;14134:22;;;14158:2;14130:31;;;14123:42;;;;14226:2;14205:15;;;-1:-1:-1;;14201:29:27;14186:45;14182:54;;13854:388;-1:-1:-1;13854:388:27:o;14247:128::-;14314:9;;;14335:11;;;14332:37;;;14349:18;;:::i;14380:127::-;14441:10;14436:3;14432:20;14429:1;14422:31;14472:4;14469:1;14462:15;14496:4;14493:1;14486:15;14512:127;14573:10;14568:3;14564:20;14561:1;14554:31;14604:4;14601:1;14594:15;14628:4;14625:1;14618:15;16032:301;16161:3;16199:6;16193:13;16245:6;16238:4;16230:6;16226:17;16221:3;16215:37;16307:1;16271:16;;16296:13;;;-1:-1:-1;16271:16:27;16032:301;-1:-1:-1;16032:301:27:o;16338:245::-;16405:6;16458:2;16446:9;16437:7;16433:23;16429:32;16426:52;;;16474:1;16471;16464:12;16426:52;16506:9;16500:16;16525:28;16547:5;16525:28;:::i
Swarm Source
ipfs://3618b9f7655c1be46da20cd07ebac82e300887c0c44726db647af911fa07e50c
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.