Overview
POL Balance
POL Value
$0.00More Info
Private Name Tags
ContractCreator
Loading...
Loading
Contract Name:
ZkBobPoolUSDCMigrated
Compiler Version
v0.8.15+commit.e14f2714
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.15; import "./ZkBobPool.sol"; import "./ZkBobTokenSellerMixin.sol"; import "./ZkBobUSDCPermitMixin.sol"; /** * @title ZkBobPoolUSDCMigrated * Shielded transactions pool for USDC tokens supporting USDC transfer authorizations */ contract ZkBobPoolUSDCMigrated is ZkBobPool, ZkBobTokenSellerMixin, ZkBobUSDCPermitMixin { constructor( uint256 __pool_id, address _token, ITransferVerifier _transfer_verifier, ITreeVerifier _tree_verifier, IBatchDepositVerifier _batch_deposit_verifier, address _direct_deposit_queue ) ZkBobPool( __pool_id, _token, _transfer_verifier, _tree_verifier, _batch_deposit_verifier, _direct_deposit_queue, 1, 1_000_000_000 ) {} function migrationToUSDC() external { require(msg.sender == address(this), "Incorrect invoker"); require(token == address(0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174), "Incorrect token"); address bob_addr = address(0xB0B195aEFA3650A6908f15CdaC7D92F8a5791B0B); uint256 cur_bob_balance = IERC20(bob_addr).balanceOf(address(this)); uint256 bob_decimals = IERC20Metadata(bob_addr).decimals(); // uint256 prev_usdc_balance = IERC20(token).balanceOf(address(this)); uint256 usdc_decimals = IERC20Metadata(token).decimals(); IBobVault bobswap = IBobVault(0x25E6505297b44f4817538fB2d91b88e1cF841B54); bool retval = IERC20(bob_addr).approve(address(bobswap), cur_bob_balance); uint256 usdc_received = bobswap.sell(token, cur_bob_balance); require(IERC20(bob_addr).balanceOf(address(this)) == 0, "Incorrect swap"); // uint256 usdc_received = IERC20(token).balanceOf(address(this)) - prev_usdc_balance; uint256 spent_on_fees = (cur_bob_balance / (10 ** (bob_decimals - usdc_decimals))) - usdc_received; retval = IERC20(token).transferFrom(owner(), address(this), spent_on_fees); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.15; import "@openzeppelin/contracts/utils/Address.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol"; import "@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol"; import "@uniswap/v3-periphery/contracts/interfaces/external/IWETH9.sol"; import "../interfaces/ITransferVerifier.sol"; import "../interfaces/ITreeVerifier.sol"; import "../interfaces/IBatchDepositVerifier.sol"; import "../interfaces/IMintableERC20.sol"; import "../interfaces/IOperatorManager.sol"; import "../interfaces/IERC20Permit.sol"; import "../interfaces/ITokenSeller.sol"; import "../interfaces/IZkBobDirectDepositQueue.sol"; import "../interfaces/IZkBobPool.sol"; import "../interfaces/IBobVault.sol"; import "./utils/Parameters.sol"; import "./utils/ZkBobAccounting.sol"; import "../utils/Ownable.sol"; import "../proxy/EIP1967Admin.sol"; /** * @title ZkBobPool * Shielded transactions pool */ abstract contract ZkBobPool is IZkBobPool, EIP1967Admin, Ownable, Parameters, ZkBobAccounting { using SafeERC20 for IERC20; uint256 internal constant MAX_POOL_ID = 0xffffff; bytes4 internal constant MESSAGE_PREFIX_COMMON_V1 = 0x00000000; uint256 internal immutable TOKEN_DENOMINATOR; uint256 internal constant TOKEN_NUMERATOR = 1000; uint256 public immutable pool_id; ITransferVerifier public immutable transfer_verifier; ITreeVerifier public immutable tree_verifier; IBatchDepositVerifier public immutable batch_deposit_verifier; address public immutable token; IZkBobDirectDepositQueue public immutable direct_deposit_queue; IOperatorManager public operatorManager; mapping(uint256 => uint256) public nullifiers; mapping(uint256 => uint256) public roots; bytes32 public all_messages_hash; mapping(address => uint256) public accumulatedFee; event UpdateOperatorManager(address manager); event WithdrawFee(address indexed operator, uint256 fee); event Message(uint256 indexed index, bytes32 indexed hash, bytes message); constructor( uint256 __pool_id, address _token, ITransferVerifier _transfer_verifier, ITreeVerifier _tree_verifier, IBatchDepositVerifier _batch_deposit_verifier, address _direct_deposit_queue, uint256 _denominator, uint256 _precision ) ZkBobAccounting(_precision) { require(__pool_id <= MAX_POOL_ID, "ZkBobPool: exceeds max pool id"); require(Address.isContract(_token), "ZkBobPool: not a contract"); require(Address.isContract(address(_transfer_verifier)), "ZkBobPool: not a contract"); require(Address.isContract(address(_tree_verifier)), "ZkBobPool: not a contract"); require(Address.isContract(address(_batch_deposit_verifier)), "ZkBobPool: not a contract"); require(Address.isContract(_direct_deposit_queue), "ZkBobPool: not a contract"); require(TOKEN_NUMERATOR == 1 || _denominator == 1, "ZkBobPool: incorrect denominator"); pool_id = __pool_id; token = _token; transfer_verifier = _transfer_verifier; tree_verifier = _tree_verifier; batch_deposit_verifier = _batch_deposit_verifier; direct_deposit_queue = IZkBobDirectDepositQueue(_direct_deposit_queue); TOKEN_DENOMINATOR = _denominator; } /** * @dev Throws if called by any account other than the current relayer operator. */ modifier onlyOperator() { require(operatorManager.isOperator(_msgSender()), "ZkBobPool: not an operator"); _; } /** * @dev Initializes pool proxy storage. * Callable only once and only through EIP1967Proxy constructor / upgradeToAndCall. * @param _root initial empty merkle tree root. * @param _tvlCap initial upper cap on the entire pool tvl, 18 decimals. * @param _dailyDepositCap initial daily limit on the sum of all deposits, 18 decimals. * @param _dailyWithdrawalCap initial daily limit on the sum of all withdrawals, 18 decimals. * @param _dailyUserDepositCap initial daily limit on the sum of all per-address deposits, 18 decimals. * @param _depositCap initial limit on the amount of a single deposit, 18 decimals. * @param _dailyUserDirectDepositCap initial daily limit on the sum of all per-address direct deposits, 18 decimals. * @param _directDepositCap initial limit on the amount of a single direct deposit, 18 decimals. */ function initialize( uint256 _root, uint256 _tvlCap, uint256 _dailyDepositCap, uint256 _dailyWithdrawalCap, uint256 _dailyUserDepositCap, uint256 _depositCap, uint256 _dailyUserDirectDepositCap, uint256 _directDepositCap ) external { require(msg.sender == address(this), "ZkBobPool: not initializer"); require(roots[0] == 0, "ZkBobPool: already initialized"); require(_root != 0, "ZkBobPool: zero root"); roots[0] = _root; _setLimits( 0, _tvlCap / TOKEN_DENOMINATOR * TOKEN_NUMERATOR, _dailyDepositCap / TOKEN_DENOMINATOR * TOKEN_NUMERATOR, _dailyWithdrawalCap / TOKEN_DENOMINATOR * TOKEN_NUMERATOR, _dailyUserDepositCap / TOKEN_DENOMINATOR * TOKEN_NUMERATOR, _depositCap / TOKEN_DENOMINATOR * TOKEN_NUMERATOR, _dailyUserDirectDepositCap / TOKEN_DENOMINATOR * TOKEN_NUMERATOR, _directDepositCap / TOKEN_DENOMINATOR * TOKEN_NUMERATOR ); } /** * @dev Updates used operator manager contract. * Callable only by the contract owner / proxy admin. * @param _operatorManager new operator manager implementation. */ function setOperatorManager(IOperatorManager _operatorManager) external onlyOwner { require(address(_operatorManager) != address(0), "ZkBobPool: manager is zero address"); operatorManager = _operatorManager; emit UpdateOperatorManager(address(_operatorManager)); } /** * @dev Tells the denominator for converting pool token into zkBOB units. */ function denominator() external view returns (uint256) { return TOKEN_NUMERATOR == 1 ? TOKEN_DENOMINATOR : (1 << 255) | TOKEN_NUMERATOR; } /** * @dev Tells the current merkle tree index, which will be used for the next operation. * Each operation increases merkle tree size by 128, so index is equal to the total number of seen operations, multiplied by 128. * @return next operator merkle index. */ function pool_index() external view returns (uint256) { return _txCount() << 7; } function _root() internal view override returns (uint256) { return roots[_transfer_index()]; } function _pool_id() internal view override returns (uint256) { return pool_id; } /** * @dev Converts given amount of tokens into native coins sent to the provided address. * @param _user native coins receiver address. * @param _tokenAmount amount to tokens to convert. * @return actual converted amount, might be less than requested amount. */ function _withdrawNative(address _user, uint256 _tokenAmount) internal virtual returns (uint256); /** * @dev Performs token transfer using a signed permit signature. * @param _user token depositor address, should correspond to the signature author. * @param _nullifier nullifier and permit signature salt to avoid transaction data manipulation. * @param _tokenAmount amount to tokens to deposit. */ function _transferFromByPermit(address _user, uint256 _nullifier, int256 _tokenAmount) internal virtual; /** * @dev Perform a zkBob pool transaction. * Callable only by the current operator. * Method uses a custom ABI encoding scheme described in CustomABIDecoder. * Single transact() call performs either deposit, withdrawal or shielded transfer operation. */ function transact() external onlyOperator { address user = msg.sender; uint256 txType = _tx_type(); if (txType == 0) { user = _deposit_spender(); } else if (txType == 2) { user = _memo_receiver(); } else if (txType == 3) { user = _memo_permit_holder(); } int256 transfer_token_delta = _transfer_token_amount(); // For private transfers, operator can receive any fee amount. As receiving a fee is basically a withdrawal, // we should consider operator's tier withdrawal limits respectfully. // For deposits, fee transfers can be left unbounded, since they are paid from the deposits themselves, // not from the pool funds. // For withdrawals, withdrawal amount that is checked against limits for specific user is already inclusive // of operator's fee, thus there is no need to consider it separately. (,, uint256 txCount) = _recordOperation(user, transfer_token_delta); uint256 nullifier = _transfer_nullifier(); { uint256 _pool_index = txCount << 7; require(nullifiers[nullifier] == 0, "ZkBobPool: doublespend detected"); require(_transfer_index() <= _pool_index, "ZkBobPool: transfer index out of bounds"); require(transfer_verifier.verifyProof(_transfer_pub(), _transfer_proof()), "ZkBobPool: bad transfer proof"); require( tree_verifier.verifyProof(_tree_pub(roots[_pool_index]), _tree_proof()), "ZkBobPool: bad tree proof" ); nullifiers[nullifier] = uint256(keccak256(abi.encodePacked(_transfer_out_commit(), _transfer_delta()))); _pool_index += 128; roots[_pool_index] = _tree_root_after(); bytes memory message = _memo_message(); // restrict memo message prefix (items count in little endian) to be < 2**16 require(bytes4(message) & 0x0000ffff == MESSAGE_PREFIX_COMMON_V1, "ZkBobPool: bad message prefix"); bytes32 message_hash = keccak256(message); bytes32 _all_messages_hash = keccak256(abi.encodePacked(all_messages_hash, message_hash)); all_messages_hash = _all_messages_hash; emit Message(_pool_index, _all_messages_hash, message); } uint256 fee = _memo_fee(); int256 token_amount = transfer_token_delta + int256(fee); int256 energy_amount = _transfer_energy_amount(); require(token_amount % int256(TOKEN_NUMERATOR) == 0, "ZkBobPool: incorrect token amount"); if (txType == 0) { // Deposit require(transfer_token_delta > 0 && energy_amount == 0, "ZkBobPool: incorrect deposit amounts"); IERC20(token).safeTransferFrom( user, address(this), uint256(token_amount) * TOKEN_DENOMINATOR / TOKEN_NUMERATOR ); } else if (txType == 1) { // Transfer require(token_amount == 0 && energy_amount == 0, "ZkBobPool: incorrect transfer amounts"); } else if (txType == 2) { // Withdraw require(token_amount <= 0 && energy_amount <= 0, "ZkBobPool: incorrect withdraw amounts"); uint256 native_amount = _memo_native_amount() * TOKEN_DENOMINATOR / TOKEN_NUMERATOR; uint256 withdraw_amount = uint256(-token_amount) * TOKEN_DENOMINATOR / TOKEN_NUMERATOR; if (native_amount > 0) { withdraw_amount -= _withdrawNative(user, native_amount); } if (withdraw_amount > 0) { IERC20(token).safeTransfer(user, withdraw_amount); } // energy withdrawals are not yet implemented, any transaction with non-zero energy_amount will revert // future version of the protocol will support energy withdrawals through negative energy_amount if (energy_amount < 0) { revert("ZkBobPool: XP claiming is not yet enabled"); } } else if (txType == 3) { // Permittable token deposit require(transfer_token_delta > 0 && energy_amount == 0, "ZkBobPool: incorrect deposit amounts"); _transferFromByPermit(user, nullifier, token_amount); } else { revert("ZkBobPool: Incorrect transaction type"); } if (fee > 0) { accumulatedFee[msg.sender] += fee; } } /** * @dev Appends a batch of direct deposits into a zkBob merkle tree. * Callable only by the current operator. * @param _root_after new merkle tree root after append. * @param _indices list of indices for queued pending deposits. * @param _out_commit out commitment for output notes serialized from direct deposits. * @param _batch_deposit_proof snark proof for batch deposit verifier. * @param _tree_proof snark proof for tree update verifier. */ function appendDirectDeposits( uint256 _root_after, uint256[] calldata _indices, uint256 _out_commit, uint256[8] memory _batch_deposit_proof, uint256[8] memory _tree_proof ) external onlyOperator { (uint256 total, uint256 totalFee, uint256 hashsum, bytes memory message) = direct_deposit_queue.collect(_indices, _out_commit); (,, uint256 txCount) = _recordOperation(address(0), int256(total)); uint256 _pool_index = txCount << 7; // verify that _out_commit corresponds to zero output account + 16 chosen notes + 111 empty notes require( batch_deposit_verifier.verifyProof([hashsum], _batch_deposit_proof), "ZkBobPool: bad batch deposit proof" ); uint256[3] memory tree_pub = [roots[_pool_index], _root_after, _out_commit]; require(tree_verifier.verifyProof(tree_pub, _tree_proof), "ZkBobPool: bad tree proof"); _pool_index += 128; roots[_pool_index] = _root_after; bytes32 message_hash = keccak256(message); bytes32 _all_messages_hash = keccak256(abi.encodePacked(all_messages_hash, message_hash)); all_messages_hash = _all_messages_hash; if (totalFee > 0) { accumulatedFee[msg.sender] += totalFee; } emit Message(_pool_index, _all_messages_hash, message); } /** * @dev Records submitted direct deposit into the users limits. * Callable only by the direct deposit queue. * @param _sender direct deposit sender. * @param _amount direct deposit amount in zkBOB units. */ function recordDirectDeposit(address _sender, uint256 _amount) external { require(msg.sender == address(direct_deposit_queue), "ZkBobPool: not authorized"); _checkDirectDepositLimits(_sender, _amount); } /** * @dev Withdraws accumulated fee on behalf of an operator. * Callable only by the operator itself, or by a pre-configured operator fee receiver address. * @param _operator address of an operator account to withdraw fee from. * @param _to address of the accumulated fee tokens receiver. */ function withdrawFee(address _operator, address _to) external { require( _operator == msg.sender || operatorManager.isOperatorFeeReceiver(_operator, msg.sender), "ZkBobPool: not authorized" ); uint256 fee = accumulatedFee[_operator] * TOKEN_DENOMINATOR / TOKEN_NUMERATOR; require(fee > 0, "ZkBobPool: no fee to withdraw"); IERC20(token).safeTransfer(_to, fee); accumulatedFee[_operator] = 0; emit WithdrawFee(_operator, fee); } /** * @dev Updates pool usage limits. * Callable only by the contract owner / proxy admin. * @param _tier pool limits tier (0-254). * @param _tvlCap new upper cap on the entire pool tvl, 18 decimals. * @param _dailyDepositCap new daily limit on the sum of all deposits, 18 decimals. * @param _dailyWithdrawalCap new daily limit on the sum of all withdrawals, 18 decimals. * @param _dailyUserDepositCap new daily limit on the sum of all per-address deposits, 18 decimals. * @param _depositCap new limit on the amount of a single deposit, 18 decimals. * @param _dailyUserDirectDepositCap new daily limit on the sum of all per-address direct deposits, 18 decimals. * @param _directDepositCap new limit on the amount of a single direct deposit, 18 decimals. */ function setLimits( uint8 _tier, uint256 _tvlCap, uint256 _dailyDepositCap, uint256 _dailyWithdrawalCap, uint256 _dailyUserDepositCap, uint256 _depositCap, uint256 _dailyUserDirectDepositCap, uint256 _directDepositCap ) external onlyOwner { _setLimits( _tier, _tvlCap / TOKEN_DENOMINATOR * TOKEN_NUMERATOR, _dailyDepositCap / TOKEN_DENOMINATOR * TOKEN_NUMERATOR, _dailyWithdrawalCap / TOKEN_DENOMINATOR * TOKEN_NUMERATOR, _dailyUserDepositCap / TOKEN_DENOMINATOR * TOKEN_NUMERATOR, _depositCap / TOKEN_DENOMINATOR * TOKEN_NUMERATOR, _dailyUserDirectDepositCap / TOKEN_DENOMINATOR * TOKEN_NUMERATOR, _directDepositCap / TOKEN_DENOMINATOR * TOKEN_NUMERATOR ); } /** * @dev Resets daily limit usage for the current day. * Callable only by the contract owner / proxy admin. * @param _tier tier id to reset daily limits for. */ function resetDailyLimits(uint8 _tier) external onlyOwner { _resetDailyLimits(_tier); } /** * @dev Updates users limit tiers. * Callable only by the contract owner / proxy admin. * @param _tier pool limits tier (0-255). * 0 is the default tier. * 1-254 are custom pool limit tiers, configured at runtime. * 255 is the special tier with zero limits, used to effectively prevent some address from accessing the pool. * @param _users list of user account addresses to assign a tier for. */ function setUsersTier(uint8 _tier, address[] memory _users) external onlyOwner { _setUsersTier(_tier, _users); } /** * @dev Tells if caller is the contract owner. * Gives ownership rights to the proxy admin as well. * @return true, if caller is the contract owner or proxy admin. */ function _isOwner() internal view override returns (bool) { return super._isOwner() || _admin() == _msgSender(); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.15; import "./ZkBobPool.sol"; /** * @title ZkBobTokenSellerMixin */ abstract contract ZkBobTokenSellerMixin is ZkBobPool { using SafeERC20 for IERC20; ITokenSeller public tokenSeller; event UpdateTokenSeller(address seller); /** * @dev Updates token seller contract used for native coin withdrawals. * Callable only by the contract owner / proxy admin. * @param _seller new token seller contract implementation. address(0) will deactivate native withdrawals. */ function setTokenSeller(address _seller) external onlyOwner { tokenSeller = ITokenSeller(_seller); emit UpdateTokenSeller(_seller); } // @inheritdoc ZkBobPool function _withdrawNative(address _user, uint256 _tokenAmount) internal override returns (uint256) { ITokenSeller seller = tokenSeller; if (address(seller) != address(0)) { IERC20(token).safeTransfer(address(seller), _tokenAmount); (, uint256 refunded) = seller.sellForETH(_user, _tokenAmount); return _tokenAmount - refunded; } return 0; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.15; import "../interfaces/IUSDCPermit.sol"; import "./ZkBobPool.sol"; /** * @title ZkBobUSDCPermitMixin */ abstract contract ZkBobUSDCPermitMixin is ZkBobPool { // @inheritdoc ZkBobPool function _transferFromByPermit(address _user, uint256 _nullifier, int256 _tokenAmount) internal override { (uint8 v, bytes32 r, bytes32 s) = _permittable_deposit_signature(); IUSDCPermit(token).transferWithAuthorization( _user, address(this), uint256(_tokenAmount) * TOKEN_DENOMINATOR / TOKEN_NUMERATOR, 0, _memo_permit_deadline(), bytes32(_nullifier), v, r, s ); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @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://diligence.consensys.net/posts/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.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @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, it is bubbled up by this * function (like regular Solidity function calls). * * 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. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @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`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) 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(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @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 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 `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, 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 `from` to `to` 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 from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ 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 v4.8.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/draft-IERC20Permit.sol"; import "../../../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; function safeTransfer( IERC20 token, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @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, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.7.5; pragma abicoder v2; import '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol'; /// @title Router token swapping functionality /// @notice Functions for swapping tokens via Uniswap V3 interface ISwapRouter is IUniswapV3SwapCallback { struct ExactInputSingleParams { address tokenIn; address tokenOut; uint24 fee; address recipient; uint256 deadline; uint256 amountIn; uint256 amountOutMinimum; uint160 sqrtPriceLimitX96; } /// @notice Swaps `amountIn` of one token for as much as possible of another token /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata /// @return amountOut The amount of the received token function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut); struct ExactInputParams { bytes path; address recipient; uint256 deadline; uint256 amountIn; uint256 amountOutMinimum; } /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata /// @return amountOut The amount of the received token function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut); struct ExactOutputSingleParams { address tokenIn; address tokenOut; uint24 fee; address recipient; uint256 deadline; uint256 amountOut; uint256 amountInMaximum; uint160 sqrtPriceLimitX96; } /// @notice Swaps as little as possible of one token for `amountOut` of another token /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata /// @return amountIn The amount of the input token function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn); struct ExactOutputParams { bytes path; address recipient; uint256 deadline; uint256 amountOut; uint256 amountInMaximum; } /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed) /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata /// @return amountIn The amount of the input token function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Immutable state /// @notice Functions that return immutable state of the router interface IPeripheryImmutableState { /// @return Returns the address of the Uniswap V3 factory function factory() external view returns (address); /// @return Returns the address of WETH9 function WETH9() external view returns (address); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity =0.8.15; import '@openzeppelin/contracts/token/ERC20/IERC20.sol'; /// @title Interface for WETH9 interface IWETH9 is IERC20 { /// @notice Deposit ether to get wrapped ether function deposit() external payable; /// @notice Withdraw wrapped ether to get ether function withdraw(uint256) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.15; interface ITransferVerifier { function verifyProof(uint256[5] memory input, uint256[8] memory p) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.15; interface ITreeVerifier { function verifyProof(uint256[3] memory input, uint256[8] memory p) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.15; interface IBatchDepositVerifier { function verifyProof(uint256[1] memory input, uint256[8] memory p) external view returns (bool); }
// SPDX-License-Identifier: CC0-1.0 pragma solidity 0.8.15; interface IMintableERC20 { function mint(address to, uint256 amount) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.15; interface IOperatorManager { function isOperator(address _addr) external view returns (bool); function isOperatorFeeReceiver(address _operator, address _addr) external view returns (bool); function operatorURI() external view returns (string memory); }
// SPDX-License-Identifier: CC0-1.0 pragma solidity 0.8.15; interface IERC20Permit { function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; function nonces(address owner) external view returns (uint256); function DOMAIN_SEPARATOR() external view returns (bytes32); function PERMIT_TYPEHASH() external view returns (bytes32); function SALTED_PERMIT_TYPEHASH() external view returns (bytes32); function receiveWithPermit( address _holder, uint256 _value, uint256 _deadline, uint8 _v, bytes32 _r, bytes32 _s ) external; function receiveWithSaltedPermit( address _holder, uint256 _value, uint256 _deadline, bytes32 _salt, uint8 _v, bytes32 _r, bytes32 _s ) external; }
// SPDX-License-Identifier: CC0-1.0 pragma solidity 0.8.15; interface ITokenSeller { /** * @dev Sells tokens for ETH. * Prior to calling this function, contract balance of token0 should be greater than or equal to the sold amount. * @param _receiver native ETH receiver. * @param _amount amount of tokens to sell. * @return (received eth amount, refunded token amount). */ function sellForETH(address _receiver, uint256 _amount) external returns (uint256, uint256); /** * @dev Estimates amount of received ETH, when selling given amount of tokens via sellForETH function. * @param _amount amount of tokens to sell. * @return received eth amount. */ function quoteSellForETH(uint256 _amount) external returns (uint256); }
// SPDX-License-Identifier: CC0-1.0 pragma solidity ^0.8.0; interface IZkBobDirectDepositQueue { /** * @dev Collects aggregated info about submitted direct deposits and marks them as completed. * Callable only by the zkBOB pool contract. * @param _indices list of direct deposit indices to process, max of 16 indices are allowed. * @param _out_commit pre-calculated out commitment associated with the given deposits. * @return total sum of deposit amounts, not counting fees. * @return totalFee sum of deposit fees. * @return hashsum hashsum over all retrieved direct deposits. * @return message memo message to record into the tree. */ function collect( uint256[] calldata _indices, uint256 _out_commit ) external returns (uint256 total, uint256 totalFee, uint256 hashsum, bytes memory message); }
// SPDX-License-Identifier: CC0-1.0 pragma solidity ^0.8.0; interface IZkBobPool { function pool_id() external view returns (uint256); function recordDirectDeposit(address _sender, uint256 _amount) external; }
// SPDX-License-Identifier: CC0-1.0 pragma solidity ^0.8.0; interface IBobVault { function buy(address _token, uint256 _amount) external returns (uint256); function sell(address _token, uint256 _amount) external returns (uint256); function swap(address _inToken, address _outToken, uint256 _amount) external returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.15; import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import "./CustomABIDecoder.sol"; abstract contract Parameters is CustomABIDecoder { uint256 constant R = 21888242871839275222246405745257275088548364400416034343698204186575808495617; bytes32 constant S_MASK = 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; function _root() internal view virtual returns (uint256); function _pool_id() internal view virtual returns (uint256); function _transfer_pub() internal view returns (uint256[5] memory r) { r[0] = _root(); r[1] = _transfer_nullifier(); r[2] = _transfer_out_commit(); r[3] = _transfer_delta() + (_pool_id() << (transfer_delta_size * 8)); r[4] = uint256(keccak256(_memo_data())) % R; } function _tree_pub(uint256 _root_before) internal view returns (uint256[3] memory r) { r[0] = _root_before; r[1] = _tree_root_after(); r[2] = _transfer_out_commit(); } // NOTE only valid in the context of normal deposit (tx_type=0) function _deposit_spender() internal pure returns (address) { (bytes32 r, bytes32 vs) = _sign_r_vs(); return ECDSA.recover(ECDSA.toEthSignedMessageHash(bytes32(_transfer_nullifier())), r, vs); } // NOTE only valid in the context of permittable token deposit (tx_type=3) function _permittable_deposit_signature() internal pure returns (uint8, bytes32, bytes32) { (bytes32 r, bytes32 vs) = _sign_r_vs(); return (uint8((uint256(vs) >> 255) + 27), r, vs & S_MASK); } }
// SPDX-License-Identifier: CC0-1.0 pragma solidity 0.8.15; import "../../interfaces/IKycProvidersManager.sol"; import "./KycProvidersManagerStorage.sol"; /** * @title ZkBobAccounting * @dev On chain accounting for zkBob operations, limits and stats. * Units: 1 BOB = 1e18 wei = 1e9 zkBOB units * Limitations: Contract will only work correctly as long as pool tvl does not exceed 4.7e12 BOB (4.7 trillion) * and overall transaction count does not exceed 4.3e9 (4.3 billion). Pool usage limits cannot exceed 4.3e9 BOB (4.3 billion) per day. */ contract ZkBobAccounting is KycProvidersManagerStorage { uint256 internal constant SLOT_DURATION = 1 hours; uint256 internal constant DAY_SLOTS = 1 days / SLOT_DURATION; uint256 internal constant WEEK_SLOTS = 1 weeks / SLOT_DURATION; uint256 internal immutable PRECISION; struct Slot0 { // max seen average tvl over period of at least 1 week (granularity of 1e9), might not be precise // max possible tvl - type(uint56).max * 1e9 zkBOB units ~= 7.2e16 BOB uint56 maxWeeklyAvgTvl; // max number of pool interactions over 1 week, might not be precise // max possible tx count - type(uint32).max ~= 4.3e9 transactions uint32 maxWeeklyTxCount; // 1 week behind snapshot time slot (granularity of 1 hour) // max possible timestamp - Dec 08 3883 uint24 tailSlot; // active snapshot time slot (granularity of 1 hour) // max possible timestamp - Dec 08 3883 uint24 headSlot; // cumulative sum of tvl over txCount interactions (granularity of 1e9) // max possible cumulative tvl ~= type(uint32).max * type(uint56).max = 4.3e9 transactions * 7.2e16 BOB uint88 cumTvl; // number of successful pool interactions since launch // max possible tx count - type(uint32).max ~= 4.3e9 transactions uint32 txCount; } struct Slot1 { // current pool tvl (granularity of 1) // max possible tvl - type(uint72).max * 1 zkBOB units ~= 4.7e21 zkBOB units ~= 4.7e12 BOB uint72 tvl; } struct Tier { TierLimits limits; TierStats stats; } struct TierLimits { // max cap on the entire pool tvl (granularity of 1e9) // max possible cap - type(uint56).max * 1e9 zkBOB units ~= 7.2e16 BOB uint56 tvlCap; // max cap on the daily deposits sum (granularity of 1e9) // max possible cap - type(uint32).max * 1e9 zkBOB units ~= 4.3e9 BOB uint32 dailyDepositCap; // max cap on the daily withdrawal sum (granularity of 1e9) // max possible cap - type(uint32).max * 1e9 zkBOB units ~= 4.3e9 BOB uint32 dailyWithdrawalCap; // max cap on the daily deposits sum for single user (granularity of 1e9) // max possible cap - type(uint32).max * 1e9 zkBOB units ~= 4.3e9 BOB uint32 dailyUserDepositCap; // max cap on a single deposit (granularity of 1e9) // max possible cap - type(uint32).max * 1e9 zkBOB units ~= 4.3e9 BOB uint32 depositCap; // max cap on a single direct deposit (granularity of 1e9) // max possible cap - type(uint32).max * 1e9 zkBOB units ~= 4.3e9 BOB uint32 directDepositCap; // max cap on the daily direct deposits sum for single user (granularity of 1e9) // max possible cap - type(uint32).max * 1e9 zkBOB units ~= 4.3e9 BOB uint32 dailyUserDirectDepositCap; } struct TierStats { uint16 day; // last update day number uint72 dailyDeposit; // sum of all deposits during given day uint72 dailyWithdrawal; // sum of all withdrawals during given day } struct Snapshot { uint24 nextSlot; // next slot to from the queue uint32 txCount; // number of successful pool interactions since launch at the time of the snapshot uint88 cumTvl; // cumulative sum of tvl over txCount interactions (granularity of 1e9) } struct UserStats { uint16 day; // last update day number uint72 dailyDeposit; // sum of user deposits during given day uint8 tier; // user limits tier, 0 being the default tier uint72 dailyDirectDeposit; // sum of user direct deposits during given day } struct Limits { uint256 tvlCap; uint256 tvl; uint256 dailyDepositCap; uint256 dailyDepositCapUsage; uint256 dailyWithdrawalCap; uint256 dailyWithdrawalCapUsage; uint256 dailyUserDepositCap; uint256 dailyUserDepositCapUsage; uint256 depositCap; uint8 tier; uint256 dailyUserDirectDepositCap; uint256 dailyUserDirectDepositCapUsage; uint256 directDepositCap; } Slot0 private slot0; Slot1 private slot1; mapping(uint256 => Tier) private tiers; // pool limits and usage per tier mapping(uint256 => Snapshot) private snapshots; // single linked list of hourly snapshots mapping(address => UserStats) private userStats; event UpdateLimits(uint8 indexed tier, TierLimits limits); event UpdateTier(address user, uint8 tier); constructor(uint256 _precision) { PRECISION = _precision; } /** * @dev Returns currently configured limits and remaining quotas for the given user as of the current block. * @param _user user for which to retrieve limits. * @return limits (denominated in zkBOB units = 1e-9 BOB) */ function getLimitsFor(address _user) external view returns (Limits memory) { Slot1 memory s1 = slot1; UserStats memory us = userStats[_user]; uint8 tier = _adjustConfiguredTierForUser(_user, us.tier); Tier storage t = tiers[tier]; TierLimits memory tl = t.limits; TierStats memory ts = t.stats; uint24 curSlot = uint24(block.timestamp / SLOT_DURATION); uint24 today = curSlot / uint24(DAY_SLOTS); return Limits({ tvlCap: tl.tvlCap * PRECISION, tvl: s1.tvl, dailyDepositCap: tl.dailyDepositCap * PRECISION, dailyDepositCapUsage: (ts.day == today) ? ts.dailyDeposit : 0, dailyWithdrawalCap: tl.dailyWithdrawalCap * PRECISION, dailyWithdrawalCapUsage: (ts.day == today) ? ts.dailyWithdrawal : 0, dailyUserDepositCap: tl.dailyUserDepositCap * PRECISION, dailyUserDepositCapUsage: (us.day == today) ? us.dailyDeposit : 0, depositCap: tl.depositCap * PRECISION, tier: tier, dailyUserDirectDepositCap: tl.dailyUserDirectDepositCap * PRECISION, dailyUserDirectDepositCapUsage: (us.day == today) ? us.dailyDirectDeposit : 0, directDepositCap: tl.directDepositCap * PRECISION }); } function _recordOperation( address _user, int256 _txAmount ) internal returns (uint56 maxWeeklyAvgTvl, uint32 maxWeeklyTxCount, uint256 txCount) { Slot0 memory s0 = slot0; Slot1 memory s1 = slot1; uint24 curSlot = uint24(block.timestamp / SLOT_DURATION); txCount = uint256(s0.txCount); // for full correctness, next line should use "while" instead of "if" // however, in order to keep constant gas usage, "if" is being used // this can lead to a longer sliding window (> 1 week) in some cases, // but eventually it will converge back to the 1 week target if (s0.txCount > 0 && curSlot - s0.tailSlot > WEEK_SLOTS) { // if tail is more than 1 week behind, we move tail pointer to the next snapshot Snapshot memory sn = snapshots[s0.tailSlot]; delete snapshots[s0.tailSlot]; s0.tailSlot = sn.nextSlot; uint32 weeklyTxCount = s0.txCount - sn.txCount; if (weeklyTxCount > s0.maxWeeklyTxCount) { s0.maxWeeklyTxCount = weeklyTxCount; } uint56 avgTvl = uint56((s0.cumTvl - sn.cumTvl) / weeklyTxCount); if (avgTvl > s0.maxWeeklyAvgTvl) { s0.maxWeeklyAvgTvl = avgTvl; } } if (s0.headSlot < curSlot) { snapshots[s0.headSlot] = Snapshot(curSlot, s0.txCount, s0.cumTvl); s0.headSlot = curSlot; } // update head stats s0.cumTvl += s1.tvl / uint72(PRECISION); s0.txCount++; if (_txAmount != 0) { _processTVLChange(s1, _user, _txAmount); } slot0 = s0; return (s0.maxWeeklyAvgTvl, s0.maxWeeklyTxCount, txCount); } function _processTVLChange(Slot1 memory s1, address _user, int256 _txAmount) internal { // short path for direct deposits batch processing if (_user == address(0) && _txAmount > 0) { slot1.tvl += uint72(uint256(_txAmount)); return; } uint16 curDay = uint16(block.timestamp / SLOT_DURATION / DAY_SLOTS); UserStats memory us = userStats[_user]; Tier storage t = tiers[_adjustConfiguredTierForUser(_user, us.tier)]; TierLimits memory tl = t.limits; TierStats memory ts = t.stats; if (_txAmount > 0) { uint256 depositAmount = uint256(_txAmount); s1.tvl += uint72(depositAmount); // check all sorts of limits when processing a deposit require(depositAmount <= uint256(tl.depositCap) * PRECISION, "ZkBobAccounting: single deposit cap exceeded"); require(uint256(s1.tvl) <= uint256(tl.tvlCap) * PRECISION, "ZkBobAccounting: tvl cap exceeded"); if (curDay > us.day) { // user snapshot is outdated, day number and daily sum could be reset // original user's tier (0) is preserved userStats[_user] = UserStats({day: curDay, dailyDeposit: uint72(depositAmount), tier: us.tier, dailyDirectDeposit: 0}); } else { us.dailyDeposit += uint72(depositAmount); require( uint256(us.dailyDeposit) <= uint256(tl.dailyUserDepositCap) * PRECISION, "ZkBobAccounting: daily user deposit cap exceeded" ); userStats[_user] = us; } if (curDay > ts.day) { // latest deposit was on an earlier day, reset daily withdrawal sum ts = TierStats({day: curDay, dailyDeposit: uint72(depositAmount), dailyWithdrawal: 0}); } else { ts.dailyDeposit += uint72(depositAmount); require( uint256(ts.dailyDeposit) <= uint256(tl.dailyDepositCap) * PRECISION, "ZkBobAccounting: daily deposit cap exceeded" ); } } else { uint256 withdrawAmount = uint256(-_txAmount); require(withdrawAmount <= type(uint32).max * PRECISION, "ZkBobAccounting: withdrawal amount too large"); s1.tvl -= uint72(withdrawAmount); if (curDay > ts.day) { // latest withdrawal was on an earlier day, reset daily deposit sum ts = TierStats({day: curDay, dailyDeposit: 0, dailyWithdrawal: uint72(withdrawAmount)}); } else { ts.dailyWithdrawal += uint72(withdrawAmount); require( uint256(ts.dailyWithdrawal) <= uint256(tl.dailyWithdrawalCap) * PRECISION, "ZkBobAccounting: daily withdrawal cap exceeded" ); } } slot1 = s1; t.stats = ts; } function _checkDirectDepositLimits(address _user, uint256 _amount) internal { uint16 curDay = uint16(block.timestamp / SLOT_DURATION / DAY_SLOTS); UserStats memory us = userStats[_user]; TierLimits memory tl = tiers[_adjustConfiguredTierForUser(_user, us.tier)].limits; // check all sorts of limits when processing a deposit require( _amount <= uint256(tl.directDepositCap) * PRECISION, "ZkBobAccounting: single direct deposit cap exceeded" ); if (curDay > us.day) { // user snapshot is outdated, day number and daily sum could be reset // original user's tier (0) is preserved us = UserStats({day: curDay, dailyDeposit: 0, tier: us.tier, dailyDirectDeposit: uint72(_amount)}); } else { us.dailyDirectDeposit += uint72(_amount); require( uint256(us.dailyDirectDeposit) <= uint256(tl.dailyUserDirectDepositCap) * PRECISION, "ZkBobAccounting: daily user direct deposit cap exceeded" ); } userStats[_user] = us; } function _resetDailyLimits(uint8 _tier) internal { delete tiers[_tier].stats; } function _setLimits( uint8 _tier, uint256 _tvlCap, uint256 _dailyDepositCap, uint256 _dailyWithdrawalCap, uint256 _dailyUserDepositCap, uint256 _depositCap, uint256 _dailyUserDirectDepositCap, uint256 _directDepositCap ) internal { require(_tier < 255, "ZkBobAccounting: invalid limit tier"); require(_depositCap > 0, "ZkBobAccounting: zero deposit cap"); require(_tvlCap <= type(uint56).max * PRECISION, "ZkBobAccounting: tvl cap too large"); require(_dailyDepositCap <= type(uint32).max * PRECISION, "ZkBobAccounting: daily deposit cap too large"); require(_dailyWithdrawalCap <= type(uint32).max * PRECISION, "ZkBobAccounting: daily withdrawal cap too large"); require(_dailyUserDepositCap >= _depositCap, "ZkBobAccounting: daily user deposit cap too low"); require(_dailyDepositCap >= _dailyUserDepositCap, "ZkBobAccounting: daily deposit cap too low"); require(_tvlCap >= _dailyDepositCap, "ZkBobAccounting: tvl cap too low"); require(_dailyWithdrawalCap > 0, "ZkBobAccounting: zero daily withdrawal cap"); require( _dailyUserDirectDepositCap >= _directDepositCap, "ZkBobAccounting: daily user direct deposit cap too low" ); TierLimits memory tl = TierLimits({ tvlCap: uint56(_tvlCap / PRECISION), dailyDepositCap: uint32(_dailyDepositCap / PRECISION), dailyWithdrawalCap: uint32(_dailyWithdrawalCap / PRECISION), dailyUserDepositCap: uint32(_dailyUserDepositCap / PRECISION), depositCap: uint32(_depositCap / PRECISION), dailyUserDirectDepositCap: uint32(_dailyUserDirectDepositCap / PRECISION), directDepositCap: uint32(_directDepositCap / PRECISION) }); tiers[_tier].limits = tl; emit UpdateLimits(_tier, tl); } // Tier is set as per the KYC Providers Manager recommendation only in the case if no // specific tier assigned to the user function _adjustConfiguredTierForUser(address _user, uint8 _configuredTier) internal view returns (uint8) { IKycProvidersManager kycProvidersMgr = kycProvidersManager(); if (_configuredTier == 0 && address(kycProvidersMgr) != address(0)) { (bool kycPassed, uint8 tier) = kycProvidersMgr.getIfKYCpassedAndTier(_user); if (kycPassed && tiers[tier].limits.tvlCap > 0) { return tier; } } return _configuredTier; } function _setUsersTier(uint8 _tier, address[] memory _users) internal { require( _tier == 255 || tiers[uint256(_tier)].limits.tvlCap > 0, "ZkBobAccounting: non-existing pool limits tier" ); for (uint256 i = 0; i < _users.length; ++i) { address user = _users[i]; userStats[user].tier = _tier; emit UpdateTier(user, _tier); } } function _txCount() internal view returns (uint256) { return slot0.txCount; } }
// SPDX-License-Identifier: CC0-1.0 pragma solidity 0.8.15; import "@openzeppelin/contracts/access/Ownable.sol" as OZOwnable; /** * @title Ownable */ contract Ownable is OZOwnable.Ownable { /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view override { require(_isOwner(), "Ownable: caller is not the owner"); } /** * @dev Tells if caller is the contract owner. * @return true, if caller is the contract owner. */ function _isOwner() internal view virtual returns (bool) { return owner() == _msgSender(); } }
// SPDX-License-Identifier: CC0-1.0 pragma solidity 0.8.15; /** * @title EIP1967Admin * @dev Upgradeable proxy pattern implementation according to minimalistic EIP1967. */ contract EIP1967Admin { // EIP 1967 // bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1) uint256 internal constant EIP1967_ADMIN_STORAGE = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; modifier onlyAdmin() { require(msg.sender == _admin(), "EIP1967Admin: not an admin"); _; } function _admin() internal view returns (address res) { assembly { res := sload(EIP1967_ADMIN_STORAGE) } } }
// SPDX-License-Identifier: CC0-1.0 pragma solidity 0.8.15; interface IUSDCPermit { function transferWithAuthorization( address from, address to, uint256 value, uint256 validAfter, uint256 validBefore, bytes32 nonce, uint8 v, bytes32 r, bytes32 s ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) pragma solidity ^0.8.0; /** * @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. */ 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]. */ 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: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Callback for IUniswapV3PoolActions#swap /// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface interface IUniswapV3SwapCallback { /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap. /// @dev In the implementation you must pay the pool tokens owed for the swap. /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped. /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by /// the end of the swap. If positive, the callback must send that amount of token0 to the pool. /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by /// the end of the swap. If positive, the callback must send that amount of token1 to the pool. /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call function uniswapV3SwapCallback( int256 amount0Delta, int256 amount1Delta, bytes calldata data ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.0; import "../Strings.sol"; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS, InvalidSignatureV // Deprecated in v4.8 } function _throwError(RecoverError error) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert("ECDSA: invalid signature"); } else if (error == RecoverError.InvalidSignatureLength) { revert("ECDSA: invalid signature length"); } else if (error == RecoverError.InvalidSignatureS) { revert("ECDSA: invalid signature 's' value"); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature` or error string. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, signature); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] * * _Available since v4.3._ */ function tryRecover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address, RecoverError) { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. * * _Available since v4.2._ */ function recover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, r, vs); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. * * _Available since v4.3._ */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address, RecoverError) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature); } return (signer, RecoverError.NoError); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, v, r, s); _throwError(error); return recovered; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) { // 32 is the length in bytes of hash, // enforced by the type signature above return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); } /** * @dev Returns an Ethereum Signed Message, created from `s`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s)); } /** * @dev Returns an Ethereum Signed Typed Data, created from a * `domainSeparator` and a `structHash`. This produces hash corresponding * to the one signed with the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] * JSON-RPC method as part of EIP-712. * * See {recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.15; contract CustomABIDecoder { uint256 constant transfer_nullifier_pos = 4; uint256 constant transfer_nullifier_size = 32; uint256 constant uint256_size = 32; function _loaduint256(uint256 pos) internal pure returns (uint256 r) { assembly { r := calldataload(pos) } } function _transfer_nullifier() internal pure returns (uint256 r) { r = _loaduint256(transfer_nullifier_pos); } uint256 constant transfer_out_commit_pos = transfer_nullifier_pos + transfer_nullifier_size; uint256 constant transfer_out_commit_size = 32; function _transfer_out_commit() internal pure returns (uint256 r) { r = _loaduint256(transfer_out_commit_pos); } uint256 constant transfer_index_pos = transfer_out_commit_pos + transfer_out_commit_size; uint256 constant transfer_index_size = 6; function _transfer_index() internal pure returns (uint48 r) { r = uint48(_loaduint256(transfer_index_pos + transfer_index_size - uint256_size)); } uint256 constant transfer_energy_amount_pos = transfer_index_pos + transfer_index_size; uint256 constant transfer_energy_amount_size = 14; function _transfer_energy_amount() internal pure returns (int112 r) { r = int112(uint112(_loaduint256(transfer_energy_amount_pos + transfer_energy_amount_size - uint256_size))); } uint256 constant transfer_token_amount_pos = transfer_energy_amount_pos + transfer_energy_amount_size; uint256 constant transfer_token_amount_size = 8; function _transfer_token_amount() internal pure returns (int64 r) { r = int64(uint64(_loaduint256(transfer_token_amount_pos + transfer_token_amount_size - uint256_size))); } uint256 constant transfer_proof_pos = transfer_token_amount_pos + transfer_token_amount_size; uint256 constant transfer_proof_size = 256; function _transfer_proof() internal pure returns (uint256[8] calldata r) { uint256 pos = transfer_proof_pos; assembly { r := pos } } uint256 constant tree_root_after_pos = transfer_proof_pos + transfer_proof_size; uint256 constant tree_root_after_size = 32; function _tree_root_after() internal pure returns (uint256 r) { r = _loaduint256(tree_root_after_pos); } uint256 constant tree_proof_pos = tree_root_after_pos + tree_root_after_size; uint256 constant tree_proof_size = 256; function _tree_proof() internal pure returns (uint256[8] calldata r) { uint256 pos = tree_proof_pos; assembly { r := pos } } uint256 constant tx_type_pos = tree_proof_pos + tree_proof_size; uint256 constant tx_type_size = 2; uint256 constant tx_type_mask = (1 << (tx_type_size * 8)) - 1; function _tx_type() internal pure returns (uint256 r) { r = _loaduint256(tx_type_pos + tx_type_size - uint256_size) & tx_type_mask; } uint256 constant memo_data_size_pos = tx_type_pos + tx_type_size; uint256 constant memo_data_size_size = 2; uint256 constant memo_data_size_mask = (1 << (memo_data_size_size * 8)) - 1; uint256 constant memo_data_pos = memo_data_size_pos + memo_data_size_size; function _memo_data_size() internal pure returns (uint256 r) { r = _loaduint256(memo_data_size_pos + memo_data_size_size - uint256_size) & memo_data_size_mask; } function _memo_data() internal pure returns (bytes calldata r) { uint256 offset = memo_data_pos; uint256 length = _memo_data_size(); assembly { r.offset := offset r.length := length } } function _sign_r_vs_pos() internal pure returns (uint256) { return memo_data_pos + _memo_data_size(); } uint256 constant sign_r_vs_size = 64; function _sign_r_vs() internal pure returns (bytes32 r, bytes32 vs) { uint256 offset = _sign_r_vs_pos(); assembly { r := calldataload(offset) vs := calldataload(add(offset, 32)) } } uint256 constant transfer_delta_size = transfer_index_size + transfer_energy_amount_size + transfer_token_amount_size; uint256 constant transfer_delta_mask = (1 << (transfer_delta_size * 8)) - 1; function _transfer_delta() internal pure returns (uint256 r) { r = _loaduint256(transfer_index_pos + transfer_delta_size - uint256_size) & transfer_delta_mask; } function _memo_fixed_size() internal pure returns (uint256 r) { uint256 t = _tx_type(); if (t == 0 || t == 1) { // fee // 8 r = 8; } else if (t == 2) { // fee + native amount + recipient // 8 + 8 + 20 r = 36; } else if (t == 3) { // fee + deadline + address // 8 + 8 + 20 r = 36; } else { revert(); } } function _memo_message() internal pure returns (bytes calldata r) { uint256 memo_fixed_size = _memo_fixed_size(); uint256 offset = memo_data_pos + memo_fixed_size; uint256 length = _memo_data_size() - memo_fixed_size; assembly { r.offset := offset r.length := length } } uint256 constant memo_fee_pos = memo_data_pos; uint256 constant memo_fee_size = 8; uint256 constant memo_fee_mask = (1 << (memo_fee_size * 8)) - 1; function _memo_fee() internal pure returns (uint256 r) { r = _loaduint256(memo_fee_pos + memo_fee_size - uint256_size) & memo_fee_mask; } // Withdraw specific data uint256 constant memo_native_amount_pos = memo_fee_pos + memo_fee_size; uint256 constant memo_native_amount_size = 8; uint256 constant memo_native_amount_mask = (1 << (memo_native_amount_size * 8)) - 1; function _memo_native_amount() internal pure returns (uint256 r) { r = _loaduint256(memo_native_amount_pos + memo_native_amount_size - uint256_size) & memo_native_amount_mask; } uint256 constant memo_receiver_pos = memo_native_amount_pos + memo_native_amount_size; uint256 constant memo_receiver_size = 20; function _memo_receiver() internal pure returns (address r) { r = address(uint160(_loaduint256(memo_receiver_pos + memo_receiver_size - uint256_size))); } // Permittable token deposit specific data uint256 constant memo_permit_deadline_pos = memo_fee_pos + memo_fee_size; uint256 constant memo_permit_deadline_size = 8; function _memo_permit_deadline() internal pure returns (uint64 r) { r = uint64(_loaduint256(memo_permit_deadline_pos + memo_permit_deadline_size - uint256_size)); } uint256 constant memo_permit_holder_pos = memo_permit_deadline_pos + memo_permit_deadline_size; uint256 constant memo_permit_holder_size = 20; function _memo_permit_holder() internal pure returns (address r) { r = address(uint160(_loaduint256(memo_permit_holder_pos + memo_permit_holder_size - uint256_size))); } }
// SPDX-License-Identifier: CC0-1.0 pragma solidity 0.8.15; interface IKycProvidersManager { function getIfKYCpassedAndTier(address _user) external view returns (bool, uint8); }
// SPDX-License-Identifier: CC0-1.0 pragma solidity 0.8.15; import "@openzeppelin/contracts/utils/Address.sol"; import "../../interfaces/IKycProvidersManager.sol"; import "../../utils/Ownable.sol"; contract KycProvidersManagerStorage is Ownable { // In order to avoid shifting storage slots by defining a new variable in // the contract, KYC Providers Manager will be accessed through specifying // a free slot explicitly. Similar approach is used in EIP1967. // // bytes32(uint256(keccak256('zkBob.ZkBobAccounting.kycProvidersManager')) - 1) uint256 internal constant KYC_PROVIDER_MANAGER_STORAGE = 0x06c991646992b7f0f3fd0c832eac3f519e26682bcb82fbbcfd1ff8013d876f64; event UpdateKYCProvidersManager(address manager); /** * @dev Tells the KYC Providers Manager contract address. * @return res the manager address. */ function kycProvidersManager() public view returns (IKycProvidersManager res) { assembly { res := sload(KYC_PROVIDER_MANAGER_STORAGE) } } /** * @dev Updates kyc providers manager contract. * Callable only by the contract owner / proxy admin. * @param _kycProvidersManager new operator manager implementation. */ function setKycProvidersManager(IKycProvidersManager _kycProvidersManager) external onlyOwner { require(Address.isContract(address(_kycProvidersManager)), "KycProvidersManagerStorage: not a contract"); assembly { sstore(KYC_PROVIDER_MANAGER_STORAGE, _kycProvidersManager) } emit UpdateKYCProvidersManager(address(_kycProvidersManager)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/Math.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @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; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv( uint256 x, uint256 y, uint256 denominator, Rounding rounding ) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10**64) { value /= 10**64; result += 64; } if (value >= 10**32) { value /= 10**32; result += 32; } if (value >= 10**16) { value /= 10**16; result += 16; } if (value >= 10**8) { value /= 10**8; result += 8; } if (value >= 10**4) { value /= 10**4; result += 4; } if (value >= 10**2) { value /= 10**2; result += 2; } if (value >= 10**1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0); } } }
{ "remappings": [ "@base58-solidity/=lib/base58-solidity/contracts/", "@gnosis/=lib/@gnosis/", "@gnosis/auction/=lib/@gnosis/auction/contracts/", "@openzeppelin/=lib/@openzeppelin/contracts/", "@openzeppelin/contracts/=lib/@openzeppelin/contracts/contracts/", "@uniswap/=lib/@uniswap/", "base58-solidity/=lib/base58-solidity/contracts/", "ds-test/=lib/forge-std/lib/ds-test/src/", "forge-std/=lib/forge-std/src/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "bytecodeHash": "ipfs" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "london", "libraries": { "lib/base58-solidity/contracts/Base58.sol": { "Base58": "0xcb11bf4543efeb83d7d2fb99f6b9dd040d7a6eaa" }, "src/libraries/ZkAddress.sol": { "ZkAddress": "0x43830a424783657b92913bef78ec839d2085fcf9" } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"uint256","name":"__pool_id","type":"uint256"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"contract ITransferVerifier","name":"_transfer_verifier","type":"address"},{"internalType":"contract ITreeVerifier","name":"_tree_verifier","type":"address"},{"internalType":"contract IBatchDepositVerifier","name":"_batch_deposit_verifier","type":"address"},{"internalType":"address","name":"_direct_deposit_queue","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":true,"internalType":"bytes32","name":"hash","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"message","type":"bytes"}],"name":"Message","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"manager","type":"address"}],"name":"UpdateKYCProvidersManager","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint8","name":"tier","type":"uint8"},{"components":[{"internalType":"uint56","name":"tvlCap","type":"uint56"},{"internalType":"uint32","name":"dailyDepositCap","type":"uint32"},{"internalType":"uint32","name":"dailyWithdrawalCap","type":"uint32"},{"internalType":"uint32","name":"dailyUserDepositCap","type":"uint32"},{"internalType":"uint32","name":"depositCap","type":"uint32"},{"internalType":"uint32","name":"directDepositCap","type":"uint32"},{"internalType":"uint32","name":"dailyUserDirectDepositCap","type":"uint32"}],"indexed":false,"internalType":"struct ZkBobAccounting.TierLimits","name":"limits","type":"tuple"}],"name":"UpdateLimits","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"manager","type":"address"}],"name":"UpdateOperatorManager","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint8","name":"tier","type":"uint8"}],"name":"UpdateTier","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"seller","type":"address"}],"name":"UpdateTokenSeller","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"}],"name":"WithdrawFee","type":"event"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"accumulatedFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"all_messages_hash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_root_after","type":"uint256"},{"internalType":"uint256[]","name":"_indices","type":"uint256[]"},{"internalType":"uint256","name":"_out_commit","type":"uint256"},{"internalType":"uint256[8]","name":"_batch_deposit_proof","type":"uint256[8]"},{"internalType":"uint256[8]","name":"_tree_proof","type":"uint256[8]"}],"name":"appendDirectDeposits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"batch_deposit_verifier","outputs":[{"internalType":"contract IBatchDepositVerifier","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"denominator","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"direct_deposit_queue","outputs":[{"internalType":"contract IZkBobDirectDepositQueue","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"getLimitsFor","outputs":[{"components":[{"internalType":"uint256","name":"tvlCap","type":"uint256"},{"internalType":"uint256","name":"tvl","type":"uint256"},{"internalType":"uint256","name":"dailyDepositCap","type":"uint256"},{"internalType":"uint256","name":"dailyDepositCapUsage","type":"uint256"},{"internalType":"uint256","name":"dailyWithdrawalCap","type":"uint256"},{"internalType":"uint256","name":"dailyWithdrawalCapUsage","type":"uint256"},{"internalType":"uint256","name":"dailyUserDepositCap","type":"uint256"},{"internalType":"uint256","name":"dailyUserDepositCapUsage","type":"uint256"},{"internalType":"uint256","name":"depositCap","type":"uint256"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint256","name":"dailyUserDirectDepositCap","type":"uint256"},{"internalType":"uint256","name":"dailyUserDirectDepositCapUsage","type":"uint256"},{"internalType":"uint256","name":"directDepositCap","type":"uint256"}],"internalType":"struct ZkBobAccounting.Limits","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_root","type":"uint256"},{"internalType":"uint256","name":"_tvlCap","type":"uint256"},{"internalType":"uint256","name":"_dailyDepositCap","type":"uint256"},{"internalType":"uint256","name":"_dailyWithdrawalCap","type":"uint256"},{"internalType":"uint256","name":"_dailyUserDepositCap","type":"uint256"},{"internalType":"uint256","name":"_depositCap","type":"uint256"},{"internalType":"uint256","name":"_dailyUserDirectDepositCap","type":"uint256"},{"internalType":"uint256","name":"_directDepositCap","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"kycProvidersManager","outputs":[{"internalType":"contract IKycProvidersManager","name":"res","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"migrationToUSDC","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"nullifiers","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"operatorManager","outputs":[{"internalType":"contract IOperatorManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pool_id","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pool_index","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_sender","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"recordDirectDeposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"_tier","type":"uint8"}],"name":"resetDailyLimits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"roots","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IKycProvidersManager","name":"_kycProvidersManager","type":"address"}],"name":"setKycProvidersManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"_tier","type":"uint8"},{"internalType":"uint256","name":"_tvlCap","type":"uint256"},{"internalType":"uint256","name":"_dailyDepositCap","type":"uint256"},{"internalType":"uint256","name":"_dailyWithdrawalCap","type":"uint256"},{"internalType":"uint256","name":"_dailyUserDepositCap","type":"uint256"},{"internalType":"uint256","name":"_depositCap","type":"uint256"},{"internalType":"uint256","name":"_dailyUserDirectDepositCap","type":"uint256"},{"internalType":"uint256","name":"_directDepositCap","type":"uint256"}],"name":"setLimits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IOperatorManager","name":"_operatorManager","type":"address"}],"name":"setOperatorManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_seller","type":"address"}],"name":"setTokenSeller","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"_tier","type":"uint8"},{"internalType":"address[]","name":"_users","type":"address[]"}],"name":"setUsersTier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenSeller","outputs":[{"internalType":"contract ITokenSeller","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"transact","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"transfer_verifier","outputs":[{"internalType":"contract ITransferVerifier","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tree_verifier","outputs":[{"internalType":"contract ITreeVerifier","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_operator","type":"address"},{"internalType":"address","name":"_to","type":"address"}],"name":"withdrawFee","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
6101806040523480156200001257600080fd5b506040516200608338038062006083833981016040819052620000359162000351565b8585858585856001633b9aca00806200004e33620002d9565b60805262ffffff881115620000aa5760405162461bcd60e51b815260206004820152601e60248201527f5a6b426f62506f6f6c3a2065786365656473206d617820706f6f6c206964000060448201526064015b60405180910390fd5b620000c0876200032960201b6200249e1760201c565b620000fd5760405162461bcd60e51b81526020600482015260196024820152600080516020620060638339815191526044820152606401620000a1565b62000113866200032960201b6200249e1760201c565b620001505760405162461bcd60e51b81526020600482015260196024820152600080516020620060638339815191526044820152606401620000a1565b62000166856200032960201b6200249e1760201c565b620001a35760405162461bcd60e51b81526020600482015260196024820152600080516020620060638339815191526044820152606401620000a1565b620001b9846200032960201b6200249e1760201c565b620001f65760405162461bcd60e51b81526020600482015260196024820152600080516020620060638339815191526044820152606401620000a1565b6200020c836200032960201b6200249e1760201c565b620002495760405162461bcd60e51b81526020600482015260196024820152600080516020620060638339815191526044820152606401620000a1565b816001146200029b5760405162461bcd60e51b815260206004820181905260248201527f5a6b426f62506f6f6c3a20696e636f72726563742064656e6f6d696e61746f726044820152606401620000a1565b5060c0969096526001600160a01b039485166101405292841660e05290831661010052821661012052166101605260a05250620003d9945050505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03163b151590565b6001600160a01b03811681146200034e57600080fd5b50565b60008060008060008060c087890312156200036b57600080fd5b8651955060208701516200037f8162000338565b6040880151909550620003928162000338565b6060880151909450620003a58162000338565b6080880151909350620003b88162000338565b60a0880151909250620003cb8162000338565b809150509295509295509295565b60805160a05160c05160e05161010051610120516101405161016051615ab1620005b2600039600081816102a7015281816104ed01526106370152600081816104c00152818161191901528181611ae101528181611d3501528181611e9801528181611fc10152818161211c0152818161235c01528181613ad80152613be901526000818161039c015261070e0152600081816102e10152818161081b01526115a301526000818161024101526114a30152600081816103ea0152613723015260008181610fa601528181610fdd015281816110140152818161104b01528181611082015281816110b9015281816110f0015281816118e001528181611a2f01528181611a73015281816122ce015281816124030152613c18015260008181610baa01528181610bfb01528181610c6501528181610ccf01528181610d3901528181610d7d01528181610de7015281816125e0015281816126e401528181612ae101528181612e3b01528181612ec601528181612f58015281816131e401528181613221015281816132560152818161328b015281816132c0015281816132f50152818161332a01528181614029015281816140c00152818161429801528181614444015281816144f701526146150152615ab16000f3fe608060405234801561001057600080fd5b50600436106101e45760003560e01c80637a22393b1161010f578063c41100fa116100a2578063e0ec037411610071578063e0ec037414610482578063e8fd02e414610495578063f2fde38b146104a8578063fc0c546a146104bb57600080fd5b8063c41100fa14610434578063c4a688b814610447578063c879c6d81461044f578063d21e82ab1461046257600080fd5b806396ce0795116100de57806396ce0795146103d75780639d8ad6e4146103e5578063af9890831461040c578063c2b40ae41461041457600080fd5b80637a22393b1461038457806383f26e3b146103975780638da5cb5b146103be5780638fff4676146103cf57600080fd5b80632f84c96f11610187578063508400401161015657806350840040146103365780636d55160c14610356578063715018a614610369578063790c3a331461037157600080fd5b80632f84c96f146102c95780633701f979146102dc5780634279a99e1461030357806346adf6ce1461032357600080fd5b80631cbec711116101c35780631cbec711146102635780631dc4cb33146102785780631dd69d061461028b5780632747f41d146102a257600080fd5b80622befce146101e95780630c6248de14610229578063171ef3001461023c575b600080fd5b7f06c991646992b7f0f3fd0c832eac3f519e26682bcb82fbbcfd1ff8013d876f64545b6040516001600160a01b0390911681526020015b60405180910390f35b600b5461020c906001600160a01b031681565b61020c7f000000000000000000000000000000000000000000000000000000000000000081565b610276610271366004614eee565b6104e2565b005b610276610286366004614fcf565b610569565b61029460095481565b604051908152602001610220565b61020c7f000000000000000000000000000000000000000000000000000000000000000081565b60065461020c906001600160a01b031681565b61020c7f000000000000000000000000000000000000000000000000000000000000000081565b61031661031136600461507c565b6109c0565b6040516102209190615099565b610276610331366004615146565b610e2b565b61029461034436600461507c565b600a6020526000908152604090205481565b610276610364366004615163565b610e5e565b61027661112e565b61027661037f36600461507c565b611142565b61027661039236600461507c565b611218565b61020c7f000000000000000000000000000000000000000000000000000000000000000081565b6000546001600160a01b031661020c565b61029461126e565b6103e8600160ff1b01610294565b6102947f000000000000000000000000000000000000000000000000000000000000000081565b610276611295565b6102946104223660046151b8565b60086020526000908152604090205481565b61027661044236600461507c565b611c39565b610276611cf0565b61027661045d3660046151d1565b6121dd565b6102946104703660046151b8565b60076020526000908152604090205481565b61027661049036600461520a565b6123dd565b6102766104a33660046152d1565b6123ef565b6102766104b636600461507c565b612428565b61020c7f000000000000000000000000000000000000000000000000000000000000000081565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461055b5760405162461bcd60e51b8152602060048201526019602482015278169ad09bd8941bdbdb0e881b9bdd08185d5d1a1bdc9a5e9959603a1b60448201526064015b60405180910390fd5b61056582826124ad565b5050565b6006546001600160a01b0316636d70f7ae336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa1580156105bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e39190615344565b61062f5760405162461bcd60e51b815260206004820152601a60248201527f5a6b426f62506f6f6c3a206e6f7420616e206f70657261746f720000000000006044820152606401610552565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e24546f28a8a8a6040518463ffffffff1660e01b81526004016106859392919061535f565b6000604051808303816000875af11580156106a4573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526106cc91908101906153d1565b935093509350935060006106e160008661282f565b604080516020810182528781529051633cac775b60e01b8152919450600785901b93506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169250633cac775b9161074591908c906004016154a5565b602060405180830381865afa158015610762573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107869190615344565b6107dd5760405162461bcd60e51b815260206004820152602260248201527f5a6b426f62506f6f6c3a20626164206261746368206465706f7369742070726f60448201526137b360f11b6064820152608401610552565b604080516060810182526000838152600860209081529083902054825281018e90528082018b905290516345bb94c160e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906345bb94c1906108529084908c90600401615501565b602060405180830381865afa15801561086f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108939190615344565b6108db5760405162461bcd60e51b81526020600482015260196024820152782d35a137b12837b7b61d103130b2103a3932b290383937b7b360391b6044820152606401610552565b6108e6608083615533565b91508c600860008481526020019081526020016000208190555060008480519060200120905060006009548260405160200161092c929190918252602082015260400190565b60408051601f19818403018152919052805160209091012060098190559050871561097657336000908152600a6020526040812080548a9290610970908490615533565b90915550505b80847f7d39f8a6bc8929456fba511441be7361aa014ac6f8e21b99990ce9e1c7373536886040516109a79190615577565b60405180910390a3505050505050505050505050505050565b610a2e604051806101a00160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600060ff1681526020016000815260200160008152602001600081525090565b60408051602080820183526002546001600160481b0390811683526001600160a01b0386166000908152600583528481208551608081018752905461ffff8116825262010000810484169482019490945260ff600160581b850416958101869052600160601b90930490911660608301529192909190610aaf908690612c28565b60ff81166000908152600360209081526040808320815160e081018352815466ffffffffffffff8116825263ffffffff600160381b8204811683870152600160581b808304821684870152600160781b83048216606080860191909152600160981b840483166080860152600160b81b8404831660a0860152600160d81b90930490911660c084015284519182018552600184015461ffff811683526001600160481b03620100008204811697840197909752049094169284019290925293945091610b7d610e10426155a0565b90506000610b90610e10620151806155a0565b610b9a90836155b4565b9050604051806101a001604052807f0000000000000000000000000000000000000000000000000000000000000000866000015166ffffffffffffff16610be191906155d6565b815260200189600001516001600160481b031681526020017f0000000000000000000000000000000000000000000000000000000000000000866020015163ffffffff16610c2f91906155d6565b81526020018262ffffff16856000015161ffff1614610c4f576000610c55565b84602001515b6001600160481b031681526020017f0000000000000000000000000000000000000000000000000000000000000000866040015163ffffffff16610c9991906155d6565b81526020018262ffffff16856000015161ffff1614610cb9576000610cbf565b84604001515b6001600160481b031681526020017f0000000000000000000000000000000000000000000000000000000000000000866060015163ffffffff16610d0391906155d6565b81526020018262ffffff16896000015161ffff1614610d23576000610d29565b88602001515b6001600160481b031681526020017f0000000000000000000000000000000000000000000000000000000000000000866080015163ffffffff16610d6d91906155d6565b81526020018760ff1681526020017f00000000000000000000000000000000000000000000000000000000000000008660c0015163ffffffff16610db191906155d6565b81526020018262ffffff16896000015161ffff1614610dd1576000610dd7565b88606001515b6001600160481b031681526020017f00000000000000000000000000000000000000000000000000000000000000008660a0015163ffffffff16610e1b91906155d6565b90529a9950505050505050505050565b610e33612d29565b610e5b8160ff16600090815260036020526040902060010180546001600160a01b0319169055565b50565b333014610ead5760405162461bcd60e51b815260206004820152601a60248201527f5a6b426f62506f6f6c3a206e6f7420696e697469616c697a65720000000000006044820152606401610552565b6000805260086020527f5eff886ea0ce6ca488a3d6e336d6c0f75f46d19b42c06ce5ee98e42c96d256c75415610f255760405162461bcd60e51b815260206004820152601e60248201527f5a6b426f62506f6f6c3a20616c726561647920696e697469616c697a656400006044820152606401610552565b87600003610f6c5760405162461bcd60e51b8152602060048201526014602482015273169ad09bd8941bdbdb0e881e995c9bc81c9bdbdd60621b6044820152606401610552565b600080805260086020527f5eff886ea0ce6ca488a3d6e336d6c0f75f46d19b42c06ce5ee98e42c96d256c7899055611124906103e8610fcb7f00000000000000000000000000000000000000000000000000000000000000008b6155a0565b610fd591906155d6565b6103e86110027f00000000000000000000000000000000000000000000000000000000000000008b6155a0565b61100c91906155d6565b6103e86110397f00000000000000000000000000000000000000000000000000000000000000008b6155a0565b61104391906155d6565b6103e86110707f00000000000000000000000000000000000000000000000000000000000000008b6155a0565b61107a91906155d6565b6103e86110a77f00000000000000000000000000000000000000000000000000000000000000008b6155a0565b6110b191906155d6565b6103e86110de7f00000000000000000000000000000000000000000000000000000000000000008b6155a0565b6110e891906155d6565b6103e86111157f00000000000000000000000000000000000000000000000000000000000000008b6155a0565b61111f91906155d6565b612d7d565b5050505050505050565b611136612d29565b61114060006134eb565b565b61114a612d29565b6001600160a01b0381163b6111b45760405162461bcd60e51b815260206004820152602a60248201527f4b796350726f7669646572734d616e6167657253746f726167653a206e6f7420604482015269184818dbdb9d1c9858dd60b21b6064820152608401610552565b7f06c991646992b7f0f3fd0c832eac3f519e26682bcb82fbbcfd1ff8013d876f648190556040516001600160a01b03821681527fcfca215f2134266880a5d2c68d2f52493a9d57fe6dd1245086a201e78871348e906020015b60405180910390a150565b611220612d29565b600b80546001600160a01b0319166001600160a01b0383169081179091556040519081527fdf71641930ea322cb32f687f4d292a0af694c81216254f204c930092593d82829060200161120d565b6000600761128960015463ffffffff600160e01b9091041690565b901b905090565b905090565b6006546001600160a01b0316636d70f7ae336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa1580156112eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061130f9190615344565b61135b5760405162461bcd60e51b815260206004820152601a60248201527f5a6b426f62506f6f6c3a206e6f7420616e206f70657261746f720000000000006044820152606401610552565b33600061136661353b565b90508060000361137f576113786135db565b91506113a2565b8060020361138f5761137861365c565b806003036113a25761139f61365c565b91505b60006113ac6136a9565b60070b905060006113bd848361282f565b9250505060006113cc60043590565b60008181526007602081905260409091205491925083901b90156114325760405162461bcd60e51b815260206004820152601f60248201527f5a6b426f62506f6f6c3a20646f75626c657370656e64206465746563746564006044820152606401610552565b8061143b6136c2565b65ffffffffffff1611156114a15760405162461bcd60e51b815260206004820152602760248201527f5a6b426f62506f6f6c3a207472616e7366657220696e646578206f7574206f6660448201526620626f756e647360c81b6064820152608401610552565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166368444dc76114d86136d7565b6114e06137ad565b6040518363ffffffff1660e01b81526004016114fd9291906155f5565b602060405180830381865afa15801561151a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061153e9190615344565b61158a5760405162461bcd60e51b815260206004820152601d60248201527f5a6b426f62506f6f6c3a20626164207472616e736665722070726f6f660000006044820152606401610552565b6000818152600860205260409020546001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906345bb94c1906115d3906137eb565b6115db613815565b6040518363ffffffff1660e01b81526004016115f8929190615635565b602060405180830381865afa158015611615573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116399190615344565b6116815760405162461bcd60e51b81526020600482015260196024820152782d35a137b12837b7b61d103130b2103a3932b290383937b7b360391b6044820152606401610552565b611689613843565b611691613854565b60408051602081019390935282015260600160408051601f198184030181529181528151602092830120600085815260079093529120556116d3608082615533565b90506116dd6138b3565b6000828152600860205260408120919091556116f7613900565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092018290525093945061173992508491506156589050565b61ffff60e01b161461178d5760405162461bcd60e51b815260206004820152601d60248201527f5a6b426f62506f6f6c3a20626164206d657373616765207072656669780000006044820152606401610552565b6000818051906020012090506000600954826040516020016117b9929190918252602082015260400190565b6040516020818303038152906040528051906020012090508060098190555080847f7d39f8a6bc8929456fba511441be7361aa014ac6f8e21b99990ce9e1c7373536856040516118099190615577565b60405180910390a350505050600061181f6139b3565b9050600061182d828661568f565b905060006118396139f0565b600d0b905061184a6103e8836156d0565b156118a15760405162461bcd60e51b815260206004820152602160248201527f5a6b426f62506f6f6c3a20696e636f727265637420746f6b656e20616d6f756e6044820152601d60fa1b6064820152608401610552565b86600003611946576000861380156118b7575080155b6118d35760405162461bcd60e51b8152600401610552906156e4565b61194188306103e86119057f0000000000000000000000000000000000000000000000000000000000000000876155d6565b61190f91906155a0565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016929190613a07565b611c05565b866001036119b4578115801561195a575080155b6119415760405162461bcd60e51b815260206004820152602560248201527f5a6b426f62506f6f6c3a20696e636f7272656374207472616e7366657220616d6044820152646f756e747360d81b6064820152608401610552565b86600203611b7257600082131580156119ce575060008113155b611a285760405162461bcd60e51b815260206004820152602560248201527f5a6b426f62506f6f6c3a20696e636f727265637420776974686472617720616d6044820152646f756e747360d81b6064820152608401610552565b60006103e87f0000000000000000000000000000000000000000000000000000000000000000611a56613a78565b611a6091906155d6565b611a6a91906155a0565b905060006103e87f0000000000000000000000000000000000000000000000000000000000000000611a9b86615728565b611aa591906155d6565b611aaf91906155a0565b90508115611ace57611ac18a83613ab6565b611acb9082615744565b90505b8015611b0857611b086001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168b83613b96565b6000831215611b6b5760405162461bcd60e51b815260206004820152602960248201527f5a6b426f62506f6f6c3a20585020636c61696d696e67206973206e6f742079656044820152681d08195b98589b195960ba1b6064820152608401610552565b5050611c05565b86600303611baf57600086138015611b88575080155b611ba45760405162461bcd60e51b8152600401610552906156e4565b611941888584613bcb565b60405162461bcd60e51b815260206004820152602560248201527f5a6b426f62506f6f6c3a20496e636f7272656374207472616e73616374696f6e604482015264207479706560d81b6064820152608401610552565b821561112457336000908152600a602052604081208054859290611c2a908490615533565b90915550505050505050505050565b611c41612d29565b6001600160a01b038116611ca25760405162461bcd60e51b815260206004820152602260248201527f5a6b426f62506f6f6c3a206d616e61676572206973207a65726f206164647265604482015261737360f01b6064820152608401610552565b600680546001600160a01b0319166001600160a01b0383169081179091556040519081527f267052ecaebdd552dc1b20904f59d83d51ae7add7514165322a7da9ef6cf543b9060200161120d565b333014611d335760405162461bcd60e51b815260206004820152601160248201527024b731b7b93932b1ba1034b73b37b5b2b960791b6044820152606401610552565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316732791bca1f2de4661ed88a30c99a7a9449aa8417414611db15760405162461bcd60e51b815260206004820152600f60248201526e24b731b7b93932b1ba103a37b5b2b760891b6044820152606401610552565b6040516370a0823160e01b815230600482015273b0b195aefa3650a6908f15cdac7d92f8a5791b0b9060009082906370a0823190602401602060405180830381865afa158015611e05573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e29919061575b565b90506000826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e8f9190615774565b60ff16905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ef4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f189190615774565b60405163095ea7b360e01b81527325e6505297b44f4817538fb2d91b88e1cf841b54600482018190526024820186905260ff9290921692506000906001600160a01b0387169063095ea7b3906044016020604051808303816000875af1158015611f86573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611faa9190615344565b604051636c197ff560e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260248201889052919250600091841690636c197ff5906044016020604051808303816000875af115801561201f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612043919061575b565b6040516370a0823160e01b81523060048201529091506001600160a01b038816906370a0823190602401602060405180830381865afa15801561208a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120ae919061575b565b156120ec5760405162461bcd60e51b815260206004820152600e60248201526d0496e636f727265637420737761760941b6044820152606401610552565b6000816120f98688615744565b61210490600a615875565b61210e90896155a0565b6121189190615744565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166323b872dd61215b6000546001600160a01b031690565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152306024820152604481018490526064016020604051808303816000875af11580156121ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121d29190615344565b505050505050505050565b6001600160a01b0382163314806122635750600654604051632bb6fe4d60e21b81526001600160a01b0384811660048301523360248301529091169063aedbf93490604401602060405180830381865afa15801561223f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122639190615344565b6122ab5760405162461bcd60e51b8152602060048201526019602482015278169ad09bd8941bdbdb0e881b9bdd08185d5d1a1bdc9a5e9959603a1b6044820152606401610552565b6001600160a01b0382166000908152600a60205260408120546103e8906122f3907f0000000000000000000000000000000000000000000000000000000000000000906155d6565b6122fd91906155a0565b90506000811161234f5760405162461bcd60e51b815260206004820152601d60248201527f5a6b426f62506f6f6c3a206e6f2066656520746f2077697468647261770000006044820152606401610552565b6123836001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168383613b96565b6001600160a01b0383166000818152600a602052604080822091909155517f66bf9186b00db666fc37aaffbb95a050c66e599e000c785c1dff0467d868f1b1906123d09084815260200190565b60405180910390a2505050565b6123e5612d29565b6105658282613cf7565b6123f7612d29565b611124886103e8610fcb7f00000000000000000000000000000000000000000000000000000000000000008b6155a0565b612430612d29565b6001600160a01b0381166124955760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610552565b610e5b816134eb565b6001600160a01b03163b151590565b60006124be610e10620151806155a0565b6124ca610e10426155a0565b6124d491906155a0565b6001600160a01b03841660009081526005602090815260408083208151608081018352905461ffff811682526001600160481b0362010000820481169483019490945260ff600160581b820416928201839052600160601b9004909216606083015292935091600390829061254a908890612c28565b60ff1681526020808201929092526040908101600020815160e081018352905466ffffffffffffff8116825263ffffffff600160381b8204811694830194909452600160581b8104841692820192909252600160781b820483166060820152600160981b820483166080820152600160b81b8204831660a08201819052600160d81b90920490921660c0830152909150612605907f0000000000000000000000000000000000000000000000000000000000000000906155d6565b8411156126705760405162461bcd60e51b815260206004820152603360248201527f5a6b426f624163636f756e74696e673a2073696e676c65206469726563742064604482015272195c1bdcda5d0818d85c08195e18d959591959606a1b6064820152608401610552565b816000015161ffff168361ffff1611156126bb576040805160808101825261ffff85168152600060208201529281015160ff16908301526001600160481b0384166060830152612791565b83826060018181516126cd9190615881565b6001600160481b031690525060c081015161270f907f00000000000000000000000000000000000000000000000000000000000000009063ffffffff166155d6565b82606001516001600160481b031611156127915760405162461bcd60e51b815260206004820152603760248201527f5a6b426f624163636f756e74696e673a206461696c792075736572206469726560448201527f6374206465706f736974206361702065786365656465640000000000000000006064820152608401610552565b506001600160a01b039390931660009081526005602090815260409182902085518154928701519387015160609097015161ffff9091166001600160581b031990931692909217620100006001600160481b03948516021769ffffffffffffffffffff60581b1916600160581b60ff9097169690960268ffffffffffffffffff60601b191695909517600160601b9290911691909102179092555050565b6040805160c08101825260015466ffffffffffffff8116825263ffffffff600160381b8204811660208085019190915262ffffff600160581b8404811685870152600160701b84041660608501526001600160581b03600160881b8404166080850152600160e01b9092041660a083015282519081019092526002546001600160481b0316825260009182918291826128ca610e10426155a0565b60a084015163ffffffff1694509050831580159061290857506128f2610e1062093a806155a0565b604084015161290190836158ac565b62ffffff16115b15612a1e576040838101805162ffffff9081166000908152600460208181528583208651606081018852905480861682526301000000810463ffffffff16828401908152600160381b9091046001600160581b03168289015286518616855292909152948220805471ffffffffffffffffffffffffffffffffffff1916905584519092169092525160a086015161299f91906158d0565b9050846020015163ffffffff168163ffffffff1611156129c65763ffffffff811660208601525b60008163ffffffff16836040015187608001516129e391906158ed565b6129ed919061590d565b9050856000015166ffffffffffffff168166ffffffffffffff161115612a1a5766ffffffffffffff811686525b5050505b8062ffffff16836060015162ffffff161015612ad957604080516060808201835262ffffff80851680845260a088015163ffffffff908116602080870191825260808b01516001600160581b03908116888a01908152968c018051871660009081526004909352989091209651875492519651909116600160381b0271ffffffffffffffffffffff00000000000000199690931663010000000266ffffffffffffff1990921694169390931792909217929092161790915590525b8151612b06907f000000000000000000000000000000000000000000000000000000000000000090615927565b6001600160481b031683608001818151612b209190615941565b6001600160581b031690525060a08301805190612b3c82615963565b63ffffffff169052508615612b5657612b56828989613e32565b5050805160018054602084015160408501516060860151608087015160a09097015166ffffffffffffff87166001600160581b031990951694909417600160381b63ffffffff808616919091029190911765ffffffffffff60581b1916600160581b62ffffff9485160262ffffff60701b191617600160701b93909216929092021770ffffffffffffffffffffffffffffffffff16600160881b6001600160581b03909716969096026001600160e01b031695909517600160e01b959092169490940217905596909550909350915050565b600080612c537f06c991646992b7f0f3fd0c832eac3f519e26682bcb82fbbcfd1ff8013d876f645490565b905060ff8316158015612c6e57506001600160a01b03811615155b15612d1e57604051630a364e7560e41b81526001600160a01b038581166004830152600091829184169063a364e750906024016040805180830381865afa158015612cbd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ce19190615986565b91509150818015612d0c575060ff811660009081526003602052604090205466ffffffffffffff1615155b15612d1b579250612d23915050565b50505b829150505b92915050565b612d31614736565b6111405760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610552565b60ff8860ff1610612ddc5760405162461bcd60e51b815260206004820152602360248201527f5a6b426f624163636f756e74696e673a20696e76616c6964206c696d6974207460448201526234b2b960e91b6064820152608401610552565b60008311612e365760405162461bcd60e51b815260206004820152602160248201527f5a6b426f624163636f756e74696e673a207a65726f206465706f7369742063616044820152600760fc1b6064820152608401610552565b612e677f000000000000000000000000000000000000000000000000000000000000000066ffffffffffffff6155d6565b871115612ec15760405162461bcd60e51b815260206004820152602260248201527f5a6b426f624163636f756e74696e673a2074766c2063617020746f6f206c6172604482015261676560f01b6064820152608401610552565b612eef7f000000000000000000000000000000000000000000000000000000000000000063ffffffff6155d6565b861115612f535760405162461bcd60e51b815260206004820152602c60248201527f5a6b426f624163636f756e74696e673a206461696c79206465706f736974206360448201526b617020746f6f206c6172676560a01b6064820152608401610552565b612f817f000000000000000000000000000000000000000000000000000000000000000063ffffffff6155d6565b851115612fe85760405162461bcd60e51b815260206004820152602f60248201527f5a6b426f624163636f756e74696e673a206461696c792077697468647261776160448201526e6c2063617020746f6f206c6172676560881b6064820152608401610552565b828410156130505760405162461bcd60e51b815260206004820152602f60248201527f5a6b426f624163636f756e74696e673a206461696c792075736572206465706f60448201526e7369742063617020746f6f206c6f7760881b6064820152608401610552565b838610156130b35760405162461bcd60e51b815260206004820152602a60248201527f5a6b426f624163636f756e74696e673a206461696c79206465706f7369742063604482015269617020746f6f206c6f7760b01b6064820152608401610552565b858710156131035760405162461bcd60e51b815260206004820181905260248201527f5a6b426f624163636f756e74696e673a2074766c2063617020746f6f206c6f776044820152606401610552565b600085116131665760405162461bcd60e51b815260206004820152602a60248201527f5a6b426f624163636f756e74696e673a207a65726f206461696c792077697468604482015269064726177616c206361760b41b6064820152608401610552565b808210156131d55760405162461bcd60e51b815260206004820152603660248201527f5a6b426f624163636f756e74696e673a206461696c79207573657220646972656044820152756374206465706f7369742063617020746f6f206c6f7760501b6064820152608401610552565b60006040518060e001604052807f00000000000000000000000000000000000000000000000000000000000000008a61320e91906155a0565b66ffffffffffffff1681526020016132467f00000000000000000000000000000000000000000000000000000000000000008a6155a0565b63ffffffff16815260200161327b7f0000000000000000000000000000000000000000000000000000000000000000896155a0565b63ffffffff1681526020016132b07f0000000000000000000000000000000000000000000000000000000000000000886155a0565b63ffffffff1681526020016132e57f0000000000000000000000000000000000000000000000000000000000000000876155a0565b63ffffffff16815260200161331a7f0000000000000000000000000000000000000000000000000000000000000000856155a0565b63ffffffff16815260200161334f7f0000000000000000000000000000000000000000000000000000000000000000866155a0565b63ffffffff90811690915260ff8b16600081815260036020908152604091829020855181549287015184880151606089015160808a015160a08b015160c08c01518b16600160d81b0263ffffffff60d81b19918c16600160b81b0263ffffffff60b81b19938d16600160981b029390931667ffffffffffffffff60981b19948d16600160781b0263ffffffff60781b19968e16600160581b029690961667ffffffffffffffff60581b1997909d16600160381b026001600160581b0319909a1666ffffffffffffff909816979097179890981794909416999099179190911716919091179590951794909416179092559051919250907f3cb26612e7105331adad836a65ae9b7f1d30a9e469ec70510a7c7ea36b0185ed906134d8908490600060e08201905066ffffffffffffff8351168252602083015163ffffffff80821660208501528060408601511660408501528060608601511660608501528060808601511660808501528060a08601511660a08501528060c08601511660c0850152505092915050565b60405180910390a2505050505050505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000600161354b600260086155d6565b6001901b6135599190615744565b6135d56020600261010082816008600e600684613577816004615533565b6135819190615533565b61358b9190615533565b6135959190615533565b61359f9190615533565b6135a99190615533565b6135b39190615533565b6135bd9190615533565b6135c79190615533565b6135d19190615744565b3590565b16905090565b60008060006135e861477a565b9150915061365561364e6135fb60043590565b6040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b8383614797565b9250505090565b600061129060206014600880600280610100868185600e600684613681816004615533565b61368b9190615533565b6136959190615533565b61369f9190615533565b6135779190615533565b600061129060206008600e60068361359f816004615533565b600061129060206006816135b3816004615533565b6136df614e9d565b6136e76147bf565b815260043560208201526136f9613843565b6040820152600861370c600e6006615533565b6137169190615533565b6137219060086155d6565b7f0000000000000000000000000000000000000000000000000000000000000000901b61374c613854565b6137569190615533565b60608201527f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016137846147e9565b6040516137929291906159c8565b6040519081900390206137a591906159d8565b608082015290565b3660006008600e600660206137c3816004615533565b6137cd9190615533565b6137d79190615533565b6137e19190615533565b612d239190615533565b6137f3614ebb565b8181526137fe6138b3565b602082015261380b613843565b6040820152919050565b36600060206101006008600e60068461382f816004615533565b6138399190615533565b6137c39190615533565b60006112906135d160206004615533565b600060016008613866600e6006615533565b6138709190615533565b61387b9060086155d6565b6001901b6138899190615744565b6135d56020600861389c600e6006615533565b6138a69190615533565b60206135b3816004615533565b60006112906101006008600e600660206138ce816004615533565b6138d89190615533565b6138e29190615533565b6138ec9190615533565b6138f69190615533565b6135d19190615533565b3660008061390c614879565b90506000816002806101006020816008600e60068461392c816004615533565b6139369190615533565b6139409190615533565b61394a9190615533565b6139549190615533565b61395e9190615533565b6139689190615533565b6139729190615533565b61397c9190615533565b6139869190615533565b6139909190615533565b905060008261399d6148c0565b6139a79190615744565b91959194509092505050565b600060016139c26008806155d6565b6001901b6139d09190615744565b6135d560206008600280610100848185600e600684613695816004615533565b60006112906020600e6006826135a9816004615533565b6040516001600160a01b0380851660248301528316604482015260648101829052613a729085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526148fd565b50505050565b60006001613a876008806155d6565b6001901b613a959190615744565b6135d56020600880600280610100858185600e60068461368b816004615533565b600b546000906001600160a01b03168015613b8c57613aff6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168285613b96565b604051630802e33b60e41b81526001600160a01b038581166004830152602482018590526000919083169063802e33b09060440160408051808303816000875af1158015613b51573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b7591906159ec565b9150613b8390508185615744565b92505050612d23565b5060009392505050565b6040516001600160a01b038316602482015260448101829052613bc690849063a9059cbb60e01b90606401613a3b565b505050565b6000806000613bd86149cf565b919450925090506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663e3ee160e87306103e8613c3d7f00000000000000000000000000000000000000000000000000000000000000008a6155d6565b613c4791906155a0565b6000613c51614a06565b60405160e087901b6001600160e01b03191681526001600160a01b0395861660048201529490931660248501526044840191909152606483015267ffffffffffffffff16608482015260a4810188905260ff861660c482015260e48101859052610104810184905261012401600060405180830381600087803b158015613cd757600080fd5b505af1158015613ceb573d6000803e3d6000fd5b50505050505050505050565b8160ff1660ff1480613d23575060ff821660009081526003602052604090205466ffffffffffffff1615155b613d865760405162461bcd60e51b815260206004820152602e60248201527f5a6b426f624163636f756e74696e673a206e6f6e2d6578697374696e6720706f60448201526d37b6103634b6b4ba39903a34b2b960911b6064820152608401610552565b60005b8151811015613bc6576000828281518110613da657613da66159b2565b6020908102919091018101516001600160a01b038116600081815260058452604090819020805460ff60581b1916600160581b60ff8b16908102919091179091558151928352938201939093529092507f1283ebeb150dffd4da976f64c81e074fd4dc895cb64995dc46f13c9fd96a9551910160405180910390a150613e2b81615a10565b9050613d89565b6001600160a01b038216158015613e495750600081135b15613e955760028054829190600090613e6c9084906001600160481b0316615881565b92506101000a8154816001600160481b0302191690836001600160481b03160217905550505050565b6000613ea6610e10620151806155a0565b613eb2610e10426155a0565b613ebc91906155a0565b6001600160a01b03841660009081526005602090815260408083208151608081018352905461ffff811682526001600160481b0362010000820481169483019490945260ff600160581b820416928201839052600160601b90049092166060830152929350916003908290613f32908890612c28565b60ff16815260208082019290925260409081016000908120825160e081018452815466ffffffffffffff8116825263ffffffff600160381b8204811683880152600160581b808304821684880152600160781b83048216606080860191909152600160981b840483166080860152600160b81b8404831660a0860152600160d81b90930490911660c084015285519182018652600184015461ffff811683526001600160481b03620100008204811698840198909852049095169385019390935293509091908613156144e5578751869081908a90614012908390615881565b6001600160481b03169052506080830151614054907f00000000000000000000000000000000000000000000000000000000000000009063ffffffff166155d6565b8111156140b85760405162461bcd60e51b815260206004820152602c60248201527f5a6b426f624163636f756e74696e673a2073696e676c65206465706f7369742060448201526b18d85c08195e18d95959195960a21b6064820152608401610552565b82516140ee907f00000000000000000000000000000000000000000000000000000000000000009066ffffffffffffff166155d6565b89516001600160481b031611156141515760405162461bcd60e51b815260206004820152602160248201527f5a6b426f624163636f756e74696e673a2074766c2063617020657863656564656044820152601960fa1b6064820152608401610552565b846000015161ffff168661ffff16111561426f5760405180608001604052808761ffff168152602001826001600160481b03168152602001866040015160ff16815260200160006001600160481b0316815250600560008a6001600160a01b03166001600160a01b0316815260200190815260200160002060008201518160000160006101000a81548161ffff021916908361ffff16021790555060208201518160000160026101000a8154816001600160481b0302191690836001600160481b03160217905550604082015181600001600b6101000a81548160ff021916908360ff160217905550606082015181600001600c6101000a8154816001600160481b0302191690836001600160481b031602179055509050506143ce565b80856020018181516142819190615881565b6001600160481b031690525060608301516142c3907f00000000000000000000000000000000000000000000000000000000000000009063ffffffff166155d6565b85602001516001600160481b031611156143385760405162461bcd60e51b815260206004820152603060248201527f5a6b426f624163636f756e74696e673a206461696c792075736572206465706f60448201526f1cda5d0818d85c08195e18d95959195960821b6064820152608401610552565b6001600160a01b03881660009081526005602090815260409182902087518154928901519389015160608a01516001600160481b03908116600160601b0268ffffffffffffffffff60601b1960ff909316600160581b029290921669ffffffffffffffffffff60581b199190961662010000026001600160581b031990951661ffff909316929092179390931716929092171790555b816000015161ffff168661ffff16111561441b5760405180606001604052808761ffff168152602001826001600160481b0316815260200160006001600160481b031681525091506144df565b808260200181815161442d9190615881565b6001600160481b0316905250602083015161446f907f00000000000000000000000000000000000000000000000000000000000000009063ffffffff166155d6565b82602001516001600160481b031611156144df5760405162461bcd60e51b815260206004820152602b60248201527f5a6b426f624163636f756e74696e673a206461696c79206465706f736974206360448201526a185c08195e18d95959195960aa1b6064820152608401610552565b506146b5565b60006144f087615728565b90506145207f000000000000000000000000000000000000000000000000000000000000000063ffffffff6155d6565b8111156145845760405162461bcd60e51b815260206004820152602c60248201527f5a6b426f624163636f756e74696e673a207769746864726177616c20616d6f7560448201526b6e7420746f6f206c6172676560a01b6064820152608401610552565b80896000018181516145969190615a29565b6001600160481b0316905250815161ffff90811690871611156145ec5760405180606001604052808761ffff16815260200160006001600160481b03168152602001826001600160481b031681525091506146b3565b80826040018181516145fe9190615881565b6001600160481b03169052506040830151614640907f00000000000000000000000000000000000000000000000000000000000000009063ffffffff166155d6565b82604001516001600160481b031611156146b35760405162461bcd60e51b815260206004820152602e60248201527f5a6b426f624163636f756e74696e673a206461696c792077697468647261776160448201526d1b0818d85c08195e18d95959195960921b6064820152608401610552565b505b9651600280546001600160481b0392831668ffffffffffffffffff199091161790558751600193909301805460208a01516040909a01518316600160581b0268ffffffffffffffffff60581b199a90931662010000026001600160581b031990911661ffff9095169490941793909317979097169690961790555050505050565b6000614740614a29565b8061129057507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035433905b6001600160a01b031614905090565b6000806000614787614a3d565b8035946020909101359350915050565b60008060006147a7868686614ac6565b915091506147b481614aff565b5090505b9392505050565b6000600860006147cd6136c2565b65ffffffffffff16815260200190815260200160002054905090565b366000806002806101006020816008600e600684614808816004615533565b6148129190615533565b61481c9190615533565b6148269190615533565b6148309190615533565b61483a9190615533565b6148449190615533565b61484e9190615533565b6148589190615533565b6148629190615533565b9050600061486e6148c0565b919491935090915050565b60008061488461353b565b90508015806148935750806001145b156148a057600891505090565b806002036148b057602491505090565b806003036101e457602491505090565b600060016148d0600260086155d6565b6001901b6148de9190615744565b6135d5602060028061010083816008600e60068461369f816004615533565b6000614952826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614c499092919063ffffffff16565b805190915015613bc657808060200190518101906149709190615344565b613bc65760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610552565b60008060008060006149df61477a565b90925090506149f360ff82901c601b615533565b959194506001600160ff1b031692509050565b60006112906020600880600280610100858185600e60068461368b816004615533565b6000805433906001600160a01b031661476b565b6000614a476148c0565b6002806101006020816008600e600684614a62816004615533565b614a6c9190615533565b614a769190615533565b614a809190615533565b614a8a9190615533565b614a949190615533565b614a9e9190615533565b614aa89190615533565b614ab29190615533565b614abc9190615533565b6112909190615533565b6000806001600160ff1b03831681614ae360ff86901c601b615533565b9050614af187828885614c60565b935093505050935093915050565b6000816004811115614b1357614b13615a49565b03614b1b5750565b6001816004811115614b2f57614b2f615a49565b03614b7c5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610552565b6002816004811115614b9057614b90615a49565b03614bdd5760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610552565b6003816004811115614bf157614bf1615a49565b03610e5b5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610552565b6060614c588484600085614d24565b949350505050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115614c975750600090506003614d1b565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015614ceb573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116614d1457600060019250925050614d1b565b9150600090505b94509492505050565b606082471015614d855760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610552565b600080866001600160a01b03168587604051614da19190615a5f565b60006040518083038185875af1925050503d8060008114614dde576040519150601f19603f3d011682016040523d82523d6000602084013e614de3565b606091505b5091509150614df487838387614dff565b979650505050505050565b60608315614e6e578251600003614e67576001600160a01b0385163b614e675760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610552565b5081614c58565b614c588383815115614e835781518083602001fd5b8060405162461bcd60e51b81526004016105529190615577565b6040518060a001604052806005906020820280368337509192915050565b60405180606001604052806003906020820280368337509192915050565b6001600160a01b0381168114610e5b57600080fd5b60008060408385031215614f0157600080fd5b8235614f0c81614ed9565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614f5957614f59614f1a565b604052919050565b600082601f830112614f7257600080fd5b60405161010080820182811067ffffffffffffffff82111715614f9757614f97614f1a565b60405283018185821115614faa57600080fd5b845b82811015614fc4578035825260209182019101614fac565b509195945050505050565b6000806000806000806102608789031215614fe957600080fd5b86359550602087013567ffffffffffffffff8082111561500857600080fd5b818901915089601f83011261501c57600080fd5b81358181111561502b57600080fd5b8a60208260051b850101111561504057600080fd5b602083019750809650505050604087013592506150608860608901614f61565b9150615070886101608901614f61565b90509295509295509295565b60006020828403121561508e57600080fd5b81356147b881614ed9565b60006101a082019050825182526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015260c083015160c083015260e083015160e08301526101008084015181840152506101208084015161510d8285018260ff169052565b50506101408381015190830152610160808401519083015261018092830151929091019190915290565b60ff81168114610e5b57600080fd5b60006020828403121561515857600080fd5b81356147b881615137565b600080600080600080600080610100898b03121561518057600080fd5b505086359860208801359850604088013597606081013597506080810135965060a0810135955060c0810135945060e0013592509050565b6000602082840312156151ca57600080fd5b5035919050565b600080604083850312156151e457600080fd5b82356151ef81614ed9565b915060208301356151ff81614ed9565b809150509250929050565b6000806040838503121561521d57600080fd5b823561522881615137565b915060208381013567ffffffffffffffff8082111561524657600080fd5b818601915086601f83011261525a57600080fd5b81358181111561526c5761526c614f1a565b8060051b915061527d848301614f30565b818152918301840191848101908984111561529757600080fd5b938501935b838510156152c157843592506152b183614ed9565b828252938501939085019061529c565b8096505050505050509250929050565b600080600080600080600080610100898b0312156152ee57600080fd5b88356152f981615137565b9a60208a01359a5060408a013599606081013599506080810135985060a0810135975060c0810135965060e00135945092505050565b8051801515811461533f57600080fd5b919050565b60006020828403121561535657600080fd5b6147b88261532f565b6040808252810183905260006001600160fb1b0384111561537f57600080fd5b8360051b8086606085013760009083016060019081526020909201929092529392505050565b60005b838110156153c05781810151838201526020016153a8565b83811115613a725750506000910152565b600080600080608085870312156153e757600080fd5b845193506020850151925060408501519150606085015167ffffffffffffffff8082111561541457600080fd5b818701915087601f83011261542857600080fd5b81518181111561543a5761543a614f1a565b61544d601f8201601f1916602001614f30565b915080825288602082850101111561546457600080fd5b6154758160208401602086016153a5565b5094979396509194505050565b8060005b6008811015613a72578151845260209384019390910190600101615486565b6101208101818460005b60018110156154ce5781518352602092830192909101906001016154af565b5050506147b86020830184615482565b8060005b6003811015613a725781518452602093840193909101906001016154e2565b610160810161551082856154de565b6147b86060830184615482565b634e487b7160e01b600052601160045260246000fd5b600082198211156155465761554661551d565b500190565b600081518084526155638160208601602086016153a5565b601f01601f19169290920160200192915050565b6020815260006147b8602083018461554b565b634e487b7160e01b600052601260045260246000fd5b6000826155af576155af61558a565b500490565b600062ffffff808416806155ca576155ca61558a565b92169190910492915050565b60008160001904831182151516156155f0576155f061551d565b500290565b6101a08101818460005b600581101561561e5781518352602092830192909101906001016155ff565b5050506101008360a0840137600081529392505050565b610160810161564482856154de565b610100836060840137600081529392505050565b805160208201516001600160e01b031980821692919060048310156156875780818460040360031b1b83161693505b505050919050565b600080821280156001600160ff1b03849003851316156156b1576156b161551d565b600160ff1b83900384128116156156ca576156ca61551d565b50500190565b6000826156df576156df61558a565b500790565b60208082526024908201527f5a6b426f62506f6f6c3a20696e636f7272656374206465706f73697420616d6f604082015263756e747360e01b606082015260800190565b6000600160ff1b820161573d5761573d61551d565b5060000390565b6000828210156157565761575661551d565b500390565b60006020828403121561576d57600080fd5b5051919050565b60006020828403121561578657600080fd5b81516147b881615137565b600181815b808511156157cc5781600019048211156157b2576157b261551d565b808516156157bf57918102915b93841c9390800290615796565b509250929050565b6000826157e357506001612d23565b816157f057506000612d23565b816001811461580657600281146158105761582c565b6001915050612d23565b60ff8411156158215761582161551d565b50506001821b612d23565b5060208310610133831016604e8410600b841016171561584f575081810a612d23565b6158598383615791565b806000190482111561586d5761586d61551d565b029392505050565b60006147b883836157d4565b60006001600160481b038083168185168083038211156158a3576158a361551d565b01949350505050565b600062ffffff838116908316818110156158c8576158c861551d565b039392505050565b600063ffffffff838116908316818110156158c8576158c861551d565b60006001600160581b03838116908316818110156158c8576158c861551d565b60006001600160581b03808416806155ca576155ca61558a565b60006001600160481b03808416806155ca576155ca61558a565b60006001600160581b038083168185168083038211156158a3576158a361551d565b600063ffffffff80831681810361597c5761597c61551d565b6001019392505050565b6000806040838503121561599957600080fd5b6159a28361532f565b915060208301516151ff81615137565b634e487b7160e01b600052603260045260246000fd5b8183823760009101908152919050565b6000826159e7576159e761558a565b500690565b600080604083850312156159ff57600080fd5b505080516020909101519092909150565b600060018201615a2257615a2261551d565b5060010190565b60006001600160481b03838116908316818110156158c8576158c861551d565b634e487b7160e01b600052602160045260246000fd5b60008251615a718184602087016153a5565b919091019291505056fea2646970667358221220fa7609678ac81c6da4f63b538c6ee0aad8ce3e88b670453eb9eb6fac1d4dfaa364736f6c634300080f00335a6b426f62506f6f6c3a206e6f74206120636f6e74726163740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa84174000000000000000000000000a86c511832ead78d30ad49711874a9f3a1dfb84000000000000000000000000082907eaeb25d248dc82033e45b00a3e012ba2d0d0000000000000000000000009a7b4198065efe631a962e737bdfe1f44f2cb3ee000000000000000000000000668c5286ead26fac5fa944887f9d2f20f7ddf289
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101e45760003560e01c80637a22393b1161010f578063c41100fa116100a2578063e0ec037411610071578063e0ec037414610482578063e8fd02e414610495578063f2fde38b146104a8578063fc0c546a146104bb57600080fd5b8063c41100fa14610434578063c4a688b814610447578063c879c6d81461044f578063d21e82ab1461046257600080fd5b806396ce0795116100de57806396ce0795146103d75780639d8ad6e4146103e5578063af9890831461040c578063c2b40ae41461041457600080fd5b80637a22393b1461038457806383f26e3b146103975780638da5cb5b146103be5780638fff4676146103cf57600080fd5b80632f84c96f11610187578063508400401161015657806350840040146103365780636d55160c14610356578063715018a614610369578063790c3a331461037157600080fd5b80632f84c96f146102c95780633701f979146102dc5780634279a99e1461030357806346adf6ce1461032357600080fd5b80631cbec711116101c35780631cbec711146102635780631dc4cb33146102785780631dd69d061461028b5780632747f41d146102a257600080fd5b80622befce146101e95780630c6248de14610229578063171ef3001461023c575b600080fd5b7f06c991646992b7f0f3fd0c832eac3f519e26682bcb82fbbcfd1ff8013d876f64545b6040516001600160a01b0390911681526020015b60405180910390f35b600b5461020c906001600160a01b031681565b61020c7f000000000000000000000000a86c511832ead78d30ad49711874a9f3a1dfb84081565b610276610271366004614eee565b6104e2565b005b610276610286366004614fcf565b610569565b61029460095481565b604051908152602001610220565b61020c7f000000000000000000000000668c5286ead26fac5fa944887f9d2f20f7ddf28981565b60065461020c906001600160a01b031681565b61020c7f00000000000000000000000082907eaeb25d248dc82033e45b00a3e012ba2d0d81565b61031661031136600461507c565b6109c0565b6040516102209190615099565b610276610331366004615146565b610e2b565b61029461034436600461507c565b600a6020526000908152604090205481565b610276610364366004615163565b610e5e565b61027661112e565b61027661037f36600461507c565b611142565b61027661039236600461507c565b611218565b61020c7f0000000000000000000000009a7b4198065efe631a962e737bdfe1f44f2cb3ee81565b6000546001600160a01b031661020c565b61029461126e565b6103e8600160ff1b01610294565b6102947f000000000000000000000000000000000000000000000000000000000000000081565b610276611295565b6102946104223660046151b8565b60086020526000908152604090205481565b61027661044236600461507c565b611c39565b610276611cf0565b61027661045d3660046151d1565b6121dd565b6102946104703660046151b8565b60076020526000908152604090205481565b61027661049036600461520a565b6123dd565b6102766104a33660046152d1565b6123ef565b6102766104b636600461507c565b612428565b61020c7f0000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa8417481565b336001600160a01b037f000000000000000000000000668c5286ead26fac5fa944887f9d2f20f7ddf289161461055b5760405162461bcd60e51b8152602060048201526019602482015278169ad09bd8941bdbdb0e881b9bdd08185d5d1a1bdc9a5e9959603a1b60448201526064015b60405180910390fd5b61056582826124ad565b5050565b6006546001600160a01b0316636d70f7ae336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa1580156105bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e39190615344565b61062f5760405162461bcd60e51b815260206004820152601a60248201527f5a6b426f62506f6f6c3a206e6f7420616e206f70657261746f720000000000006044820152606401610552565b6000806000807f000000000000000000000000668c5286ead26fac5fa944887f9d2f20f7ddf2896001600160a01b031663e24546f28a8a8a6040518463ffffffff1660e01b81526004016106859392919061535f565b6000604051808303816000875af11580156106a4573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526106cc91908101906153d1565b935093509350935060006106e160008661282f565b604080516020810182528781529051633cac775b60e01b8152919450600785901b93506001600160a01b037f0000000000000000000000009a7b4198065efe631a962e737bdfe1f44f2cb3ee169250633cac775b9161074591908c906004016154a5565b602060405180830381865afa158015610762573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107869190615344565b6107dd5760405162461bcd60e51b815260206004820152602260248201527f5a6b426f62506f6f6c3a20626164206261746368206465706f7369742070726f60448201526137b360f11b6064820152608401610552565b604080516060810182526000838152600860209081529083902054825281018e90528082018b905290516345bb94c160e01b81526001600160a01b037f00000000000000000000000082907eaeb25d248dc82033e45b00a3e012ba2d0d16906345bb94c1906108529084908c90600401615501565b602060405180830381865afa15801561086f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108939190615344565b6108db5760405162461bcd60e51b81526020600482015260196024820152782d35a137b12837b7b61d103130b2103a3932b290383937b7b360391b6044820152606401610552565b6108e6608083615533565b91508c600860008481526020019081526020016000208190555060008480519060200120905060006009548260405160200161092c929190918252602082015260400190565b60408051601f19818403018152919052805160209091012060098190559050871561097657336000908152600a6020526040812080548a9290610970908490615533565b90915550505b80847f7d39f8a6bc8929456fba511441be7361aa014ac6f8e21b99990ce9e1c7373536886040516109a79190615577565b60405180910390a3505050505050505050505050505050565b610a2e604051806101a00160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600060ff1681526020016000815260200160008152602001600081525090565b60408051602080820183526002546001600160481b0390811683526001600160a01b0386166000908152600583528481208551608081018752905461ffff8116825262010000810484169482019490945260ff600160581b850416958101869052600160601b90930490911660608301529192909190610aaf908690612c28565b60ff81166000908152600360209081526040808320815160e081018352815466ffffffffffffff8116825263ffffffff600160381b8204811683870152600160581b808304821684870152600160781b83048216606080860191909152600160981b840483166080860152600160b81b8404831660a0860152600160d81b90930490911660c084015284519182018552600184015461ffff811683526001600160481b03620100008204811697840197909752049094169284019290925293945091610b7d610e10426155a0565b90506000610b90610e10620151806155a0565b610b9a90836155b4565b9050604051806101a001604052807f000000000000000000000000000000000000000000000000000000003b9aca00866000015166ffffffffffffff16610be191906155d6565b815260200189600001516001600160481b031681526020017f000000000000000000000000000000000000000000000000000000003b9aca00866020015163ffffffff16610c2f91906155d6565b81526020018262ffffff16856000015161ffff1614610c4f576000610c55565b84602001515b6001600160481b031681526020017f000000000000000000000000000000000000000000000000000000003b9aca00866040015163ffffffff16610c9991906155d6565b81526020018262ffffff16856000015161ffff1614610cb9576000610cbf565b84604001515b6001600160481b031681526020017f000000000000000000000000000000000000000000000000000000003b9aca00866060015163ffffffff16610d0391906155d6565b81526020018262ffffff16896000015161ffff1614610d23576000610d29565b88602001515b6001600160481b031681526020017f000000000000000000000000000000000000000000000000000000003b9aca00866080015163ffffffff16610d6d91906155d6565b81526020018760ff1681526020017f000000000000000000000000000000000000000000000000000000003b9aca008660c0015163ffffffff16610db191906155d6565b81526020018262ffffff16896000015161ffff1614610dd1576000610dd7565b88606001515b6001600160481b031681526020017f000000000000000000000000000000000000000000000000000000003b9aca008660a0015163ffffffff16610e1b91906155d6565b90529a9950505050505050505050565b610e33612d29565b610e5b8160ff16600090815260036020526040902060010180546001600160a01b0319169055565b50565b333014610ead5760405162461bcd60e51b815260206004820152601a60248201527f5a6b426f62506f6f6c3a206e6f7420696e697469616c697a65720000000000006044820152606401610552565b6000805260086020527f5eff886ea0ce6ca488a3d6e336d6c0f75f46d19b42c06ce5ee98e42c96d256c75415610f255760405162461bcd60e51b815260206004820152601e60248201527f5a6b426f62506f6f6c3a20616c726561647920696e697469616c697a656400006044820152606401610552565b87600003610f6c5760405162461bcd60e51b8152602060048201526014602482015273169ad09bd8941bdbdb0e881e995c9bc81c9bdbdd60621b6044820152606401610552565b600080805260086020527f5eff886ea0ce6ca488a3d6e336d6c0f75f46d19b42c06ce5ee98e42c96d256c7899055611124906103e8610fcb7f00000000000000000000000000000000000000000000000000000000000000018b6155a0565b610fd591906155d6565b6103e86110027f00000000000000000000000000000000000000000000000000000000000000018b6155a0565b61100c91906155d6565b6103e86110397f00000000000000000000000000000000000000000000000000000000000000018b6155a0565b61104391906155d6565b6103e86110707f00000000000000000000000000000000000000000000000000000000000000018b6155a0565b61107a91906155d6565b6103e86110a77f00000000000000000000000000000000000000000000000000000000000000018b6155a0565b6110b191906155d6565b6103e86110de7f00000000000000000000000000000000000000000000000000000000000000018b6155a0565b6110e891906155d6565b6103e86111157f00000000000000000000000000000000000000000000000000000000000000018b6155a0565b61111f91906155d6565b612d7d565b5050505050505050565b611136612d29565b61114060006134eb565b565b61114a612d29565b6001600160a01b0381163b6111b45760405162461bcd60e51b815260206004820152602a60248201527f4b796350726f7669646572734d616e6167657253746f726167653a206e6f7420604482015269184818dbdb9d1c9858dd60b21b6064820152608401610552565b7f06c991646992b7f0f3fd0c832eac3f519e26682bcb82fbbcfd1ff8013d876f648190556040516001600160a01b03821681527fcfca215f2134266880a5d2c68d2f52493a9d57fe6dd1245086a201e78871348e906020015b60405180910390a150565b611220612d29565b600b80546001600160a01b0319166001600160a01b0383169081179091556040519081527fdf71641930ea322cb32f687f4d292a0af694c81216254f204c930092593d82829060200161120d565b6000600761128960015463ffffffff600160e01b9091041690565b901b905090565b905090565b6006546001600160a01b0316636d70f7ae336040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa1580156112eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061130f9190615344565b61135b5760405162461bcd60e51b815260206004820152601a60248201527f5a6b426f62506f6f6c3a206e6f7420616e206f70657261746f720000000000006044820152606401610552565b33600061136661353b565b90508060000361137f576113786135db565b91506113a2565b8060020361138f5761137861365c565b806003036113a25761139f61365c565b91505b60006113ac6136a9565b60070b905060006113bd848361282f565b9250505060006113cc60043590565b60008181526007602081905260409091205491925083901b90156114325760405162461bcd60e51b815260206004820152601f60248201527f5a6b426f62506f6f6c3a20646f75626c657370656e64206465746563746564006044820152606401610552565b8061143b6136c2565b65ffffffffffff1611156114a15760405162461bcd60e51b815260206004820152602760248201527f5a6b426f62506f6f6c3a207472616e7366657220696e646578206f7574206f6660448201526620626f756e647360c81b6064820152608401610552565b7f000000000000000000000000a86c511832ead78d30ad49711874a9f3a1dfb8406001600160a01b03166368444dc76114d86136d7565b6114e06137ad565b6040518363ffffffff1660e01b81526004016114fd9291906155f5565b602060405180830381865afa15801561151a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061153e9190615344565b61158a5760405162461bcd60e51b815260206004820152601d60248201527f5a6b426f62506f6f6c3a20626164207472616e736665722070726f6f660000006044820152606401610552565b6000818152600860205260409020546001600160a01b037f00000000000000000000000082907eaeb25d248dc82033e45b00a3e012ba2d0d16906345bb94c1906115d3906137eb565b6115db613815565b6040518363ffffffff1660e01b81526004016115f8929190615635565b602060405180830381865afa158015611615573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116399190615344565b6116815760405162461bcd60e51b81526020600482015260196024820152782d35a137b12837b7b61d103130b2103a3932b290383937b7b360391b6044820152606401610552565b611689613843565b611691613854565b60408051602081019390935282015260600160408051601f198184030181529181528151602092830120600085815260079093529120556116d3608082615533565b90506116dd6138b3565b6000828152600860205260408120919091556116f7613900565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092018290525093945061173992508491506156589050565b61ffff60e01b161461178d5760405162461bcd60e51b815260206004820152601d60248201527f5a6b426f62506f6f6c3a20626164206d657373616765207072656669780000006044820152606401610552565b6000818051906020012090506000600954826040516020016117b9929190918252602082015260400190565b6040516020818303038152906040528051906020012090508060098190555080847f7d39f8a6bc8929456fba511441be7361aa014ac6f8e21b99990ce9e1c7373536856040516118099190615577565b60405180910390a350505050600061181f6139b3565b9050600061182d828661568f565b905060006118396139f0565b600d0b905061184a6103e8836156d0565b156118a15760405162461bcd60e51b815260206004820152602160248201527f5a6b426f62506f6f6c3a20696e636f727265637420746f6b656e20616d6f756e6044820152601d60fa1b6064820152608401610552565b86600003611946576000861380156118b7575080155b6118d35760405162461bcd60e51b8152600401610552906156e4565b61194188306103e86119057f0000000000000000000000000000000000000000000000000000000000000001876155d6565b61190f91906155a0565b6001600160a01b037f0000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa8417416929190613a07565b611c05565b866001036119b4578115801561195a575080155b6119415760405162461bcd60e51b815260206004820152602560248201527f5a6b426f62506f6f6c3a20696e636f7272656374207472616e7366657220616d6044820152646f756e747360d81b6064820152608401610552565b86600203611b7257600082131580156119ce575060008113155b611a285760405162461bcd60e51b815260206004820152602560248201527f5a6b426f62506f6f6c3a20696e636f727265637420776974686472617720616d6044820152646f756e747360d81b6064820152608401610552565b60006103e87f0000000000000000000000000000000000000000000000000000000000000001611a56613a78565b611a6091906155d6565b611a6a91906155a0565b905060006103e87f0000000000000000000000000000000000000000000000000000000000000001611a9b86615728565b611aa591906155d6565b611aaf91906155a0565b90508115611ace57611ac18a83613ab6565b611acb9082615744565b90505b8015611b0857611b086001600160a01b037f0000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa84174168b83613b96565b6000831215611b6b5760405162461bcd60e51b815260206004820152602960248201527f5a6b426f62506f6f6c3a20585020636c61696d696e67206973206e6f742079656044820152681d08195b98589b195960ba1b6064820152608401610552565b5050611c05565b86600303611baf57600086138015611b88575080155b611ba45760405162461bcd60e51b8152600401610552906156e4565b611941888584613bcb565b60405162461bcd60e51b815260206004820152602560248201527f5a6b426f62506f6f6c3a20496e636f7272656374207472616e73616374696f6e604482015264207479706560d81b6064820152608401610552565b821561112457336000908152600a602052604081208054859290611c2a908490615533565b90915550505050505050505050565b611c41612d29565b6001600160a01b038116611ca25760405162461bcd60e51b815260206004820152602260248201527f5a6b426f62506f6f6c3a206d616e61676572206973207a65726f206164647265604482015261737360f01b6064820152608401610552565b600680546001600160a01b0319166001600160a01b0383169081179091556040519081527f267052ecaebdd552dc1b20904f59d83d51ae7add7514165322a7da9ef6cf543b9060200161120d565b333014611d335760405162461bcd60e51b815260206004820152601160248201527024b731b7b93932b1ba1034b73b37b5b2b960791b6044820152606401610552565b7f0000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa841746001600160a01b0316732791bca1f2de4661ed88a30c99a7a9449aa8417414611db15760405162461bcd60e51b815260206004820152600f60248201526e24b731b7b93932b1ba103a37b5b2b760891b6044820152606401610552565b6040516370a0823160e01b815230600482015273b0b195aefa3650a6908f15cdac7d92f8a5791b0b9060009082906370a0823190602401602060405180830381865afa158015611e05573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e29919061575b565b90506000826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e8f9190615774565b60ff16905060007f0000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa841746001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ef4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f189190615774565b60405163095ea7b360e01b81527325e6505297b44f4817538fb2d91b88e1cf841b54600482018190526024820186905260ff9290921692506000906001600160a01b0387169063095ea7b3906044016020604051808303816000875af1158015611f86573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611faa9190615344565b604051636c197ff560e01b81526001600160a01b037f0000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa841748116600483015260248201889052919250600091841690636c197ff5906044016020604051808303816000875af115801561201f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612043919061575b565b6040516370a0823160e01b81523060048201529091506001600160a01b038816906370a0823190602401602060405180830381865afa15801561208a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120ae919061575b565b156120ec5760405162461bcd60e51b815260206004820152600e60248201526d0496e636f727265637420737761760941b6044820152606401610552565b6000816120f98688615744565b61210490600a615875565b61210e90896155a0565b6121189190615744565b90507f0000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa841746001600160a01b03166323b872dd61215b6000546001600160a01b031690565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152306024820152604481018490526064016020604051808303816000875af11580156121ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121d29190615344565b505050505050505050565b6001600160a01b0382163314806122635750600654604051632bb6fe4d60e21b81526001600160a01b0384811660048301523360248301529091169063aedbf93490604401602060405180830381865afa15801561223f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122639190615344565b6122ab5760405162461bcd60e51b8152602060048201526019602482015278169ad09bd8941bdbdb0e881b9bdd08185d5d1a1bdc9a5e9959603a1b6044820152606401610552565b6001600160a01b0382166000908152600a60205260408120546103e8906122f3907f0000000000000000000000000000000000000000000000000000000000000001906155d6565b6122fd91906155a0565b90506000811161234f5760405162461bcd60e51b815260206004820152601d60248201527f5a6b426f62506f6f6c3a206e6f2066656520746f2077697468647261770000006044820152606401610552565b6123836001600160a01b037f0000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa84174168383613b96565b6001600160a01b0383166000818152600a602052604080822091909155517f66bf9186b00db666fc37aaffbb95a050c66e599e000c785c1dff0467d868f1b1906123d09084815260200190565b60405180910390a2505050565b6123e5612d29565b6105658282613cf7565b6123f7612d29565b611124886103e8610fcb7f00000000000000000000000000000000000000000000000000000000000000018b6155a0565b612430612d29565b6001600160a01b0381166124955760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610552565b610e5b816134eb565b6001600160a01b03163b151590565b60006124be610e10620151806155a0565b6124ca610e10426155a0565b6124d491906155a0565b6001600160a01b03841660009081526005602090815260408083208151608081018352905461ffff811682526001600160481b0362010000820481169483019490945260ff600160581b820416928201839052600160601b9004909216606083015292935091600390829061254a908890612c28565b60ff1681526020808201929092526040908101600020815160e081018352905466ffffffffffffff8116825263ffffffff600160381b8204811694830194909452600160581b8104841692820192909252600160781b820483166060820152600160981b820483166080820152600160b81b8204831660a08201819052600160d81b90920490921660c0830152909150612605907f000000000000000000000000000000000000000000000000000000003b9aca00906155d6565b8411156126705760405162461bcd60e51b815260206004820152603360248201527f5a6b426f624163636f756e74696e673a2073696e676c65206469726563742064604482015272195c1bdcda5d0818d85c08195e18d959591959606a1b6064820152608401610552565b816000015161ffff168361ffff1611156126bb576040805160808101825261ffff85168152600060208201529281015160ff16908301526001600160481b0384166060830152612791565b83826060018181516126cd9190615881565b6001600160481b031690525060c081015161270f907f000000000000000000000000000000000000000000000000000000003b9aca009063ffffffff166155d6565b82606001516001600160481b031611156127915760405162461bcd60e51b815260206004820152603760248201527f5a6b426f624163636f756e74696e673a206461696c792075736572206469726560448201527f6374206465706f736974206361702065786365656465640000000000000000006064820152608401610552565b506001600160a01b039390931660009081526005602090815260409182902085518154928701519387015160609097015161ffff9091166001600160581b031990931692909217620100006001600160481b03948516021769ffffffffffffffffffff60581b1916600160581b60ff9097169690960268ffffffffffffffffff60601b191695909517600160601b9290911691909102179092555050565b6040805160c08101825260015466ffffffffffffff8116825263ffffffff600160381b8204811660208085019190915262ffffff600160581b8404811685870152600160701b84041660608501526001600160581b03600160881b8404166080850152600160e01b9092041660a083015282519081019092526002546001600160481b0316825260009182918291826128ca610e10426155a0565b60a084015163ffffffff1694509050831580159061290857506128f2610e1062093a806155a0565b604084015161290190836158ac565b62ffffff16115b15612a1e576040838101805162ffffff9081166000908152600460208181528583208651606081018852905480861682526301000000810463ffffffff16828401908152600160381b9091046001600160581b03168289015286518616855292909152948220805471ffffffffffffffffffffffffffffffffffff1916905584519092169092525160a086015161299f91906158d0565b9050846020015163ffffffff168163ffffffff1611156129c65763ffffffff811660208601525b60008163ffffffff16836040015187608001516129e391906158ed565b6129ed919061590d565b9050856000015166ffffffffffffff168166ffffffffffffff161115612a1a5766ffffffffffffff811686525b5050505b8062ffffff16836060015162ffffff161015612ad957604080516060808201835262ffffff80851680845260a088015163ffffffff908116602080870191825260808b01516001600160581b03908116888a01908152968c018051871660009081526004909352989091209651875492519651909116600160381b0271ffffffffffffffffffffff00000000000000199690931663010000000266ffffffffffffff1990921694169390931792909217929092161790915590525b8151612b06907f000000000000000000000000000000000000000000000000000000003b9aca0090615927565b6001600160481b031683608001818151612b209190615941565b6001600160581b031690525060a08301805190612b3c82615963565b63ffffffff169052508615612b5657612b56828989613e32565b5050805160018054602084015160408501516060860151608087015160a09097015166ffffffffffffff87166001600160581b031990951694909417600160381b63ffffffff808616919091029190911765ffffffffffff60581b1916600160581b62ffffff9485160262ffffff60701b191617600160701b93909216929092021770ffffffffffffffffffffffffffffffffff16600160881b6001600160581b03909716969096026001600160e01b031695909517600160e01b959092169490940217905596909550909350915050565b600080612c537f06c991646992b7f0f3fd0c832eac3f519e26682bcb82fbbcfd1ff8013d876f645490565b905060ff8316158015612c6e57506001600160a01b03811615155b15612d1e57604051630a364e7560e41b81526001600160a01b038581166004830152600091829184169063a364e750906024016040805180830381865afa158015612cbd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ce19190615986565b91509150818015612d0c575060ff811660009081526003602052604090205466ffffffffffffff1615155b15612d1b579250612d23915050565b50505b829150505b92915050565b612d31614736565b6111405760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610552565b60ff8860ff1610612ddc5760405162461bcd60e51b815260206004820152602360248201527f5a6b426f624163636f756e74696e673a20696e76616c6964206c696d6974207460448201526234b2b960e91b6064820152608401610552565b60008311612e365760405162461bcd60e51b815260206004820152602160248201527f5a6b426f624163636f756e74696e673a207a65726f206465706f7369742063616044820152600760fc1b6064820152608401610552565b612e677f000000000000000000000000000000000000000000000000000000003b9aca0066ffffffffffffff6155d6565b871115612ec15760405162461bcd60e51b815260206004820152602260248201527f5a6b426f624163636f756e74696e673a2074766c2063617020746f6f206c6172604482015261676560f01b6064820152608401610552565b612eef7f000000000000000000000000000000000000000000000000000000003b9aca0063ffffffff6155d6565b861115612f535760405162461bcd60e51b815260206004820152602c60248201527f5a6b426f624163636f756e74696e673a206461696c79206465706f736974206360448201526b617020746f6f206c6172676560a01b6064820152608401610552565b612f817f000000000000000000000000000000000000000000000000000000003b9aca0063ffffffff6155d6565b851115612fe85760405162461bcd60e51b815260206004820152602f60248201527f5a6b426f624163636f756e74696e673a206461696c792077697468647261776160448201526e6c2063617020746f6f206c6172676560881b6064820152608401610552565b828410156130505760405162461bcd60e51b815260206004820152602f60248201527f5a6b426f624163636f756e74696e673a206461696c792075736572206465706f60448201526e7369742063617020746f6f206c6f7760881b6064820152608401610552565b838610156130b35760405162461bcd60e51b815260206004820152602a60248201527f5a6b426f624163636f756e74696e673a206461696c79206465706f7369742063604482015269617020746f6f206c6f7760b01b6064820152608401610552565b858710156131035760405162461bcd60e51b815260206004820181905260248201527f5a6b426f624163636f756e74696e673a2074766c2063617020746f6f206c6f776044820152606401610552565b600085116131665760405162461bcd60e51b815260206004820152602a60248201527f5a6b426f624163636f756e74696e673a207a65726f206461696c792077697468604482015269064726177616c206361760b41b6064820152608401610552565b808210156131d55760405162461bcd60e51b815260206004820152603660248201527f5a6b426f624163636f756e74696e673a206461696c79207573657220646972656044820152756374206465706f7369742063617020746f6f206c6f7760501b6064820152608401610552565b60006040518060e001604052807f000000000000000000000000000000000000000000000000000000003b9aca008a61320e91906155a0565b66ffffffffffffff1681526020016132467f000000000000000000000000000000000000000000000000000000003b9aca008a6155a0565b63ffffffff16815260200161327b7f000000000000000000000000000000000000000000000000000000003b9aca00896155a0565b63ffffffff1681526020016132b07f000000000000000000000000000000000000000000000000000000003b9aca00886155a0565b63ffffffff1681526020016132e57f000000000000000000000000000000000000000000000000000000003b9aca00876155a0565b63ffffffff16815260200161331a7f000000000000000000000000000000000000000000000000000000003b9aca00856155a0565b63ffffffff16815260200161334f7f000000000000000000000000000000000000000000000000000000003b9aca00866155a0565b63ffffffff90811690915260ff8b16600081815260036020908152604091829020855181549287015184880151606089015160808a015160a08b015160c08c01518b16600160d81b0263ffffffff60d81b19918c16600160b81b0263ffffffff60b81b19938d16600160981b029390931667ffffffffffffffff60981b19948d16600160781b0263ffffffff60781b19968e16600160581b029690961667ffffffffffffffff60581b1997909d16600160381b026001600160581b0319909a1666ffffffffffffff909816979097179890981794909416999099179190911716919091179590951794909416179092559051919250907f3cb26612e7105331adad836a65ae9b7f1d30a9e469ec70510a7c7ea36b0185ed906134d8908490600060e08201905066ffffffffffffff8351168252602083015163ffffffff80821660208501528060408601511660408501528060608601511660608501528060808601511660808501528060a08601511660a08501528060c08601511660c0850152505092915050565b60405180910390a2505050505050505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000600161354b600260086155d6565b6001901b6135599190615744565b6135d56020600261010082816008600e600684613577816004615533565b6135819190615533565b61358b9190615533565b6135959190615533565b61359f9190615533565b6135a99190615533565b6135b39190615533565b6135bd9190615533565b6135c79190615533565b6135d19190615744565b3590565b16905090565b60008060006135e861477a565b9150915061365561364e6135fb60043590565b6040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b8383614797565b9250505090565b600061129060206014600880600280610100868185600e600684613681816004615533565b61368b9190615533565b6136959190615533565b61369f9190615533565b6135779190615533565b600061129060206008600e60068361359f816004615533565b600061129060206006816135b3816004615533565b6136df614e9d565b6136e76147bf565b815260043560208201526136f9613843565b6040820152600861370c600e6006615533565b6137169190615533565b6137219060086155d6565b7f0000000000000000000000000000000000000000000000000000000000000000901b61374c613854565b6137569190615533565b60608201527f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016137846147e9565b6040516137929291906159c8565b6040519081900390206137a591906159d8565b608082015290565b3660006008600e600660206137c3816004615533565b6137cd9190615533565b6137d79190615533565b6137e19190615533565b612d239190615533565b6137f3614ebb565b8181526137fe6138b3565b602082015261380b613843565b6040820152919050565b36600060206101006008600e60068461382f816004615533565b6138399190615533565b6137c39190615533565b60006112906135d160206004615533565b600060016008613866600e6006615533565b6138709190615533565b61387b9060086155d6565b6001901b6138899190615744565b6135d56020600861389c600e6006615533565b6138a69190615533565b60206135b3816004615533565b60006112906101006008600e600660206138ce816004615533565b6138d89190615533565b6138e29190615533565b6138ec9190615533565b6138f69190615533565b6135d19190615533565b3660008061390c614879565b90506000816002806101006020816008600e60068461392c816004615533565b6139369190615533565b6139409190615533565b61394a9190615533565b6139549190615533565b61395e9190615533565b6139689190615533565b6139729190615533565b61397c9190615533565b6139869190615533565b6139909190615533565b905060008261399d6148c0565b6139a79190615744565b91959194509092505050565b600060016139c26008806155d6565b6001901b6139d09190615744565b6135d560206008600280610100848185600e600684613695816004615533565b60006112906020600e6006826135a9816004615533565b6040516001600160a01b0380851660248301528316604482015260648101829052613a729085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526148fd565b50505050565b60006001613a876008806155d6565b6001901b613a959190615744565b6135d56020600880600280610100858185600e60068461368b816004615533565b600b546000906001600160a01b03168015613b8c57613aff6001600160a01b037f0000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa84174168285613b96565b604051630802e33b60e41b81526001600160a01b038581166004830152602482018590526000919083169063802e33b09060440160408051808303816000875af1158015613b51573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b7591906159ec565b9150613b8390508185615744565b92505050612d23565b5060009392505050565b6040516001600160a01b038316602482015260448101829052613bc690849063a9059cbb60e01b90606401613a3b565b505050565b6000806000613bd86149cf565b919450925090506001600160a01b037f0000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa841741663e3ee160e87306103e8613c3d7f00000000000000000000000000000000000000000000000000000000000000018a6155d6565b613c4791906155a0565b6000613c51614a06565b60405160e087901b6001600160e01b03191681526001600160a01b0395861660048201529490931660248501526044840191909152606483015267ffffffffffffffff16608482015260a4810188905260ff861660c482015260e48101859052610104810184905261012401600060405180830381600087803b158015613cd757600080fd5b505af1158015613ceb573d6000803e3d6000fd5b50505050505050505050565b8160ff1660ff1480613d23575060ff821660009081526003602052604090205466ffffffffffffff1615155b613d865760405162461bcd60e51b815260206004820152602e60248201527f5a6b426f624163636f756e74696e673a206e6f6e2d6578697374696e6720706f60448201526d37b6103634b6b4ba39903a34b2b960911b6064820152608401610552565b60005b8151811015613bc6576000828281518110613da657613da66159b2565b6020908102919091018101516001600160a01b038116600081815260058452604090819020805460ff60581b1916600160581b60ff8b16908102919091179091558151928352938201939093529092507f1283ebeb150dffd4da976f64c81e074fd4dc895cb64995dc46f13c9fd96a9551910160405180910390a150613e2b81615a10565b9050613d89565b6001600160a01b038216158015613e495750600081135b15613e955760028054829190600090613e6c9084906001600160481b0316615881565b92506101000a8154816001600160481b0302191690836001600160481b03160217905550505050565b6000613ea6610e10620151806155a0565b613eb2610e10426155a0565b613ebc91906155a0565b6001600160a01b03841660009081526005602090815260408083208151608081018352905461ffff811682526001600160481b0362010000820481169483019490945260ff600160581b820416928201839052600160601b90049092166060830152929350916003908290613f32908890612c28565b60ff16815260208082019290925260409081016000908120825160e081018452815466ffffffffffffff8116825263ffffffff600160381b8204811683880152600160581b808304821684880152600160781b83048216606080860191909152600160981b840483166080860152600160b81b8404831660a0860152600160d81b90930490911660c084015285519182018652600184015461ffff811683526001600160481b03620100008204811698840198909852049095169385019390935293509091908613156144e5578751869081908a90614012908390615881565b6001600160481b03169052506080830151614054907f000000000000000000000000000000000000000000000000000000003b9aca009063ffffffff166155d6565b8111156140b85760405162461bcd60e51b815260206004820152602c60248201527f5a6b426f624163636f756e74696e673a2073696e676c65206465706f7369742060448201526b18d85c08195e18d95959195960a21b6064820152608401610552565b82516140ee907f000000000000000000000000000000000000000000000000000000003b9aca009066ffffffffffffff166155d6565b89516001600160481b031611156141515760405162461bcd60e51b815260206004820152602160248201527f5a6b426f624163636f756e74696e673a2074766c2063617020657863656564656044820152601960fa1b6064820152608401610552565b846000015161ffff168661ffff16111561426f5760405180608001604052808761ffff168152602001826001600160481b03168152602001866040015160ff16815260200160006001600160481b0316815250600560008a6001600160a01b03166001600160a01b0316815260200190815260200160002060008201518160000160006101000a81548161ffff021916908361ffff16021790555060208201518160000160026101000a8154816001600160481b0302191690836001600160481b03160217905550604082015181600001600b6101000a81548160ff021916908360ff160217905550606082015181600001600c6101000a8154816001600160481b0302191690836001600160481b031602179055509050506143ce565b80856020018181516142819190615881565b6001600160481b031690525060608301516142c3907f000000000000000000000000000000000000000000000000000000003b9aca009063ffffffff166155d6565b85602001516001600160481b031611156143385760405162461bcd60e51b815260206004820152603060248201527f5a6b426f624163636f756e74696e673a206461696c792075736572206465706f60448201526f1cda5d0818d85c08195e18d95959195960821b6064820152608401610552565b6001600160a01b03881660009081526005602090815260409182902087518154928901519389015160608a01516001600160481b03908116600160601b0268ffffffffffffffffff60601b1960ff909316600160581b029290921669ffffffffffffffffffff60581b199190961662010000026001600160581b031990951661ffff909316929092179390931716929092171790555b816000015161ffff168661ffff16111561441b5760405180606001604052808761ffff168152602001826001600160481b0316815260200160006001600160481b031681525091506144df565b808260200181815161442d9190615881565b6001600160481b0316905250602083015161446f907f000000000000000000000000000000000000000000000000000000003b9aca009063ffffffff166155d6565b82602001516001600160481b031611156144df5760405162461bcd60e51b815260206004820152602b60248201527f5a6b426f624163636f756e74696e673a206461696c79206465706f736974206360448201526a185c08195e18d95959195960aa1b6064820152608401610552565b506146b5565b60006144f087615728565b90506145207f000000000000000000000000000000000000000000000000000000003b9aca0063ffffffff6155d6565b8111156145845760405162461bcd60e51b815260206004820152602c60248201527f5a6b426f624163636f756e74696e673a207769746864726177616c20616d6f7560448201526b6e7420746f6f206c6172676560a01b6064820152608401610552565b80896000018181516145969190615a29565b6001600160481b0316905250815161ffff90811690871611156145ec5760405180606001604052808761ffff16815260200160006001600160481b03168152602001826001600160481b031681525091506146b3565b80826040018181516145fe9190615881565b6001600160481b03169052506040830151614640907f000000000000000000000000000000000000000000000000000000003b9aca009063ffffffff166155d6565b82604001516001600160481b031611156146b35760405162461bcd60e51b815260206004820152602e60248201527f5a6b426f624163636f756e74696e673a206461696c792077697468647261776160448201526d1b0818d85c08195e18d95959195960921b6064820152608401610552565b505b9651600280546001600160481b0392831668ffffffffffffffffff199091161790558751600193909301805460208a01516040909a01518316600160581b0268ffffffffffffffffff60581b199a90931662010000026001600160581b031990911661ffff9095169490941793909317979097169690961790555050505050565b6000614740614a29565b8061129057507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035433905b6001600160a01b031614905090565b6000806000614787614a3d565b8035946020909101359350915050565b60008060006147a7868686614ac6565b915091506147b481614aff565b5090505b9392505050565b6000600860006147cd6136c2565b65ffffffffffff16815260200190815260200160002054905090565b366000806002806101006020816008600e600684614808816004615533565b6148129190615533565b61481c9190615533565b6148269190615533565b6148309190615533565b61483a9190615533565b6148449190615533565b61484e9190615533565b6148589190615533565b6148629190615533565b9050600061486e6148c0565b919491935090915050565b60008061488461353b565b90508015806148935750806001145b156148a057600891505090565b806002036148b057602491505090565b806003036101e457602491505090565b600060016148d0600260086155d6565b6001901b6148de9190615744565b6135d5602060028061010083816008600e60068461369f816004615533565b6000614952826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614c499092919063ffffffff16565b805190915015613bc657808060200190518101906149709190615344565b613bc65760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610552565b60008060008060006149df61477a565b90925090506149f360ff82901c601b615533565b959194506001600160ff1b031692509050565b60006112906020600880600280610100858185600e60068461368b816004615533565b6000805433906001600160a01b031661476b565b6000614a476148c0565b6002806101006020816008600e600684614a62816004615533565b614a6c9190615533565b614a769190615533565b614a809190615533565b614a8a9190615533565b614a949190615533565b614a9e9190615533565b614aa89190615533565b614ab29190615533565b614abc9190615533565b6112909190615533565b6000806001600160ff1b03831681614ae360ff86901c601b615533565b9050614af187828885614c60565b935093505050935093915050565b6000816004811115614b1357614b13615a49565b03614b1b5750565b6001816004811115614b2f57614b2f615a49565b03614b7c5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610552565b6002816004811115614b9057614b90615a49565b03614bdd5760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610552565b6003816004811115614bf157614bf1615a49565b03610e5b5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610552565b6060614c588484600085614d24565b949350505050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115614c975750600090506003614d1b565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015614ceb573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116614d1457600060019250925050614d1b565b9150600090505b94509492505050565b606082471015614d855760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610552565b600080866001600160a01b03168587604051614da19190615a5f565b60006040518083038185875af1925050503d8060008114614dde576040519150601f19603f3d011682016040523d82523d6000602084013e614de3565b606091505b5091509150614df487838387614dff565b979650505050505050565b60608315614e6e578251600003614e67576001600160a01b0385163b614e675760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610552565b5081614c58565b614c588383815115614e835781518083602001fd5b8060405162461bcd60e51b81526004016105529190615577565b6040518060a001604052806005906020820280368337509192915050565b60405180606001604052806003906020820280368337509192915050565b6001600160a01b0381168114610e5b57600080fd5b60008060408385031215614f0157600080fd5b8235614f0c81614ed9565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614f5957614f59614f1a565b604052919050565b600082601f830112614f7257600080fd5b60405161010080820182811067ffffffffffffffff82111715614f9757614f97614f1a565b60405283018185821115614faa57600080fd5b845b82811015614fc4578035825260209182019101614fac565b509195945050505050565b6000806000806000806102608789031215614fe957600080fd5b86359550602087013567ffffffffffffffff8082111561500857600080fd5b818901915089601f83011261501c57600080fd5b81358181111561502b57600080fd5b8a60208260051b850101111561504057600080fd5b602083019750809650505050604087013592506150608860608901614f61565b9150615070886101608901614f61565b90509295509295509295565b60006020828403121561508e57600080fd5b81356147b881614ed9565b60006101a082019050825182526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015260c083015160c083015260e083015160e08301526101008084015181840152506101208084015161510d8285018260ff169052565b50506101408381015190830152610160808401519083015261018092830151929091019190915290565b60ff81168114610e5b57600080fd5b60006020828403121561515857600080fd5b81356147b881615137565b600080600080600080600080610100898b03121561518057600080fd5b505086359860208801359850604088013597606081013597506080810135965060a0810135955060c0810135945060e0013592509050565b6000602082840312156151ca57600080fd5b5035919050565b600080604083850312156151e457600080fd5b82356151ef81614ed9565b915060208301356151ff81614ed9565b809150509250929050565b6000806040838503121561521d57600080fd5b823561522881615137565b915060208381013567ffffffffffffffff8082111561524657600080fd5b818601915086601f83011261525a57600080fd5b81358181111561526c5761526c614f1a565b8060051b915061527d848301614f30565b818152918301840191848101908984111561529757600080fd5b938501935b838510156152c157843592506152b183614ed9565b828252938501939085019061529c565b8096505050505050509250929050565b600080600080600080600080610100898b0312156152ee57600080fd5b88356152f981615137565b9a60208a01359a5060408a013599606081013599506080810135985060a0810135975060c0810135965060e00135945092505050565b8051801515811461533f57600080fd5b919050565b60006020828403121561535657600080fd5b6147b88261532f565b6040808252810183905260006001600160fb1b0384111561537f57600080fd5b8360051b8086606085013760009083016060019081526020909201929092529392505050565b60005b838110156153c05781810151838201526020016153a8565b83811115613a725750506000910152565b600080600080608085870312156153e757600080fd5b845193506020850151925060408501519150606085015167ffffffffffffffff8082111561541457600080fd5b818701915087601f83011261542857600080fd5b81518181111561543a5761543a614f1a565b61544d601f8201601f1916602001614f30565b915080825288602082850101111561546457600080fd5b6154758160208401602086016153a5565b5094979396509194505050565b8060005b6008811015613a72578151845260209384019390910190600101615486565b6101208101818460005b60018110156154ce5781518352602092830192909101906001016154af565b5050506147b86020830184615482565b8060005b6003811015613a725781518452602093840193909101906001016154e2565b610160810161551082856154de565b6147b86060830184615482565b634e487b7160e01b600052601160045260246000fd5b600082198211156155465761554661551d565b500190565b600081518084526155638160208601602086016153a5565b601f01601f19169290920160200192915050565b6020815260006147b8602083018461554b565b634e487b7160e01b600052601260045260246000fd5b6000826155af576155af61558a565b500490565b600062ffffff808416806155ca576155ca61558a565b92169190910492915050565b60008160001904831182151516156155f0576155f061551d565b500290565b6101a08101818460005b600581101561561e5781518352602092830192909101906001016155ff565b5050506101008360a0840137600081529392505050565b610160810161564482856154de565b610100836060840137600081529392505050565b805160208201516001600160e01b031980821692919060048310156156875780818460040360031b1b83161693505b505050919050565b600080821280156001600160ff1b03849003851316156156b1576156b161551d565b600160ff1b83900384128116156156ca576156ca61551d565b50500190565b6000826156df576156df61558a565b500790565b60208082526024908201527f5a6b426f62506f6f6c3a20696e636f7272656374206465706f73697420616d6f604082015263756e747360e01b606082015260800190565b6000600160ff1b820161573d5761573d61551d565b5060000390565b6000828210156157565761575661551d565b500390565b60006020828403121561576d57600080fd5b5051919050565b60006020828403121561578657600080fd5b81516147b881615137565b600181815b808511156157cc5781600019048211156157b2576157b261551d565b808516156157bf57918102915b93841c9390800290615796565b509250929050565b6000826157e357506001612d23565b816157f057506000612d23565b816001811461580657600281146158105761582c565b6001915050612d23565b60ff8411156158215761582161551d565b50506001821b612d23565b5060208310610133831016604e8410600b841016171561584f575081810a612d23565b6158598383615791565b806000190482111561586d5761586d61551d565b029392505050565b60006147b883836157d4565b60006001600160481b038083168185168083038211156158a3576158a361551d565b01949350505050565b600062ffffff838116908316818110156158c8576158c861551d565b039392505050565b600063ffffffff838116908316818110156158c8576158c861551d565b60006001600160581b03838116908316818110156158c8576158c861551d565b60006001600160581b03808416806155ca576155ca61558a565b60006001600160481b03808416806155ca576155ca61558a565b60006001600160581b038083168185168083038211156158a3576158a361551d565b600063ffffffff80831681810361597c5761597c61551d565b6001019392505050565b6000806040838503121561599957600080fd5b6159a28361532f565b915060208301516151ff81615137565b634e487b7160e01b600052603260045260246000fd5b8183823760009101908152919050565b6000826159e7576159e761558a565b500690565b600080604083850312156159ff57600080fd5b505080516020909101519092909150565b600060018201615a2257615a2261551d565b5060010190565b60006001600160481b03838116908316818110156158c8576158c861551d565b634e487b7160e01b600052602160045260246000fd5b60008251615a718184602087016153a5565b919091019291505056fea2646970667358221220fa7609678ac81c6da4f63b538c6ee0aad8ce3e88b670453eb9eb6fac1d4dfaa364736f6c634300080f0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa84174000000000000000000000000a86c511832ead78d30ad49711874a9f3a1dfb84000000000000000000000000082907eaeb25d248dc82033e45b00a3e012ba2d0d0000000000000000000000009a7b4198065efe631a962e737bdfe1f44f2cb3ee000000000000000000000000668c5286ead26fac5fa944887f9d2f20f7ddf289
-----Decoded View---------------
Arg [0] : __pool_id (uint256): 0
Arg [1] : _token (address): 0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174
Arg [2] : _transfer_verifier (address): 0xA86C511832eAd78d30ad49711874a9F3a1dfb840
Arg [3] : _tree_verifier (address): 0x82907eAeB25D248dC82033E45b00A3E012Ba2d0D
Arg [4] : _batch_deposit_verifier (address): 0x9a7B4198065efE631a962e737bDfE1f44f2CB3EE
Arg [5] : _direct_deposit_queue (address): 0x668c5286eAD26fAC5fa944887F9D2F20f7DDF289
-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [1] : 0000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa84174
Arg [2] : 000000000000000000000000a86c511832ead78d30ad49711874a9f3a1dfb840
Arg [3] : 00000000000000000000000082907eaeb25d248dc82033e45b00a3e012ba2d0d
Arg [4] : 0000000000000000000000009a7b4198065efe631a962e737bdfe1f44f2cb3ee
Arg [5] : 000000000000000000000000668c5286ead26fac5fa944887f9d2f20f7ddf289
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 35 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
Loading...
Loading
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.