From 76b93ab0bba8e35add83ce717479c931320e2310 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Wed, 5 Jun 2024 12:06:39 +0200 Subject: [PATCH 01/20] First draft --- .../libraries/FiatTokenV2_2_ArbCompatible.sol | 2748 +++++++++++++++++ 1 file changed, 2748 insertions(+) create mode 100644 contracts/tokenbridge/libraries/FiatTokenV2_2_ArbCompatible.sol diff --git a/contracts/tokenbridge/libraries/FiatTokenV2_2_ArbCompatible.sol b/contracts/tokenbridge/libraries/FiatTokenV2_2_ArbCompatible.sol new file mode 100644 index 0000000000..3dd60b9bcc --- /dev/null +++ b/contracts/tokenbridge/libraries/FiatTokenV2_2_ArbCompatible.sol @@ -0,0 +1,2748 @@ +pragma solidity ^0.8.0; + +// contracts/interface/IERC1271.sol +/** + * Copyright 2023 Circle Internet Financial, LTD. All rights reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @dev Interface of the ERC1271 standard signature validation method for + * contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271]. + */ +interface IERC1271 { + /** + * @dev Should return whether the signature provided is valid for the provided data + * @param hash Hash of the data to be signed + * @param signature Signature byte array associated with the provided data hash + * @return magicValue bytes4 magic value 0x1626ba7e when function passes + */ + function isValidSignature(bytes32 hash, bytes memory signature) + external + view + returns (bytes4 magicValue); +} + +// contracts/util/ECRecover.sol +/** + * Copyright 2023 Circle Internet Financial, LTD. All rights reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @title ECRecover + * @notice A library that provides a safe ECDSA recovery function + */ +library ECRecover { + /** + * @notice Recover signer's address from a signed message + * @dev Adapted from: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/65e4ffde586ec89af3b7e9140bdc9235d1254853/contracts/cryptography/ECDSA.sol + * Modifications: Accept v, r, and s as separate arguments + * @param digest Keccak-256 hash digest of the signed message + * @param v v of the signature + * @param r r of the signature + * @param s s of the signature + * @return Signer address + */ + function recover(bytes32 digest, uint8 v, bytes32 r, bytes32 s) + internal + pure + returns (address) + { + // 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 (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): 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) { + revert("ECRecover: invalid signature 's' value"); + } + + if (v != 27 && v != 28) { + revert("ECRecover: invalid signature 'v' value"); + } + + // If the signature is valid (and not malleable), return the signer address + address signer = ecrecover(digest, v, r, s); + require(signer != address(0), "ECRecover: invalid signature"); + + return signer; + } + + /** + * @notice Recover signer's address from a signed message + * @dev Adapted from: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/0053ee040a7ff1dbc39691c9e67a69f564930a88/contracts/utils/cryptography/ECDSA.sol + * @param digest Keccak-256 hash digest of the signed message + * @param signature Signature byte array associated with hash + * @return Signer address + */ + function recover(bytes32 digest, bytes memory signature) internal pure returns (address) { + require(signature.length == 65, "ECRecover: invalid signature length"); + + 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 recover(digest, v, r, s); + } +} + +// contracts/util/EIP712.sol +/** + * Copyright 2023 Circle Internet Financial, LTD. All rights reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @title EIP712 + * @notice A library that provides EIP712 helper functions + */ +library EIP712 { + /** + * @notice Make EIP712 domain separator + * @param name Contract name + * @param version Contract version + * @param chainId Blockchain ID + * @return Domain separator + */ + function makeDomainSeparator(string memory name, string memory version, uint256 chainId) + internal + view + returns (bytes32) + { + return keccak256( + abi.encode( + // keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)") + 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f, + keccak256(bytes(name)), + keccak256(bytes(version)), + chainId, + address(this) + ) + ); + } + + /** + * @notice Make EIP712 domain separator + * @param name Contract name + * @param version Contract version + * @return Domain separator + */ + function makeDomainSeparator(string memory name, string memory version) + internal + view + returns (bytes32) + { + uint256 chainId; + assembly { + chainId := chainid() + } + return makeDomainSeparator(name, version, chainId); + } +} + +// contracts/util/MessageHashUtils.sol +/** + * Copyright 2023 Circle Internet Financial, LTD. All rights reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @dev Signature message hash utilities for producing digests to be consumed by {ECDSA} recovery or signing. + * + * The library provides methods for generating a hash of a message that conforms to the + * https://eips.ethereum.org/EIPS/eip-191[EIP 191] and https://eips.ethereum.org/EIPS/eip-712[EIP 712] + * specifications. + */ +library MessageHashUtils { + /** + * @dev Returns the keccak256 digest of an EIP-712 typed data (EIP-191 version `0x01`). + * Adapted from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/21bb89ef5bfc789b9333eb05e3ba2b7b284ac77c/contracts/utils/cryptography/MessageHashUtils.sol + * + * The digest is calculated from a `domainSeparator` and a `structHash`, by prefixing them with + * `\x19\x01` and hashing the result. It corresponds to the hash signed by the + * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] JSON-RPC method as part of EIP-712. + * + * @param domainSeparator Domain separator + * @param structHash Hashed EIP-712 data struct + * @return digest The keccak256 digest of an EIP-712 typed data + */ + function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) + internal + pure + returns (bytes32 digest) + { + assembly { + let ptr := mload(0x40) + mstore(ptr, "\x19\x01") + mstore(add(ptr, 0x02), domainSeparator) + mstore(add(ptr, 0x22), structHash) + digest := keccak256(ptr, 0x42) + } + } +} + +// contracts/v1/Ownable.sol +/** + * + * Copyright (c) 2018 zOS Global Limited. + * Copyright (c) 2018-2020 CENTRE SECZ + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/** + * @notice The Ownable contract has an owner address, and provides basic + * authorization control functions + * @dev Forked from https://github.com/OpenZeppelin/openzeppelin-labs/blob/3887ab77b8adafba4a26ace002f3a684c1a3388b/upgradeability_ownership/contracts/ownership/Ownable.sol + * Modifications: + * 1. Consolidate OwnableStorage into this contract (7/13/18) + * 2. Reformat, conform to Solidity 0.6 syntax, and add error messages (5/13/20) + * 3. Make public functions external (5/27/20) + */ +contract Ownable { + // Owner of the contract + address private _owner; + + /** + * @dev Event to show ownership has been transferred + * @param previousOwner representing the address of the previous owner + * @param newOwner representing the address of the new owner + */ + event OwnershipTransferred(address previousOwner, address newOwner); + + /** + * @dev The constructor sets the original owner of the contract to the sender account. + */ + constructor() { + setOwner(msg.sender); + } + + /** + * @dev Tells the address of the owner + * @return the address of the owner + */ + function owner() external view returns (address) { + return _owner; + } + + /** + * @dev Sets a new owner address + */ + function setOwner(address newOwner) internal { + _owner = newOwner; + } + + /** + * @dev Throws if called by any account other than the owner. + */ + modifier onlyOwner() { + require(msg.sender == _owner, "Ownable: caller is not the owner"); + _; + } + + /** + * @dev Allows the current owner to transfer control of the contract to a newOwner. + * @param newOwner The address to transfer ownership to. + */ + function transferOwnership(address newOwner) external onlyOwner { + require(newOwner != address(0), "Ownable: new owner is the zero address"); + emit OwnershipTransferred(_owner, newOwner); + setOwner(newOwner); + } +} + +// contracts/v2/EIP712Domain.sol +/** + * Copyright 2023 Circle Internet Financial, LTD. All rights reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// solhint-disable func-name-mixedcase + +/** + * @title EIP712 Domain + */ +contract EIP712Domain { + // was originally DOMAIN_SEPARATOR + // but that has been moved to a method so we can override it in V2_2+ + bytes32 internal _DEPRECATED_CACHED_DOMAIN_SEPARATOR; + + /** + * @notice Get the EIP712 Domain Separator. + * @return The bytes32 EIP712 domain separator. + */ + function DOMAIN_SEPARATOR() external view returns (bytes32) { + return _domainSeparator(); + } + + /** + * @dev Internal method to get the EIP712 Domain Separator. + * @return The bytes32 EIP712 domain separator. + */ + function _domainSeparator() internal view virtual returns (bytes32) { + return _DEPRECATED_CACHED_DOMAIN_SEPARATOR; + } +} + +// node_modules/@openzeppelin/contracts/math/SafeMath.sol + +/** + * @dev Wrappers over Solidity's arithmetic operations with added overflow + * checks. + * + * Arithmetic operations in Solidity wrap on overflow. This can easily result + * in bugs, because programmers usually assume that an overflow raises an + * error, which is the standard behavior in high level programming languages. + * `SafeMath` restores this intuition by reverting the transaction when an + * operation overflows. + * + * Using this library instead of the unchecked operations eliminates an entire + * class of bugs, so it's recommended to use it always. + */ +library SafeMath { + /** + * @dev Returns the addition of two unsigned integers, with an overflow flag. + * + * _Available since v3.4._ + */ + function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { + uint256 c = a + b; + if (c < a) return (false, 0); + return (true, c); + } + + /** + * @dev Returns the substraction of two unsigned integers, with an overflow flag. + * + * _Available since v3.4._ + */ + function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { + if (b > a) return (false, 0); + return (true, a - b); + } + + /** + * @dev Returns the multiplication of two unsigned integers, with an overflow flag. + * + * _Available since v3.4._ + */ + function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { + // Gas optimization: this is cheaper than requiring 'a' not being zero, but the + // benefit is lost if 'b' is also tested. + // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 + if (a == 0) return (true, 0); + uint256 c = a * b; + if (c / a != b) return (false, 0); + return (true, c); + } + + /** + * @dev Returns the division of two unsigned integers, with a division by zero flag. + * + * _Available since v3.4._ + */ + function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { + if (b == 0) return (false, 0); + return (true, a / b); + } + + /** + * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. + * + * _Available since v3.4._ + */ + function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { + if (b == 0) return (false, 0); + return (true, a % b); + } + + /** + * @dev Returns the addition of two unsigned integers, reverting on + * overflow. + * + * Counterpart to Solidity's `+` operator. + * + * Requirements: + * + * - Addition cannot overflow. + */ + function add(uint256 a, uint256 b) internal pure returns (uint256) { + uint256 c = a + b; + require(c >= a, "SafeMath: addition overflow"); + return c; + } + + /** + * @dev Returns the subtraction of two unsigned integers, reverting on + * overflow (when the result is negative). + * + * Counterpart to Solidity's `-` operator. + * + * Requirements: + * + * - Subtraction cannot overflow. + */ + function sub(uint256 a, uint256 b) internal pure returns (uint256) { + require(b <= a, "SafeMath: subtraction overflow"); + return a - b; + } + + /** + * @dev Returns the multiplication of two unsigned integers, reverting on + * overflow. + * + * Counterpart to Solidity's `*` operator. + * + * Requirements: + * + * - Multiplication cannot overflow. + */ + function mul(uint256 a, uint256 b) internal pure returns (uint256) { + if (a == 0) return 0; + uint256 c = a * b; + require(c / a == b, "SafeMath: multiplication overflow"); + return c; + } + + /** + * @dev Returns the integer division of two unsigned integers, reverting on + * division by zero. The result is rounded towards zero. + * + * Counterpart to Solidity's `/` operator. Note: this function uses a + * `revert` opcode (which leaves remaining gas untouched) while Solidity + * uses an invalid opcode to revert (consuming all remaining gas). + * + * Requirements: + * + * - The divisor cannot be zero. + */ + function div(uint256 a, uint256 b) internal pure returns (uint256) { + require(b > 0, "SafeMath: division by zero"); + return a / b; + } + + /** + * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), + * reverting when dividing by zero. + * + * Counterpart to Solidity's `%` operator. This function uses a `revert` + * opcode (which leaves remaining gas untouched) while Solidity uses an + * invalid opcode to revert (consuming all remaining gas). + * + * Requirements: + * + * - The divisor cannot be zero. + */ + function mod(uint256 a, uint256 b) internal pure returns (uint256) { + require(b > 0, "SafeMath: modulo by zero"); + return a % b; + } + + /** + * @dev Returns the subtraction of two unsigned integers, reverting with custom message on + * overflow (when the result is negative). + * + * CAUTION: This function is deprecated because it requires allocating memory for the error + * message unnecessarily. For custom revert reasons use {trySub}. + * + * Counterpart to Solidity's `-` operator. + * + * Requirements: + * + * - Subtraction cannot overflow. + */ + function sub(uint256 a, uint256 b, string memory errorMessage) + internal + pure + returns (uint256) + { + require(b <= a, errorMessage); + return a - b; + } + + /** + * @dev Returns the integer division of two unsigned integers, reverting with custom message on + * division by zero. The result is rounded towards zero. + * + * CAUTION: This function is deprecated because it requires allocating memory for the error + * message unnecessarily. For custom revert reasons use {tryDiv}. + * + * Counterpart to Solidity's `/` operator. Note: this function uses a + * `revert` opcode (which leaves remaining gas untouched) while Solidity + * uses an invalid opcode to revert (consuming all remaining gas). + * + * Requirements: + * + * - The divisor cannot be zero. + */ + function div(uint256 a, uint256 b, string memory errorMessage) + internal + pure + returns (uint256) + { + require(b > 0, errorMessage); + return a / b; + } + + /** + * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), + * reverting with custom message when dividing by zero. + * + * CAUTION: This function is deprecated because it requires allocating memory for the error + * message unnecessarily. For custom revert reasons use {tryMod}. + * + * Counterpart to Solidity's `%` operator. This function uses a `revert` + * opcode (which leaves remaining gas untouched) while Solidity uses an + * invalid opcode to revert (consuming all remaining gas). + * + * Requirements: + * + * - The divisor cannot be zero. + */ + function mod(uint256 a, uint256 b, string memory errorMessage) + internal + pure + returns (uint256) + { + require(b > 0, errorMessage); + return a % b; + } +} + +// node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol + +/** + * @dev Interface of the ERC20 standard as defined in the EIP. + */ +interface IERC20 { + /** + * @dev Returns the amount of tokens in existence. + */ + function totalSupply() external view returns (uint256); + + /** + * @dev Returns the amount of tokens owned by `account`. + */ + function balanceOf(address account) external view returns (uint256); + + /** + * @dev Moves `amount` tokens from the caller's account to `recipient`. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * Emits a {Transfer} event. + */ + function transfer(address recipient, uint256 amount) external returns (bool); + + /** + * @dev Returns the remaining number of tokens that `spender` will be + * allowed to spend on behalf of `owner` through {transferFrom}. This is + * zero by default. + * + * This value changes when {approve} or {transferFrom} are called. + */ + function allowance(address owner, address spender) external view returns (uint256); + + /** + * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * IMPORTANT: Beware that changing an allowance with this method brings the risk + * that someone may use both the old and the new allowance by unfortunate + * transaction ordering. One possible solution to mitigate this race + * condition is to first reduce the spender's allowance to 0 and set the + * desired value afterwards: + * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 + * + * Emits an {Approval} event. + */ + function approve(address spender, uint256 amount) external returns (bool); + + /** + * @dev Moves `amount` tokens from `sender` to `recipient` using the + * allowance mechanism. `amount` is then deducted from the caller's + * allowance. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * Emits a {Transfer} event. + */ + function transferFrom(address sender, address recipient, uint256 amount) + external + returns (bool); + + /** + * @dev Emitted when `value` tokens are moved from one account (`from`) to + * another (`to`). + * + * Note that `value` may be zero. + */ + event Transfer(address indexed from, address indexed to, uint256 value); + + /** + * @dev Emitted when the allowance of a `spender` for an `owner` is set by + * a call to {approve}. `value` is the new allowance. + */ + event Approval(address indexed owner, address indexed spender, uint256 value); +} + +// node_modules/@openzeppelin/contracts/utils/Address.sol + +/** + * @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 + * ==== + */ + function isContract(address account) internal view returns (bool) { + // This method relies on extcodesize, which returns 0 for contracts in + // construction, since the code is only stored at the end of the + // constructor execution. + + uint256 size; + // solhint-disable-next-line no-inline-assembly + assembly { + size := extcodesize(account) + } + return size > 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"); + + // solhint-disable-next-line avoid-low-level-calls, avoid-call-value + (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 functionCall(target, data, "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"); + require(isContract(target), "Address: call to non-contract"); + + // solhint-disable-next-line avoid-low-level-calls + (bool success, bytes memory returndata) = target.call{value: value}(data); + return _verifyCallResult(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) + { + require(isContract(target), "Address: static call to non-contract"); + + // solhint-disable-next-line avoid-low-level-calls + (bool success, bytes memory returndata) = target.staticcall(data); + return _verifyCallResult(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) + { + require(isContract(target), "Address: delegate call to non-contract"); + + // solhint-disable-next-line avoid-low-level-calls + (bool success, bytes memory returndata) = target.delegatecall(data); + return _verifyCallResult(success, returndata, errorMessage); + } + + function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) + private + pure + returns (bytes memory) + { + if (success) { + return returndata; + } else { + // 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 + + // solhint-disable-next-line no-inline-assembly + assembly { + let returndata_size := mload(returndata) + revert(add(32, returndata), returndata_size) + } + } else { + revert(errorMessage); + } + } + } +} + +// contracts/v1/AbstractFiatTokenV1.sol +/** + * Copyright 2023 Circle Internet Financial, LTD. All rights reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +abstract contract AbstractFiatTokenV1 is IERC20 { + function _approve(address owner, address spender, uint256 value) internal virtual; + + function _transfer(address from, address to, uint256 value) internal virtual; +} + +// contracts/v1/Blacklistable.sol +/** + * Copyright 2023 Circle Internet Financial, LTD. All rights reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @title Blacklistable Token + * @dev Allows accounts to be blacklisted by a "blacklister" role + */ +abstract contract Blacklistable is Ownable { + address public blacklister; + mapping(address => bool) internal _deprecatedBlacklisted; + + event Blacklisted(address indexed _account); + event UnBlacklisted(address indexed _account); + event BlacklisterChanged(address indexed newBlacklister); + + /** + * @dev Throws if called by any account other than the blacklister. + */ + modifier onlyBlacklister() { + require(msg.sender == blacklister, "Blacklistable: caller is not the blacklister"); + _; + } + + /** + * @dev Throws if argument account is blacklisted. + * @param _account The address to check. + */ + modifier notBlacklisted(address _account) { + require(!_isBlacklisted(_account), "Blacklistable: account is blacklisted"); + _; + } + + /** + * @notice Checks if account is blacklisted. + * @param _account The address to check. + * @return True if the account is blacklisted, false if the account is not blacklisted. + */ + function isBlacklisted(address _account) external view returns (bool) { + return _isBlacklisted(_account); + } + + /** + * @notice Adds account to blacklist. + * @param _account The address to blacklist. + */ + function blacklist(address _account) external onlyBlacklister { + _blacklist(_account); + emit Blacklisted(_account); + } + + /** + * @notice Removes account from blacklist. + * @param _account The address to remove from the blacklist. + */ + function unBlacklist(address _account) external onlyBlacklister { + _unBlacklist(_account); + emit UnBlacklisted(_account); + } + + /** + * @notice Updates the blacklister address. + * @param _newBlacklister The address of the new blacklister. + */ + function updateBlacklister(address _newBlacklister) external onlyOwner { + require(_newBlacklister != address(0), "Blacklistable: new blacklister is the zero address"); + blacklister = _newBlacklister; + emit BlacklisterChanged(blacklister); + } + + /** + * @dev Checks if account is blacklisted. + * @param _account The address to check. + * @return true if the account is blacklisted, false otherwise. + */ + function _isBlacklisted(address _account) internal view virtual returns (bool); + + /** + * @dev Helper method that blacklists an account. + * @param _account The address to blacklist. + */ + function _blacklist(address _account) internal virtual; + + /** + * @dev Helper method that unblacklists an account. + * @param _account The address to unblacklist. + */ + function _unBlacklist(address _account) internal virtual; +} + +// contracts/v1/Pausable.sol +/** + * + * Copyright (c) 2016 Smart Contract Solutions, Inc. + * Copyright (c) 2018-2020 CENTRE SECZ + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/** + * @notice Base contract which allows children to implement an emergency stop + * mechanism + * @dev Forked from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/feb665136c0dae9912e08397c1a21c4af3651ef3/contracts/lifecycle/Pausable.sol + * Modifications: + * 1. Added pauser role, switched pause/unpause to be onlyPauser (6/14/2018) + * 2. Removed whenNotPause/whenPaused from pause/unpause (6/14/2018) + * 3. Removed whenPaused (6/14/2018) + * 4. Switches ownable library to use ZeppelinOS (7/12/18) + * 5. Remove constructor (7/13/18) + * 6. Reformat, conform to Solidity 0.6 syntax and add error messages (5/13/20) + * 7. Make public functions external (5/27/20) + */ +contract Pausable is Ownable { + event Pause(); + event Unpause(); + event PauserChanged(address indexed newAddress); + + address public pauser; + bool public paused = false; + + /** + * @dev Modifier to make a function callable only when the contract is not paused. + */ + modifier whenNotPaused() { + require(!paused, "Pausable: paused"); + _; + } + + /** + * @dev throws if called by any account other than the pauser + */ + modifier onlyPauser() { + require(msg.sender == pauser, "Pausable: caller is not the pauser"); + _; + } + + /** + * @dev called by the owner to pause, triggers stopped state + */ + function pause() external onlyPauser { + paused = true; + emit Pause(); + } + + /** + * @dev called by the owner to unpause, returns to normal state + */ + function unpause() external onlyPauser { + paused = false; + emit Unpause(); + } + + /** + * @notice Updates the pauser address. + * @param _newPauser The address of the new pauser. + */ + function updatePauser(address _newPauser) external onlyOwner { + require(_newPauser != address(0), "Pausable: new pauser is the zero address"); + pauser = _newPauser; + emit PauserChanged(pauser); + } +} + +// contracts/util/SignatureChecker.sol +/** + * Copyright 2023 Circle Internet Financial, LTD. All rights reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @dev Signature verification helper that can be used instead of `ECRecover.recover` to seamlessly support both ECDSA + * signatures from externally owned accounts (EOAs) as well as ERC1271 signatures from smart contract wallets. + * + * Adapted from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/21bb89ef5bfc789b9333eb05e3ba2b7b284ac77c/contracts/utils/cryptography/SignatureChecker.sol + */ +library SignatureChecker { + /** + * @dev Checks if a signature is valid for a given signer and data hash. If the signer is a smart contract, the + * signature is validated against that smart contract using ERC1271, otherwise it's validated using `ECRecover.recover`. + * @param signer Address of the claimed signer + * @param digest Keccak-256 hash digest of the signed message + * @param signature Signature byte array associated with hash + */ + function isValidSignatureNow(address signer, bytes32 digest, bytes memory signature) + external + view + returns (bool) + { + if (!isContract(signer)) { + return ECRecover.recover(digest, signature) == signer; + } + return isValidERC1271SignatureNow(signer, digest, signature); + } + + /** + * @dev Checks if a signature is valid for a given signer and data hash. The signature is validated + * against the signer smart contract using ERC1271. + * @param signer Address of the claimed signer + * @param digest Keccak-256 hash digest of the signed message + * @param signature Signature byte array associated with hash + * + * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus + * change through time. It could return true at block N and false at block N+1 (or the opposite). + */ + function isValidERC1271SignatureNow(address signer, bytes32 digest, bytes memory signature) + internal + view + returns (bool) + { + (bool success, bytes memory result) = signer.staticcall( + abi.encodeWithSelector(IERC1271.isValidSignature.selector, digest, signature) + ); + return ( + success && result.length >= 32 + && abi.decode(result, (bytes32)) == bytes32(IERC1271.isValidSignature.selector) + ); + } + + /** + * @dev Checks if the input address is a smart contract. + */ + function isContract(address addr) internal view returns (bool) { + uint256 size; + assembly { + size := extcodesize(addr) + } + return size > 0; + } +} + +// contracts/v2/AbstractFiatTokenV2.sol +/** + * Copyright 2023 Circle Internet Financial, LTD. All rights reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +abstract contract AbstractFiatTokenV2 is AbstractFiatTokenV1 { + function _increaseAllowance(address owner, address spender, uint256 increment) + internal + virtual; + + function _decreaseAllowance(address owner, address spender, uint256 decrement) + internal + virtual; +} + +// node_modules/@openzeppelin/contracts/token/ERC20/SafeERC20.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 SafeMath for uint256; + 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' + // solhint-disable-next-line max-line-length + 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).add(value); + _callOptionalReturn( + token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance) + ); + } + + function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { + uint256 newAllowance = token.allowance(address(this), spender).sub( + value, "SafeERC20: decreased allowance below zero" + ); + _callOptionalReturn( + token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance) + ); + } + + /** + * @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 + // solhint-disable-next-line max-line-length + require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); + } + } +} + +// contracts/v1.1/Rescuable.sol +/** + * Copyright 2023 Circle Internet Financial, LTD. All rights reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +contract Rescuable is Ownable { + using SafeERC20 for IERC20; + + address private _rescuer; + + event RescuerChanged(address indexed newRescuer); + + /** + * @notice Returns current rescuer + * @return Rescuer's address + */ + function rescuer() external view returns (address) { + return _rescuer; + } + + /** + * @notice Revert if called by any account other than the rescuer. + */ + modifier onlyRescuer() { + require(msg.sender == _rescuer, "Rescuable: caller is not the rescuer"); + _; + } + + /** + * @notice Rescue ERC20 tokens locked up in this contract. + * @param tokenContract ERC20 token contract address + * @param to Recipient address + * @param amount Amount to withdraw + */ + function rescueERC20(IERC20 tokenContract, address to, uint256 amount) external onlyRescuer { + tokenContract.safeTransfer(to, amount); + } + + /** + * @notice Updates the rescuer address. + * @param newRescuer The address of the new rescuer. + */ + function updateRescuer(address newRescuer) external onlyOwner { + require(newRescuer != address(0), "Rescuable: new rescuer is the zero address"); + _rescuer = newRescuer; + emit RescuerChanged(newRescuer); + } +} + +// contracts/v1/FiatTokenV1.sol +/** + * Copyright 2023 Circle Internet Financial, LTD. All rights reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @title FiatToken + * @dev ERC20 Token backed by fiat reserves + */ +contract FiatTokenV1 is AbstractFiatTokenV1, Ownable, Pausable, Blacklistable { + using SafeMath for uint256; + + string public name; + string public symbol; + uint8 public decimals; + string public currency; + address public masterMinter; + bool internal initialized; + + /// @dev A mapping that stores the balance and blacklist states for a given address. + /// The first bit defines whether the address is blacklisted (1 if blacklisted, 0 otherwise). + /// The last 255 bits define the balance for the address. + mapping(address => uint256) internal balanceAndBlacklistStates; + mapping(address => mapping(address => uint256)) internal allowed; + uint256 internal totalSupply_ = 0; + mapping(address => bool) internal minters; + mapping(address => uint256) internal minterAllowed; + + event Mint(address indexed minter, address indexed to, uint256 amount); + event Burn(address indexed burner, uint256 amount); + event MinterConfigured(address indexed minter, uint256 minterAllowedAmount); + event MinterRemoved(address indexed oldMinter); + event MasterMinterChanged(address indexed newMasterMinter); + + /** + * @notice Initializes the fiat token contract. + * @param tokenName The name of the fiat token. + * @param tokenSymbol The symbol of the fiat token. + * @param tokenCurrency The fiat currency that the token represents. + * @param tokenDecimals The number of decimals that the token uses. + * @param newMasterMinter The masterMinter address for the fiat token. + * @param newPauser The pauser address for the fiat token. + * @param newBlacklister The blacklister address for the fiat token. + * @param newOwner The owner of the fiat token. + */ + function initialize( + string memory tokenName, + string memory tokenSymbol, + string memory tokenCurrency, + uint8 tokenDecimals, + address newMasterMinter, + address newPauser, + address newBlacklister, + address newOwner + ) public { + require(!initialized, "FiatToken: contract is already initialized"); + require(newMasterMinter != address(0), "FiatToken: new masterMinter is the zero address"); + require(newPauser != address(0), "FiatToken: new pauser is the zero address"); + require(newBlacklister != address(0), "FiatToken: new blacklister is the zero address"); + require(newOwner != address(0), "FiatToken: new owner is the zero address"); + + name = tokenName; + symbol = tokenSymbol; + currency = tokenCurrency; + decimals = tokenDecimals; + masterMinter = newMasterMinter; + pauser = newPauser; + blacklister = newBlacklister; + setOwner(newOwner); + initialized = true; + } + + /** + * @dev Throws if called by any account other than a minter. + */ + modifier onlyMinters() { + require(minters[msg.sender], "FiatToken: caller is not a minter"); + _; + } + + /** + * @notice Mints fiat tokens to an address. + * @param _to The address that will receive the minted tokens. + * @param _amount The amount of tokens to mint. Must be less than or equal + * to the minterAllowance of the caller. + * @return True if the operation was successful. + */ + function mint(address _to, uint256 _amount) + public + whenNotPaused + onlyMinters + notBlacklisted(msg.sender) + notBlacklisted(_to) + returns (bool) + { + require(_to != address(0), "FiatToken: mint to the zero address"); + require(_amount > 0, "FiatToken: mint amount not greater than 0"); + + uint256 mintingAllowedAmount = minterAllowed[msg.sender]; + require(_amount <= mintingAllowedAmount, "FiatToken: mint amount exceeds minterAllowance"); + + totalSupply_ = totalSupply_.add(_amount); + _setBalance(_to, _balanceOf(_to).add(_amount)); + minterAllowed[msg.sender] = mintingAllowedAmount.sub(_amount); + emit Mint(msg.sender, _to, _amount); + emit Transfer(address(0), _to, _amount); + return true; + } + + /** + * @dev Throws if called by any account other than the masterMinter + */ + modifier onlyMasterMinter() { + require(msg.sender == masterMinter, "FiatToken: caller is not the masterMinter"); + _; + } + + /** + * @notice Gets the minter allowance for an account. + * @param minter The address to check. + * @return The remaining minter allowance for the account. + */ + function minterAllowance(address minter) external view returns (uint256) { + return minterAllowed[minter]; + } + + /** + * @notice Checks if an account is a minter. + * @param account The address to check. + * @return True if the account is a minter, false if the account is not a minter. + */ + function isMinter(address account) external view returns (bool) { + return minters[account]; + } + + /** + * @notice Gets the remaining amount of fiat tokens a spender is allowed to transfer on + * behalf of the token owner. + * @param owner The token owner's address. + * @param spender The spender's address. + * @return The remaining allowance. + */ + function allowance(address owner, address spender) external view override returns (uint256) { + return allowed[owner][spender]; + } + + /** + * @notice Gets the totalSupply of the fiat token. + * @return The totalSupply of the fiat token. + */ + function totalSupply() external view override returns (uint256) { + return totalSupply_; + } + + /** + * @notice Gets the fiat token balance of an account. + * @param account The address to check. + * @return balance The fiat token balance of the account. + */ + function balanceOf(address account) external view override returns (uint256) { + return _balanceOf(account); + } + + /** + * @notice Sets a fiat token allowance for a spender to spend on behalf of the caller. + * @param spender The spender's address. + * @param value The allowance amount. + * @return True if the operation was successful. + */ + function approve(address spender, uint256 value) + external + virtual + override + whenNotPaused + notBlacklisted(msg.sender) + notBlacklisted(spender) + returns (bool) + { + _approve(msg.sender, spender, value); + return true; + } + + /** + * @dev Internal function to set allowance. + * @param owner Token owner's address. + * @param spender Spender's address. + * @param value Allowance amount. + */ + function _approve(address owner, address spender, uint256 value) internal override { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + allowed[owner][spender] = value; + emit Approval(owner, spender, value); + } + + /** + * @notice Transfers tokens from an address to another by spending the caller's allowance. + * @dev The caller must have some fiat token allowance on the payer's tokens. + * @param from Payer's address. + * @param to Payee's address. + * @param value Transfer amount. + * @return True if the operation was successful. + */ + function transferFrom(address from, address to, uint256 value) + external + override + whenNotPaused + notBlacklisted(msg.sender) + notBlacklisted(from) + notBlacklisted(to) + returns (bool) + { + require(value <= allowed[from][msg.sender], "ERC20: transfer amount exceeds allowance"); + _transfer(from, to, value); + allowed[from][msg.sender] = allowed[from][msg.sender].sub(value); + return true; + } + + /** + * @notice Transfers tokens from the caller. + * @param to Payee's address. + * @param value Transfer amount. + * @return True if the operation was successful. + */ + function transfer(address to, uint256 value) + external + override + whenNotPaused + notBlacklisted(msg.sender) + notBlacklisted(to) + returns (bool) + { + _transfer(msg.sender, to, value); + return true; + } + + /** + * @dev Internal function to process transfers. + * @param from Payer's address. + * @param to Payee's address. + * @param value Transfer amount. + */ + function _transfer(address from, address to, uint256 value) internal override { + require(from != address(0), "ERC20: transfer from the zero address"); + require(to != address(0), "ERC20: transfer to the zero address"); + require(value <= _balanceOf(from), "ERC20: transfer amount exceeds balance"); + + _setBalance(from, _balanceOf(from).sub(value)); + _setBalance(to, _balanceOf(to).add(value)); + emit Transfer(from, to, value); + } + + /** + * @notice Adds or updates a new minter with a mint allowance. + * @param minter The address of the minter. + * @param minterAllowedAmount The minting amount allowed for the minter. + * @return True if the operation was successful. + */ + function configureMinter(address minter, uint256 minterAllowedAmount) + external + whenNotPaused + onlyMasterMinter + returns (bool) + { + minters[minter] = true; + minterAllowed[minter] = minterAllowedAmount; + emit MinterConfigured(minter, minterAllowedAmount); + return true; + } + + /** + * @notice Removes a minter. + * @param minter The address of the minter to remove. + * @return True if the operation was successful. + */ + function removeMinter(address minter) external onlyMasterMinter returns (bool) { + minters[minter] = false; + minterAllowed[minter] = 0; + emit MinterRemoved(minter); + return true; + } + + /** + * @notice Allows a minter to burn some of its own tokens. + * @dev The caller must be a minter, must not be blacklisted, and the amount to burn + * should be less than or equal to the account's balance. + * @param _amount the amount of tokens to be burned. + */ + function burn(uint256 _amount) public whenNotPaused onlyMinters notBlacklisted(msg.sender) { + uint256 balance = _balanceOf(msg.sender); + require(_amount > 0, "FiatToken: burn amount not greater than 0"); + require(balance >= _amount, "FiatToken: burn amount exceeds balance"); + + totalSupply_ = totalSupply_.sub(_amount); + _setBalance(msg.sender, balance.sub(_amount)); + emit Burn(msg.sender, _amount); + emit Transfer(msg.sender, address(0), _amount); + } + + /** + * @notice Updates the master minter address. + * @param _newMasterMinter The address of the new master minter. + */ + function updateMasterMinter(address _newMasterMinter) external onlyOwner { + require(_newMasterMinter != address(0), "FiatToken: new masterMinter is the zero address"); + masterMinter = _newMasterMinter; + emit MasterMinterChanged(masterMinter); + } + + /** + * + */ + function _blacklist(address _account) internal override { + _setBlacklistState(_account, true); + } + + /** + * + */ + function _unBlacklist(address _account) internal override { + _setBlacklistState(_account, false); + } + + /** + * @dev Helper method that sets the blacklist state of an account. + * @param _account The address of the account. + * @param _shouldBlacklist True if the account should be blacklisted, false if the account should be unblacklisted. + */ + function _setBlacklistState(address _account, bool _shouldBlacklist) internal virtual { + _deprecatedBlacklisted[_account] = _shouldBlacklist; + } + + /** + * @dev Helper method that sets the balance of an account. + * @param _account The address of the account. + * @param _balance The new fiat token balance of the account. + */ + function _setBalance(address _account, uint256 _balance) internal virtual { + balanceAndBlacklistStates[_account] = _balance; + } + + /** + * + */ + function _isBlacklisted(address _account) internal view virtual override returns (bool) { + return _deprecatedBlacklisted[_account]; + } + + /** + * @dev Helper method to obtain the balance of an account. + * @param _account The address of the account. + * @return The fiat token balance of the account. + */ + function _balanceOf(address _account) internal view virtual returns (uint256) { + return balanceAndBlacklistStates[_account]; + } +} + +// contracts/v2/EIP2612.sol +/** + * Copyright 2023 Circle Internet Financial, LTD. All rights reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @title EIP-2612 + * @notice Provide internal implementation for gas-abstracted approvals + */ +abstract contract EIP2612 is AbstractFiatTokenV2, EIP712Domain { + // keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)") + bytes32 public constant PERMIT_TYPEHASH = + 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9; + + mapping(address => uint256) private _permitNonces; + + /** + * @notice Nonces for permit + * @param owner Token owner's address (Authorizer) + * @return Next nonce + */ + function nonces(address owner) external view returns (uint256) { + return _permitNonces[owner]; + } + + /** + * @notice Verify a signed approval permit and execute if valid + * @param owner Token owner's address (Authorizer) + * @param spender Spender's address + * @param value Amount of allowance + * @param deadline The time at which the signature expires (unix time), or max uint256 value to signal no expiration + * @param v v of the signature + * @param r r of the signature + * @param s s of the signature + */ + function _permit( + address owner, + address spender, + uint256 value, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) internal { + _permit(owner, spender, value, deadline, abi.encodePacked(r, s, v)); + } + + /** + * @notice Verify a signed approval permit and execute if valid + * @dev EOA wallet signatures should be packed in the order of r, s, v. + * @param owner Token owner's address (Authorizer) + * @param spender Spender's address + * @param value Amount of allowance + * @param deadline The time at which the signature expires (unix time), or max uint256 value to signal no expiration + * @param signature Signature byte array signed by an EOA wallet or a contract wallet + */ + function _permit( + address owner, + address spender, + uint256 value, + uint256 deadline, + bytes memory signature + ) internal { + require( + deadline == type(uint256).max || deadline >= block.timestamp, + "FiatTokenV2: permit is expired" + ); + + bytes32 typedDataHash = MessageHashUtils.toTypedDataHash( + _domainSeparator(), + keccak256( + abi.encode(PERMIT_TYPEHASH, owner, spender, value, _permitNonces[owner]++, deadline) + ) + ); + require( + SignatureChecker.isValidSignatureNow(owner, typedDataHash, signature), + "EIP2612: invalid signature" + ); + + _approve(owner, spender, value); + } +} + +// contracts/v2/EIP3009.sol +/** + * Copyright 2023 Circle Internet Financial, LTD. All rights reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @title EIP-3009 + * @notice Provide internal implementation for gas-abstracted transfers + * @dev Contracts that inherit from this must wrap these with publicly + * accessible functions, optionally adding modifiers where necessary + */ +abstract contract EIP3009 is AbstractFiatTokenV2, EIP712Domain { + // keccak256("TransferWithAuthorization(address from,address to,uint256 value,uint256 validAfter,uint256 validBefore,bytes32 nonce)") + bytes32 public constant TRANSFER_WITH_AUTHORIZATION_TYPEHASH = + 0x7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a2267; + + // keccak256("ReceiveWithAuthorization(address from,address to,uint256 value,uint256 validAfter,uint256 validBefore,bytes32 nonce)") + bytes32 public constant RECEIVE_WITH_AUTHORIZATION_TYPEHASH = + 0xd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de8; + + // keccak256("CancelAuthorization(address authorizer,bytes32 nonce)") + bytes32 public constant CANCEL_AUTHORIZATION_TYPEHASH = + 0x158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a1597429; + + /** + * @dev authorizer address => nonce => bool (true if nonce is used) + */ + mapping(address => mapping(bytes32 => bool)) private _authorizationStates; + + event AuthorizationUsed(address indexed authorizer, bytes32 indexed nonce); + event AuthorizationCanceled(address indexed authorizer, bytes32 indexed nonce); + + /** + * @notice Returns the state of an authorization + * @dev Nonces are randomly generated 32-byte data unique to the + * authorizer's address + * @param authorizer Authorizer's address + * @param nonce Nonce of the authorization + * @return True if the nonce is used + */ + function authorizationState(address authorizer, bytes32 nonce) external view returns (bool) { + return _authorizationStates[authorizer][nonce]; + } + + /** + * @notice Execute a transfer with a signed authorization + * @param from Payer's address (Authorizer) + * @param to Payee's address + * @param value Amount to be transferred + * @param validAfter The time after which this is valid (unix time) + * @param validBefore The time before which this is valid (unix time) + * @param nonce Unique nonce + * @param v v of the signature + * @param r r of the signature + * @param s s of the signature + */ + function _transferWithAuthorization( + address from, + address to, + uint256 value, + uint256 validAfter, + uint256 validBefore, + bytes32 nonce, + uint8 v, + bytes32 r, + bytes32 s + ) internal { + _transferWithAuthorization( + from, to, value, validAfter, validBefore, nonce, abi.encodePacked(r, s, v) + ); + } + + /** + * @notice Execute a transfer with a signed authorization + * @dev EOA wallet signatures should be packed in the order of r, s, v. + * @param from Payer's address (Authorizer) + * @param to Payee's address + * @param value Amount to be transferred + * @param validAfter The time after which this is valid (unix time) + * @param validBefore The time before which this is valid (unix time) + * @param nonce Unique nonce + * @param signature Signature byte array produced by an EOA wallet or a contract wallet + */ + function _transferWithAuthorization( + address from, + address to, + uint256 value, + uint256 validAfter, + uint256 validBefore, + bytes32 nonce, + bytes memory signature + ) internal { + _requireValidAuthorization(from, nonce, validAfter, validBefore); + _requireValidSignature( + from, + keccak256( + abi.encode( + TRANSFER_WITH_AUTHORIZATION_TYPEHASH, + from, + to, + value, + validAfter, + validBefore, + nonce + ) + ), + signature + ); + + _markAuthorizationAsUsed(from, nonce); + _transfer(from, to, value); + } + + /** + * @notice Receive a transfer with a signed authorization from the payer + * @dev This has an additional check to ensure that the payee's address + * matches the caller of this function to prevent front-running attacks. + * @param from Payer's address (Authorizer) + * @param to Payee's address + * @param value Amount to be transferred + * @param validAfter The time after which this is valid (unix time) + * @param validBefore The time before which this is valid (unix time) + * @param nonce Unique nonce + * @param v v of the signature + * @param r r of the signature + * @param s s of the signature + */ + function _receiveWithAuthorization( + address from, + address to, + uint256 value, + uint256 validAfter, + uint256 validBefore, + bytes32 nonce, + uint8 v, + bytes32 r, + bytes32 s + ) internal { + _receiveWithAuthorization( + from, to, value, validAfter, validBefore, nonce, abi.encodePacked(r, s, v) + ); + } + + /** + * @notice Receive a transfer with a signed authorization from the payer + * @dev This has an additional check to ensure that the payee's address + * matches the caller of this function to prevent front-running attacks. + * EOA wallet signatures should be packed in the order of r, s, v. + * @param from Payer's address (Authorizer) + * @param to Payee's address + * @param value Amount to be transferred + * @param validAfter The time after which this is valid (unix time) + * @param validBefore The time before which this is valid (unix time) + * @param nonce Unique nonce + * @param signature Signature byte array produced by an EOA wallet or a contract wallet + */ + function _receiveWithAuthorization( + address from, + address to, + uint256 value, + uint256 validAfter, + uint256 validBefore, + bytes32 nonce, + bytes memory signature + ) internal { + require(to == msg.sender, "FiatTokenV2: caller must be the payee"); + _requireValidAuthorization(from, nonce, validAfter, validBefore); + _requireValidSignature( + from, + keccak256( + abi.encode( + RECEIVE_WITH_AUTHORIZATION_TYPEHASH, + from, + to, + value, + validAfter, + validBefore, + nonce + ) + ), + signature + ); + + _markAuthorizationAsUsed(from, nonce); + _transfer(from, to, value); + } + + /** + * @notice Attempt to cancel an authorization + * @param authorizer Authorizer's address + * @param nonce Nonce of the authorization + * @param v v of the signature + * @param r r of the signature + * @param s s of the signature + */ + function _cancelAuthorization(address authorizer, bytes32 nonce, uint8 v, bytes32 r, bytes32 s) + internal + { + _cancelAuthorization(authorizer, nonce, abi.encodePacked(r, s, v)); + } + + /** + * @notice Attempt to cancel an authorization + * @dev EOA wallet signatures should be packed in the order of r, s, v. + * @param authorizer Authorizer's address + * @param nonce Nonce of the authorization + * @param signature Signature byte array produced by an EOA wallet or a contract wallet + */ + function _cancelAuthorization(address authorizer, bytes32 nonce, bytes memory signature) + internal + { + _requireUnusedAuthorization(authorizer, nonce); + _requireValidSignature( + authorizer, + keccak256(abi.encode(CANCEL_AUTHORIZATION_TYPEHASH, authorizer, nonce)), + signature + ); + + _authorizationStates[authorizer][nonce] = true; + emit AuthorizationCanceled(authorizer, nonce); + } + + /** + * @notice Validates that signature against input data struct + * @param signer Signer's address + * @param dataHash Hash of encoded data struct + * @param signature Signature byte array produced by an EOA wallet or a contract wallet + */ + function _requireValidSignature(address signer, bytes32 dataHash, bytes memory signature) + private + view + { + require( + SignatureChecker.isValidSignatureNow( + signer, MessageHashUtils.toTypedDataHash(_domainSeparator(), dataHash), signature + ), + "FiatTokenV2: invalid signature" + ); + } + + /** + * @notice Check that an authorization is unused + * @param authorizer Authorizer's address + * @param nonce Nonce of the authorization + */ + function _requireUnusedAuthorization(address authorizer, bytes32 nonce) private view { + require( + !_authorizationStates[authorizer][nonce], + "FiatTokenV2: authorization is used or canceled" + ); + } + + /** + * @notice Check that authorization is valid + * @param authorizer Authorizer's address + * @param nonce Nonce of the authorization + * @param validAfter The time after which this is valid (unix time) + * @param validBefore The time before which this is valid (unix time) + */ + function _requireValidAuthorization( + address authorizer, + bytes32 nonce, + uint256 validAfter, + uint256 validBefore + ) private view { + require(block.timestamp > validAfter, "FiatTokenV2: authorization is not yet valid"); + require(block.timestamp < validBefore, "FiatTokenV2: authorization is expired"); + _requireUnusedAuthorization(authorizer, nonce); + } + + /** + * @notice Mark an authorization as used + * @param authorizer Authorizer's address + * @param nonce Nonce of the authorization + */ + function _markAuthorizationAsUsed(address authorizer, bytes32 nonce) private { + _authorizationStates[authorizer][nonce] = true; + emit AuthorizationUsed(authorizer, nonce); + } +} + +// contracts/v1.1/FiatTokenV1_1.sol +/** + * Copyright 2023 Circle Internet Financial, LTD. All rights reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @title FiatTokenV1_1 + * @dev ERC20 Token backed by fiat reserves + */ +contract FiatTokenV1_1 is FiatTokenV1, Rescuable {} + +// contracts/v2/FiatTokenV2.sol +/** + * Copyright 2023 Circle Internet Financial, LTD. All rights reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @title FiatToken V2 + * @notice ERC20 Token backed by fiat reserves, version 2 + */ +contract FiatTokenV2 is FiatTokenV1_1, EIP3009, EIP2612 { + uint8 internal _initializedVersion; + + /** + * @notice Initialize v2 + * @param newName New token name + */ + function initializeV2(string calldata newName) external { + // solhint-disable-next-line reason-string + require(initialized && _initializedVersion == 0); + name = newName; + _DEPRECATED_CACHED_DOMAIN_SEPARATOR = EIP712.makeDomainSeparator(newName, "2"); + _initializedVersion = 1; + } + + /** + * @notice Increase the allowance by a given increment + * @param spender Spender's address + * @param increment Amount of increase in allowance + * @return True if successful + */ + function increaseAllowance(address spender, uint256 increment) + external + virtual + whenNotPaused + notBlacklisted(msg.sender) + notBlacklisted(spender) + returns (bool) + { + _increaseAllowance(msg.sender, spender, increment); + return true; + } + + /** + * @notice Decrease the allowance by a given decrement + * @param spender Spender's address + * @param decrement Amount of decrease in allowance + * @return True if successful + */ + function decreaseAllowance(address spender, uint256 decrement) + external + virtual + whenNotPaused + notBlacklisted(msg.sender) + notBlacklisted(spender) + returns (bool) + { + _decreaseAllowance(msg.sender, spender, decrement); + return true; + } + + /** + * @notice Execute a transfer with a signed authorization + * @param from Payer's address (Authorizer) + * @param to Payee's address + * @param value Amount to be transferred + * @param validAfter The time after which this is valid (unix time) + * @param validBefore The time before which this is valid (unix time) + * @param nonce Unique nonce + * @param v v of the signature + * @param r r of the signature + * @param s s of the signature + */ + function transferWithAuthorization( + address from, + address to, + uint256 value, + uint256 validAfter, + uint256 validBefore, + bytes32 nonce, + uint8 v, + bytes32 r, + bytes32 s + ) external whenNotPaused notBlacklisted(from) notBlacklisted(to) { + _transferWithAuthorization(from, to, value, validAfter, validBefore, nonce, v, r, s); + } + + /** + * @notice Receive a transfer with a signed authorization from the payer + * @dev This has an additional check to ensure that the payee's address + * matches the caller of this function to prevent front-running attacks. + * @param from Payer's address (Authorizer) + * @param to Payee's address + * @param value Amount to be transferred + * @param validAfter The time after which this is valid (unix time) + * @param validBefore The time before which this is valid (unix time) + * @param nonce Unique nonce + * @param v v of the signature + * @param r r of the signature + * @param s s of the signature + */ + function receiveWithAuthorization( + address from, + address to, + uint256 value, + uint256 validAfter, + uint256 validBefore, + bytes32 nonce, + uint8 v, + bytes32 r, + bytes32 s + ) external whenNotPaused notBlacklisted(from) notBlacklisted(to) { + _receiveWithAuthorization(from, to, value, validAfter, validBefore, nonce, v, r, s); + } + + /** + * @notice Attempt to cancel an authorization + * @dev Works only if the authorization is not yet used. + * @param authorizer Authorizer's address + * @param nonce Nonce of the authorization + * @param v v of the signature + * @param r r of the signature + * @param s s of the signature + */ + function cancelAuthorization(address authorizer, bytes32 nonce, uint8 v, bytes32 r, bytes32 s) + external + whenNotPaused + { + _cancelAuthorization(authorizer, nonce, v, r, s); + } + + /** + * @notice Update allowance with a signed permit + * @param owner Token owner's address (Authorizer) + * @param spender Spender's address + * @param value Amount of allowance + * @param deadline The time at which the signature expires (unix time), or max uint256 value to signal no expiration + * @param v v of the signature + * @param r r of the signature + * @param s s of the signature + */ + function permit( + address owner, + address spender, + uint256 value, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) external virtual whenNotPaused notBlacklisted(owner) notBlacklisted(spender) { + _permit(owner, spender, value, deadline, v, r, s); + } + + /** + * @dev Internal function to increase the allowance by a given increment + * @param owner Token owner's address + * @param spender Spender's address + * @param increment Amount of increase + */ + function _increaseAllowance(address owner, address spender, uint256 increment) + internal + override + { + _approve(owner, spender, allowed[owner][spender] + increment); + } + + /** + * @dev Internal function to decrease the allowance by a given decrement + * @param owner Token owner's address + * @param spender Spender's address + * @param decrement Amount of decrease + */ + function _decreaseAllowance(address owner, address spender, uint256 decrement) + internal + override + { + _approve(owner, spender, allowed[owner][spender] - decrement); + } +} + +// contracts/v2/FiatTokenV2_1.sol +/** + * Copyright 2023 Circle Internet Financial, LTD. All rights reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// solhint-disable func-name-mixedcase + +/** + * @title FiatToken V2.1 + * @notice ERC20 Token backed by fiat reserves, version 2.1 + */ +contract FiatTokenV2_1 is FiatTokenV2 { + /** + * @notice Initialize v2.1 + * @param lostAndFound The address to which the locked funds are sent + */ + function initializeV2_1(address lostAndFound) external { + // solhint-disable-next-line reason-string + require(_initializedVersion == 1); + + uint256 lockedAmount = _balanceOf(address(this)); + if (lockedAmount > 0) { + _transfer(address(this), lostAndFound, lockedAmount); + } + _blacklist(address(this)); + + _initializedVersion = 2; + } + + /** + * @notice Version string for the EIP712 domain separator + * @return Version string + */ + function version() external pure returns (string memory) { + return "2"; + } +} + +// contracts/v2/FiatTokenV2_2.sol +/** + * Copyright 2023 Circle Internet Financial, LTD. All rights reserved. + * + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// solhint-disable-line no-unused-import +// solhint-disable-line no-unused-import +// solhint-disable-line no-unused-import +// solhint-disable-line no-unused-import + +// solhint-disable func-name-mixedcase + +/** + * @title FiatToken V2.2 + * @notice ERC20 Token backed by fiat reserves, version 2.2 + */ +contract FiatTokenV2_2 is FiatTokenV2_1 { + /** + * @notice Initialize v2.2 + * @param accountsToBlacklist A list of accounts to migrate from the old blacklist + * @param newSymbol New token symbol + * data structure to the new blacklist data structure. + */ + function initializeV2_2(address[] calldata accountsToBlacklist, string calldata newSymbol) + external + { + // solhint-disable-next-line reason-string + require(_initializedVersion == 2); + + // Update fiat token symbol + symbol = newSymbol; + + // Add previously blacklisted accounts to the new blacklist data structure + // and remove them from the old blacklist data structure. + for (uint256 i = 0; i < accountsToBlacklist.length; i++) { + require( + _deprecatedBlacklisted[accountsToBlacklist[i]], + "FiatTokenV2_2: Blacklisting previously unblacklisted account!" + ); + _blacklist(accountsToBlacklist[i]); + delete _deprecatedBlacklisted[accountsToBlacklist[i]]; + } + _blacklist(address(this)); + delete _deprecatedBlacklisted[address(this)]; + + _initializedVersion = 3; + } + + /** + * @dev Internal function to get the current chain id. + * @return The current chain id. + */ + function _chainId() internal view virtual returns (uint256) { + uint256 chainId; + assembly { + chainId := chainid() + } + return chainId; + } + + /** + * + */ + function _domainSeparator() internal view override returns (bytes32) { + return EIP712.makeDomainSeparator(name, "2", _chainId()); + } + + /** + * @notice Update allowance with a signed permit + * @dev EOA wallet signatures should be packed in the order of r, s, v. + * @param owner Token owner's address (Authorizer) + * @param spender Spender's address + * @param value Amount of allowance + * @param deadline The time at which the signature expires (unix time), or max uint256 value to signal no expiration + * @param signature Signature bytes signed by an EOA wallet or a contract wallet + */ + function permit( + address owner, + address spender, + uint256 value, + uint256 deadline, + bytes memory signature + ) external whenNotPaused { + _permit(owner, spender, value, deadline, signature); + } + + /** + * @notice Execute a transfer with a signed authorization + * @dev EOA wallet signatures should be packed in the order of r, s, v. + * @param from Payer's address (Authorizer) + * @param to Payee's address + * @param value Amount to be transferred + * @param validAfter The time after which this is valid (unix time) + * @param validBefore The time before which this is valid (unix time) + * @param nonce Unique nonce + * @param signature Signature bytes signed by an EOA wallet or a contract wallet + */ + function transferWithAuthorization( + address from, + address to, + uint256 value, + uint256 validAfter, + uint256 validBefore, + bytes32 nonce, + bytes memory signature + ) external whenNotPaused notBlacklisted(from) notBlacklisted(to) { + _transferWithAuthorization(from, to, value, validAfter, validBefore, nonce, signature); + } + + /** + * @notice Receive a transfer with a signed authorization from the payer + * @dev This has an additional check to ensure that the payee's address + * matches the caller of this function to prevent front-running attacks. + * EOA wallet signatures should be packed in the order of r, s, v. + * @param from Payer's address (Authorizer) + * @param to Payee's address + * @param value Amount to be transferred + * @param validAfter The time after which this is valid (unix time) + * @param validBefore The time before which this is valid (unix time) + * @param nonce Unique nonce + * @param signature Signature bytes signed by an EOA wallet or a contract wallet + */ + function receiveWithAuthorization( + address from, + address to, + uint256 value, + uint256 validAfter, + uint256 validBefore, + bytes32 nonce, + bytes memory signature + ) external whenNotPaused notBlacklisted(from) notBlacklisted(to) { + _receiveWithAuthorization(from, to, value, validAfter, validBefore, nonce, signature); + } + + /** + * @notice Attempt to cancel an authorization + * @dev Works only if the authorization is not yet used. + * EOA wallet signatures should be packed in the order of r, s, v. + * @param authorizer Authorizer's address + * @param nonce Nonce of the authorization + * @param signature Signature bytes signed by an EOA wallet or a contract wallet + */ + function cancelAuthorization(address authorizer, bytes32 nonce, bytes memory signature) + external + whenNotPaused + { + _cancelAuthorization(authorizer, nonce, signature); + } + + /** + * @dev Helper method that sets the blacklist state of an account on balanceAndBlacklistStates. + * If _shouldBlacklist is true, we apply a (1 << 255) bitmask with an OR operation on the + * account's balanceAndBlacklistState. This flips the high bit for the account to 1, + * indicating that the account is blacklisted. + * + * If _shouldBlacklist if false, we reset the account's balanceAndBlacklistStates to their + * balances. This clears the high bit for the account, indicating that the account is unblacklisted. + * @param _account The address of the account. + * @param _shouldBlacklist True if the account should be blacklisted, false if the account should be unblacklisted. + */ + function _setBlacklistState(address _account, bool _shouldBlacklist) internal override { + balanceAndBlacklistStates[_account] = _shouldBlacklist + ? balanceAndBlacklistStates[_account] | (1 << 255) + : _balanceOf(_account); + } + + /** + * @dev Helper method that sets the balance of an account on balanceAndBlacklistStates. + * Since balances are stored in the last 255 bits of the balanceAndBlacklistStates value, + * we need to ensure that the updated balance does not exceed (2^255 - 1). + * Since blacklisted accounts' balances cannot be updated, the method will also + * revert if the account is blacklisted + * @param _account The address of the account. + * @param _balance The new fiat token balance of the account (max: (2^255 - 1)). + */ + function _setBalance(address _account, uint256 _balance) internal override { + require(_balance <= ((1 << 255) - 1), "FiatTokenV2_2: Balance exceeds (2^255 - 1)"); + require(!_isBlacklisted(_account), "FiatTokenV2_2: Account is blacklisted"); + + balanceAndBlacklistStates[_account] = _balance; + } + + /** + * + */ + function _isBlacklisted(address _account) internal view override returns (bool) { + return balanceAndBlacklistStates[_account] >> 255 == 1; + } + + /** + * @dev Helper method to obtain the balance of an account. Since balances + * are stored in the last 255 bits of the balanceAndBlacklistStates value, + * we apply a ((1 << 255) - 1) bit bitmask with an AND operation on the + * balanceAndBlacklistState to obtain the balance. + * @param _account The address of the account. + * @return The fiat token balance of the account. + */ + function _balanceOf(address _account) internal view override returns (uint256) { + return balanceAndBlacklistStates[_account] & ((1 << 255) - 1); + } + + /** + * + */ + function approve(address spender, uint256 value) + external + override(FiatTokenV1, IERC20) + whenNotPaused + returns (bool) + { + _approve(msg.sender, spender, value); + return true; + } + + /** + * + */ + function permit( + address owner, + address spender, + uint256 value, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) external override whenNotPaused { + _permit(owner, spender, value, deadline, v, r, s); + } + + /** + * + */ + function increaseAllowance(address spender, uint256 increment) + external + override + whenNotPaused + returns (bool) + { + _increaseAllowance(msg.sender, spender, increment); + return true; + } + + /** + * + */ + function decreaseAllowance(address spender, uint256 decrement) + external + override + whenNotPaused + returns (bool) + { + _decreaseAllowance(msg.sender, spender, decrement); + return true; + } +} + +import {IArbToken} from "../arbitrum/IArbToken.sol"; + +/** + * @title A custom token contract that is based on Circle's FiatToken implementation, + * but also implements IArbToken so it can be used as bridged USDC in Arbitrum token bridge. + * This implementation of bridged USDC can be upgraded to native USDC due to storage compatibility. + * @dev + */ +contract FiatTokenV2_2_ArbCompatible is FiatTokenV2_2, IArbToken { + address public l2Gateway; + address public override l1Address; + + modifier onlyGateway() { + require(msg.sender == l2Gateway, "ONLY_GATEWAY"); + _; + } + + /** + * @notice initialize the token + * @param l2Gateway_ L2 gateway this token communicates with + * @param l1Counterpart_ L1 address of ERC20 + */ + function initialize_ArbCompatible(address l2Gateway_, address l1Counterpart_) external { + // initializeV2_2 of FiatTokenV2_2 sets version to 3 + require(_initializedVersion == 3); + require(l2Gateway_ != address(0), "INVALID_GATEWAY"); + require(l2Gateway == address(0), "ALREADY_INIT"); + l2Gateway = l2Gateway_; + l1Address = l1Counterpart_; + } + + /** + * @notice Mint tokens on L2. Callable path is L1Gateway depositToken (which handles L1 escrow), which triggers L2Gateway, which calls this + * @param account recipient of tokens + * @param amount amount of tokens minted + */ + function bridgeMint(address account, uint256 amount) public virtual override onlyGateway { + mint(account, amount); + } + + /** + * @notice Burn tokens on L2. + * @dev only the token bridge can call this + * @param account owner of tokens + * @param amount amount of tokens burnt + */ + function bridgeBurn(address account, uint256 amount) public virtual override onlyGateway { + _burn(account, amount); + } + + /** + * @notice Allows a minter to burn some of its own tokens. + * @dev The caller must be a minter, must not be blacklisted, and the amount to burn + * should be less than or equal to the account's balance. + * @param _amount the amount of tokens to be burned. + */ + function _burn(address _account, uint256 _amount) + internal + whenNotPaused + onlyMinters + notBlacklisted(_account) + { + uint256 balance = _balanceOf(_account); + require(_amount > 0, "FiatToken: burn amount not greater than 0"); + require(balance >= _amount, "FiatToken: burn amount exceeds balance"); + + totalSupply_ = totalSupply_ - _amount; + _setBalance(_account, balance - _amount); + emit Burn(_account, _amount); + emit Transfer(_account, address(0), _amount); + } +} From f971a57225b3fe5056212b2e5ed3cd7a741d62d2 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 6 Jun 2024 11:27:54 +0200 Subject: [PATCH 02/20] Add Solady --- package.json | 3 ++- remappings.txt | 1 + yarn.lock | 5 +++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 92b8884871..9e8acf484f 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,8 @@ "@arbitrum/nitro-contracts": "1.1.1", "@offchainlabs/upgrade-executor": "1.1.0-beta.0", "@openzeppelin/contracts": "4.8.3", - "@openzeppelin/contracts-upgradeable": "4.8.3" + "@openzeppelin/contracts-upgradeable": "4.8.3", + "solady": "^0.0.206" }, "devDependencies": { "@arbitrum/sdk": "^3.1.3", diff --git a/remappings.txt b/remappings.txt index 1c717ff353..007c4faeda 100644 --- a/remappings.txt +++ b/remappings.txt @@ -4,3 +4,4 @@ forge-std/=lib/forge-std/src/ @openzeppelin/contracts/=node_modules/@openzeppelin/contracts/ @arbitrum=node_modules/@arbitrum @offchainlabs=node_modules/@offchainlabs +@solady=node_modules/solady diff --git a/yarn.lock b/yarn.lock index a33ede27d2..0ce02aea15 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9025,6 +9025,11 @@ snapdragon@^0.8.1: source-map-resolve "^0.5.0" use "^3.1.0" +solady@^0.0.206: + version "0.0.206" + resolved "https://registry.yarnpkg.com/solady/-/solady-0.0.206.tgz#5525770031cc4eb0d56a6d4fa0398c0c4bc2f6f8" + integrity sha512-Qpzk/M4kqMG+5GKgoxQxCB0oaH4pncxgzfd5vB8/qcN5Y12UAclhMpuKFold6Is27DsS27LKyMfYnWtZ2rUOcA== + solc@0.7.3: version "0.7.3" resolved "https://registry.yarnpkg.com/solc/-/solc-0.7.3.tgz#04646961bd867a744f63d2b4e3c0701ffdc7d78a" From 89bede4e927dcc03c10cb49617ef92c97a8030f8 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 6 Jun 2024 15:49:56 +0200 Subject: [PATCH 03/20] Remove solady --- package.json | 3 +-- yarn.lock | 5 ----- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/package.json b/package.json index 9e8acf484f..92b8884871 100644 --- a/package.json +++ b/package.json @@ -44,8 +44,7 @@ "@arbitrum/nitro-contracts": "1.1.1", "@offchainlabs/upgrade-executor": "1.1.0-beta.0", "@openzeppelin/contracts": "4.8.3", - "@openzeppelin/contracts-upgradeable": "4.8.3", - "solady": "^0.0.206" + "@openzeppelin/contracts-upgradeable": "4.8.3" }, "devDependencies": { "@arbitrum/sdk": "^3.1.3", diff --git a/yarn.lock b/yarn.lock index 0ce02aea15..a33ede27d2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9025,11 +9025,6 @@ snapdragon@^0.8.1: source-map-resolve "^0.5.0" use "^3.1.0" -solady@^0.0.206: - version "0.0.206" - resolved "https://registry.yarnpkg.com/solady/-/solady-0.0.206.tgz#5525770031cc4eb0d56a6d4fa0398c0c4bc2f6f8" - integrity sha512-Qpzk/M4kqMG+5GKgoxQxCB0oaH4pncxgzfd5vB8/qcN5Y12UAclhMpuKFold6Is27DsS27LKyMfYnWtZ2rUOcA== - solc@0.7.3: version "0.7.3" resolved "https://registry.yarnpkg.com/solc/-/solc-0.7.3.tgz#04646961bd867a744f63d2b4e3c0701ffdc7d78a" From d3b69b8e2869b92d8ea0783f0b5b836bd99f1816 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 6 Jun 2024 15:51:14 +0200 Subject: [PATCH 04/20] Add helper function to deploy usdc token from bytecode --- test-foundry/util/TestUtil.sol | 40 ++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/test-foundry/util/TestUtil.sol b/test-foundry/util/TestUtil.sol index 27b3265865..51edcb835c 100644 --- a/test-foundry/util/TestUtil.sol +++ b/test-foundry/util/TestUtil.sol @@ -4,9 +4,49 @@ pragma solidity ^0.8.4; import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; import "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; + library TestUtil { function deployProxy(address logic) public returns (address) { ProxyAdmin pa = new ProxyAdmin(); return address(new TransparentUpgradeableProxy(address(logic), address(pa), "")); } + + function deployBridgedUsdcToken() public returns (address) { + /// deploy library + bytes memory sigCheckerLibBytecode = + hex"6106cd610026600b82828239805160001a60731461001957fe5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106100355760003560e01c80636ccea6521461003a575b600080fd5b6101026004803603606081101561005057600080fd5b73ffffffffffffffffffffffffffffffffffffffff8235169160208101359181019060608101604082013564010000000081111561008d57600080fd5b82018360208201111561009f57600080fd5b803590602001918460018302840111640100000000831117156100c157600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610116945050505050565b604080519115158252519081900360200190f35b600061012184610179565b610164578373ffffffffffffffffffffffffffffffffffffffff16610146848461017f565b73ffffffffffffffffffffffffffffffffffffffff16149050610172565b61016f848484610203565b90505b9392505050565b3b151590565b600081516041146101db576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806106296023913960400191505060405180910390fd5b60208201516040830151606084015160001a6101f98682858561042d565b9695505050505050565b60008060608573ffffffffffffffffffffffffffffffffffffffff16631626ba7e60e01b86866040516024018083815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561026f578181015183820152602001610257565b50505050905090810190601f16801561029c5780820380516001836020036101000a031916815260200191505b50604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009098169790971787525181519196909550859450925090508083835b6020831061036957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161032c565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d80600081146103c9576040519150601f19603f3d011682016040523d82523d6000602084013e6103ce565b606091505b50915091508180156103e257506020815110155b80156101f9575080517f1626ba7e00000000000000000000000000000000000000000000000000000000906020808401919081101561042057600080fd5b5051149695505050505050565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08211156104a8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806106726026913960400191505060405180910390fd5b8360ff16601b141580156104c057508360ff16601c14155b15610516576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602681526020018061064c6026913960400191505060405180910390fd5b600060018686868660405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015610572573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811661061f57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f45435265636f7665723a20696e76616c6964207369676e617475726500000000604482015290519081900360640190fd5b9594505050505056fe45435265636f7665723a20696e76616c6964207369676e6174757265206c656e67746845435265636f7665723a20696e76616c6964207369676e6174757265202776272076616c756545435265636f7665723a20696e76616c6964207369676e6174757265202773272076616c7565a2646970667358221220fc883ef3b50f607958f5dc584d21cf2984d25712b89b5e11c0d53a81068ace3664736f6c634300060c0033"; + + address sigCheckerAddress; + assembly { + sigCheckerAddress := + create(0, add(sigCheckerLibBytecode, 0x20), mload(sigCheckerLibBytecode)) + } + require(sigCheckerAddress != address(0), "Failed to deploy contract"); + + + /// deploy bridged usdc token + + // insert lib address into bytecode + bytes memory b1 = + hex"60806040526001805460ff60a01b191690556000600b553480156200002357600080fd5b506200002f3362000035565b62000057565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b61632680620000676000396000f3fe608060405234801561001057600080fd5b50600436106103a45760003560e01c80638a6db9c3116101e9578063b7b728991161010f578063dd62ed3e116100ad578063ef55bec61161007c578063ef55bec614611216578063f2fde38b14611282578063f9f92be4146112b5578063fe575a87146112e8576103a4565b8063dd62ed3e1461112e578063e3ee160e14611169578063e5a6b10f146111d5578063e94a0102146111dd576103a4565b8063cf092995116100e9578063cf09299514610f74578063d505accf14611058578063d608ea64146110b6578063d916948714611126576103a4565b8063b7b7289914610e9c578063bd10243014610f64578063c2eeeebd14610f6c576103a4565b8063a0cc6a6811610187578063aa20e1e411610156578063aa20e1e414610dc0578063aa271e1a14610df3578063ad38bf2214610e26578063b2118a8d14610e59576103a4565b8063a0cc6a6814610d0b578063a297ea5e14610d13578063a457c2d714610d4e578063a9059cbb14610d87576103a4565b80638fa74a0e116101c35780638fa74a0e14610c1b57806395d89b4114610c235780639fd0506d14610c2b5780639fd5a6cf14610c33576103a4565b80638a6db9c314610ba75780638c2a993e14610bda5780638da5cb5b14610c13576103a4565b80633f4ba83a116102ce5780635a049a701161026c5780637ecebe001161023b5780637ecebe0014610a805780637f2eecc314610ab35780638456cb5914610abb57806388b7ab6314610ac3576103a4565b80635a049a70146109be5780635c975abb14610a0c57806370a0823114610a1457806374f4f54714610a47576103a4565b8063430239b4116102a8578063430239b4146108885780634e44d9561461094a57806354fd4d5014610983578063554bab3c1461098b576103a4565b80633f4ba83a1461082a57806340c10f191461083257806342966c681461086b576103a4565b80633092afd51161034657806335d99f351161031557806335d99f35146107b05780633644e515146107e157806338a63183146107e957806339509351146107f1576103a4565b80633092afd51461056b57806330adf81f1461059e578063313ce567146105a65780633357162b146105c4576103a4565b80631a895266116103825780631a8952661461048d57806323b872dd146104c25780632ab60045146105055780632fc81e0914610538576103a4565b806306fdde03146103a9578063095ea7b31461042657806318160ddd14610473575b600080fd5b6103b161131b565b6040805160208082528351818301528351919283929083019185019080838360005b838110156103eb5781810151838201526020016103d3565b50505050905090810190601f1680156104185780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61045f6004803603604081101561043c57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356113c7565b604080519115158252519081900360200190f35b61047b611468565b60408051918252519081900360200190f35b6104c0600480360360208110156104a357600080fd5b503573ffffffffffffffffffffffffffffffffffffffff1661146e565b005b61045f600480360360608110156104d857600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020810135909116906040013561152b565b6104c06004803603602081101561051b57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166117e6565b6104c06004803603602081101561054e57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611947565b61045f6004803603602081101561058157600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166119af565b61047b611aa8565b6105ae611acc565b6040805160ff9092168252519081900360200190f35b6104c060048036036101008110156105db57600080fd5b8101906020810181356401000000008111156105f657600080fd5b82018360208201111561060857600080fd5b8035906020019184600183028401116401000000008311171561062a57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929594936020810193503591505064010000000081111561067d57600080fd5b82018360208201111561068f57600080fd5b803590602001918460018302840111640100000000831117156106b157600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929594936020810193503591505064010000000081111561070457600080fd5b82018360208201111561071657600080fd5b8035906020019184600183028401116401000000008311171561073857600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050813560ff16925050602081013573ffffffffffffffffffffffffffffffffffffffff90811691604081013582169160608201358116916080013516611ad5565b6107b8611e17565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b61047b611e33565b6107b8611e42565b61045f6004803603604081101561080757600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135611e5e565b6104c0611ef6565b61045f6004803603604081101561084857600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135611fb9565b6104c06004803603602081101561088157600080fd5b503561238a565b6104c06004803603604081101561089e57600080fd5b8101906020810181356401000000008111156108b957600080fd5b8201836020820111156108cb57600080fd5b803590602001918460208302840111640100000000831117156108ed57600080fd5b91939092909160208101903564010000000081111561090b57600080fd5b82018360208201111561091d57600080fd5b8035906020019184600183028401116401000000008311171561093f57600080fd5b50909250905061262c565b61045f6004803603604081101561096057600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356127e3565b6103b1612976565b6104c0600480360360208110156109a157600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166129ad565b6104c0600480360360a08110156109d457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060208101359060ff6040820135169060608101359060800135612b14565b61045f612bb2565b61047b60048036036020811015610a2a57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612bd3565b6104c060048036036040811015610a5d57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135612be4565b61047b60048036036020811015610a9657600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612c93565b61047b612cbb565b6104c0612cdf565b6104c0600480360360e0811015610ad957600080fd5b73ffffffffffffffffffffffffffffffffffffffff823581169260208101359091169160408201359160608101359160808201359160a08101359181019060e0810160c0820135640100000000811115610b3257600080fd5b820183602082011115610b4457600080fd5b80359060200191846001830284011164010000000083111715610b6657600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612db9945050505050565b61047b60048036036020811015610bbd57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612f1d565b6104c060048036036040811015610bf057600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135612f45565b6107b8612ff5565b6107b8613011565b6103b1613036565b6107b86130af565b6104c0600480360360a0811015610c4957600080fd5b73ffffffffffffffffffffffffffffffffffffffff823581169260208101359091169160408201359160608101359181019060a081016080820135640100000000811115610c9657600080fd5b820183602082011115610ca857600080fd5b80359060200191846001830284011164010000000083111715610cca57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506130cb945050505050565b61047b613162565b6104c060048036036040811015610d2957600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020013516613186565b61045f60048036036040811015610d6457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356132f5565b61045f60048036036040811015610d9d57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813516906020013561338d565b6104c060048036036020811015610dd657600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166134f0565b61045f60048036036020811015610e0957600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16613657565b6104c060048036036020811015610e3c57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16613682565b6104c060048036036060811015610e6f57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135811691602081013590911690604001356137e9565b6104c060048036036060811015610eb257600080fd5b73ffffffffffffffffffffffffffffffffffffffff82351691602081013591810190606081016040820135640100000000811115610eef57600080fd5b820183602082011115610f0157600080fd5b80359060200191846001830284011164010000000083111715610f2357600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092955061387a945050505050565b6107b861390f565b6107b861392b565b6104c0600480360360e0811015610f8a57600080fd5b73ffffffffffffffffffffffffffffffffffffffff823581169260208101359091169160408201359160608101359160808201359160a08101359181019060e0810160c0820135640100000000811115610fe357600080fd5b820183602082011115610ff557600080fd5b8035906020019184600183028401116401000000008311171561101757600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550613950945050505050565b6104c0600480360360e081101561106e57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c00135613aa9565b6104c0600480360360208110156110cc57600080fd5b8101906020810181356401000000008111156110e757600080fd5b8201836020820111156110f957600080fd5b8035906020019184600183028401116401000000008311171561111b57600080fd5b509092509050613b4b565b61047b613c34565b61047b6004803603604081101561114457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020013516613c58565b6104c0600480360361012081101561118057600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060408101359060608101359060808101359060a08101359060ff60c0820135169060e0810135906101000135613c90565b6103b1613df8565b61045f600480360360408110156111f357600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135613e71565b6104c0600480360361012081101561122d57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060408101359060608101359060808101359060a08101359060ff60c0820135169060e0810135906101000135613ea9565b6104c06004803603602081101561129857600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16614004565b6104c0600480360360208110156112cb57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16614157565b61045f600480360360208110156112fe57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16614214565b6004805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156113bf5780601f10611394576101008083540402835291602001916113bf565b820191906000526020600020905b8154815290600101906020018083116113a257829003601f168201915b505050505081565b60015460009074010000000000000000000000000000000000000000900460ff161561145457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b61145f33848461421f565b50600192915050565b600b5490565b60025473ffffffffffffffffffffffffffffffffffffffff1633146114de576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c815260200180615fa2602c913960400191505060405180910390fd5b6114e781614366565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f117e3210bb9aa7d9baff172026820255c6f6c30ba8999d1c2fd88e2848137c4e90600090a250565b60015460009074010000000000000000000000000000000000000000900460ff16156115b857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336115c281614371565b15611618576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b8461162281614371565b15611678576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b8461168281614371565b156116d8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff87166000908152600a60209081526040808320338452909152902054851115611761576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260288152602001806160926028913960400191505060405180910390fd5b61176c87878761439f565b73ffffffffffffffffffffffffffffffffffffffff87166000908152600a602090815260408083203384529091529020546117a7908661456a565b73ffffffffffffffffffffffffffffffffffffffff88166000908152600a60209081526040808320338452909152902055600193505050509392505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461186c57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff81166118d8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180615edb602a913960400191505060405180910390fd5b600e80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517fe475e580d85111348e40d8ca33cfdd74c30fe1655c2d8537a13abc10065ffa5a90600090a250565b60125460ff1660011461195957600080fd5b6000611964306145e1565b905080156119775761197730838361439f565b6119803061462b565b5050601280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166002179055565b60085460009073ffffffffffffffffffffffffffffffffffffffff163314611a22576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615f796029913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166000818152600c6020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055600d909152808220829055517fe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb666929190a2506001919050565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60065460ff1681565b60085474010000000000000000000000000000000000000000900460ff1615611b49576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a81526020018061610d602a913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8416611bb5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f81526020018061603f602f913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8316611c21576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615eb26029913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216611c8d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e8152602001806160ba602e913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8116611cf9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260288152602001806161fa6028913960400191505060405180910390fd5b8751611d0c9060049060208b0190615c4b565b508651611d209060059060208a0190615c4b565b508551611d34906007906020890190615c4b565b50600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff8716179055600880547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff8781169190911790925560018054821686841617905560028054909116918416919091179055611dce81614636565b5050600880547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055505050505050565b60085473ffffffffffffffffffffffffffffffffffffffff1681565b6000611e3d61467d565b905090565b600e5473ffffffffffffffffffffffffffffffffffffffff1690565b60015460009074010000000000000000000000000000000000000000900460ff1615611eeb57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b61145f338484614772565b60015473ffffffffffffffffffffffffffffffffffffffff163314611f66576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806161ae6022913960400191505060405180910390fd5b600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690556040517f7805862f689e2f13df9f062ff482ad3ad112aca9e0847911ed832e158c525b3390600090a1565b60015460009074010000000000000000000000000000000000000000900460ff161561204657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff166120ae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602181526020018061601e6021913960400191505060405180910390fd5b336120b881614371565b1561210e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b8361211881614371565b1561216e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff85166121da576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180615e476023913960400191505060405180910390fd5b60008411612233576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615f2a6029913960400191505060405180910390fd5b336000908152600d60205260409020548085111561229c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e815260200180616180602e913960400191505060405180910390fd5b600b546122a990866147bc565b600b556122c8866122c3876122bd836145e1565b906147bc565b614837565b6122d2818661456a565b336000818152600d6020908152604091829020939093558051888152905173ffffffffffffffffffffffffffffffffffffffff8a16937fab8530f87dc9b59234c4623bf917212bb2536d647574c8e7e5da92c2ede0c9f8928290030190a360408051868152905173ffffffffffffffffffffffffffffffffffffffff8816916000917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a350600195945050505050565b60015474010000000000000000000000000000000000000000900460ff161561241457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff1661247c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602181526020018061601e6021913960400191505060405180910390fd5b3361248681614371565b156124dc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b60006124e7336145e1565b905060008311612542576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615e1e6029913960400191505060405180910390fd5b8281101561259b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180615ff86026913960400191505060405180910390fd5b600b546125a8908461456a565b600b556125b9336122c3838661456a565b60408051848152905133917fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5919081900360200190a260408051848152905160009133917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a3505050565b60125460ff1660021461263e57600080fd5b61264a60058383615cc9565b5060005b8381101561278c576003600086868481811061266657fe5b6020908102929092013573ffffffffffffffffffffffffffffffffffffffff168352508101919091526040016000205460ff166126ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603d815260200180615d6b603d913960400191505060405180910390fd5b61271f8585838181106126fd57fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff1661462b565b6003600086868481811061272f57fe5b6020908102929092013573ffffffffffffffffffffffffffffffffffffffff1683525081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905560010161264e565b506127963061462b565b505030600090815260036020819052604090912080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009081169091556012805490911690911790555050565b60015460009074010000000000000000000000000000000000000000900460ff161561287057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b60085473ffffffffffffffffffffffffffffffffffffffff1633146128e0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615f796029913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff83166000818152600c6020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055600d825291829020859055815185815291517f46980fca912ef9bcdbd36877427b6b90e860769f604e89c0e67720cece530d209281900390910190a250600192915050565b60408051808201909152600181527f3200000000000000000000000000000000000000000000000000000000000000602082015290565b60005473ffffffffffffffffffffffffffffffffffffffff163314612a3357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116612a9f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526028815260200180615dcb6028913960400191505060405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691909117918290556040519116907fb80482a293ca2e013eda8683c9bd7fc8347cfdaeea5ede58cba46df502c2a60490600090a250565b60015474010000000000000000000000000000000000000000900460ff1615612b9e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b612bab8585858585614938565b5050505050565b60015474010000000000000000000000000000000000000000900460ff1681565b6000612bde826145e1565b92915050565b612bec613011565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612c8557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4f4e4c595f474154455741590000000000000000000000000000000000000000604482015290519081900360640190fd5b612c8f8282614978565b5050565b73ffffffffffffffffffffffffffffffffffffffff1660009081526011602052604090205490565b7fd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de881565b60015473ffffffffffffffffffffffffffffffffffffffff163314612d4f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806161ae6022913960400191505060405180910390fd5b600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790556040517f6985a02210a168e66602d3235cb6db0e70f92b3ba4d376a33c0f3d9434bff62590600090a1565b60015474010000000000000000000000000000000000000000900460ff1615612e4357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b86612e4d81614371565b15612ea3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b86612ead81614371565b15612f03576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b612f1289898989898989614c3e565b505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff166000908152600d602052604090205490565b612f4d613011565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612fe657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4f4e4c595f474154455741590000000000000000000000000000000000000000604482015290519081900360640190fd5b612ff08282611fb9565b505050565b60005473ffffffffffffffffffffffffffffffffffffffff1690565b7fdbf6298cab77bb44ebfd5abb25ed2538c2a55f7404c47e83e6531361fba28c245490565b6005805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156113bf5780601f10611394576101008083540402835291602001916113bf565b60015473ffffffffffffffffffffffffffffffffffffffff1681565b60015474010000000000000000000000000000000000000000900460ff161561315557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b612bab8585858585614d5f565b7f7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a226781565b60125460ff1660031461319857600080fd5b73ffffffffffffffffffffffffffffffffffffffff821661321a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f494e56414c49445f474154455741590000000000000000000000000000000000604482015290519081900360640190fd5b6000613224613011565b73ffffffffffffffffffffffffffffffffffffffff16146132a657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f414c52454144595f494e49540000000000000000000000000000000000000000604482015290519081900360640190fd5b817fdbf6298cab77bb44ebfd5abb25ed2538c2a55f7404c47e83e6531361fba28c2455807f54352c0d7cc5793352a36344bfdcdcf68ba6258544ce1aed71f60a74d882c19155612c8f82615023565b60015460009074010000000000000000000000000000000000000000900460ff161561338257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b61145f3384846150d8565b60015460009074010000000000000000000000000000000000000000900460ff161561341a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b3361342481614371565b1561347a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b8361348481614371565b156134da576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b6134e533868661439f565b506001949350505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461357657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff81166135e2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f81526020018061603f602f913960400191505060405180910390fd5b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691909117918290556040519116907fdb66dfa9c6b8f5226fe9aac7e51897ae8ee94ac31dc70bb6c9900b2574b707e690600090a250565b73ffffffffffffffffffffffffffffffffffffffff166000908152600c602052604090205460ff1690565b60005473ffffffffffffffffffffffffffffffffffffffff16331461370857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116613774576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260328152602001806162506032913960400191505060405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691909117918290556040519116907fc67398012c111ce95ecb7429b933096c977380ee6c421175a71a4a4c6c88c06e90600090a250565b600e5473ffffffffffffffffffffffffffffffffffffffff163314613859576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602481526020018061606e6024913960400191505060405180910390fd5b612ff073ffffffffffffffffffffffffffffffffffffffff84168383615134565b60015474010000000000000000000000000000000000000000900460ff161561390457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b612ff08383836151c1565b60025473ffffffffffffffffffffffffffffffffffffffff1681565b7f54352c0d7cc5793352a36344bfdcdcf68ba6258544ce1aed71f60a74d882c1915490565b60015474010000000000000000000000000000000000000000900460ff16156139da57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b866139e481614371565b15613a3a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b86613a4481614371565b15613a9a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b612f12898989898989896152cb565b60015474010000000000000000000000000000000000000000900460ff1615613b3357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b613b4287878787878787615369565b50505050505050565b60085474010000000000000000000000000000000000000000900460ff168015613b78575060125460ff16155b613b8157600080fd5b613b8d60048383615cc9565b50613c0282828080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600181527f3200000000000000000000000000000000000000000000000000000000000000602082015291506153ab9050565b600f555050601280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b7f158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a159742981565b73ffffffffffffffffffffffffffffffffffffffff9182166000908152600a6020908152604080832093909416825291909152205490565b60015474010000000000000000000000000000000000000000900460ff1615613d1a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b88613d2481614371565b15613d7a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b88613d8481614371565b15613dda576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b613deb8b8b8b8b8b8b8b8b8b6153c1565b5050505050505050505050565b6007805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156113bf5780601f10611394576101008083540402835291602001916113bf565b73ffffffffffffffffffffffffffffffffffffffff919091166000908152601060209081526040808320938352929052205460ff1690565b60015474010000000000000000000000000000000000000000900460ff1615613f3357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b88613f3d81614371565b15613f93576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b88613f9d81614371565b15613ff3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b613deb8b8b8b8b8b8b8b8b8b615405565b60005473ffffffffffffffffffffffffffffffffffffffff16331461408a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff81166140f6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180615e6a6026913960400191505060405180910390fd5b6000546040805173ffffffffffffffffffffffffffffffffffffffff9283168152918316602083015280517f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09281900390910190a161415481614636565b50565b60025473ffffffffffffffffffffffffffffffffffffffff1633146141c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c815260200180615fa2602c913960400191505060405180910390fd5b6141d08161462b565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fffa4e6181777692565cf28528fc88fd1516ea86b56da075235fa575af6a4b85590600090a250565b6000612bde82614371565b73ffffffffffffffffffffffffffffffffffffffff831661428b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602481526020018061615c6024913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166142f7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180615e906022913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8084166000818152600a6020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b614154816000615449565b73ffffffffffffffffffffffffffffffffffffffff1660009081526009602052604090205460ff1c60011490565b73ffffffffffffffffffffffffffffffffffffffff831661440b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806161376025913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216614477576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180615da86023913960400191505060405180910390fd5b614480836145e1565b8111156144d8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180615f536026913960400191505060405180910390fd5b6144ef836122c3836144e9876145e1565b9061456a565b614500826122c3836122bd866145e1565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6000828211156145db57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b73ffffffffffffffffffffffffffffffffffffffff166000908152600960205260409020547f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690565b614154816001615449565b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6004805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152600093611e3d939192909183018282801561472a5780601f106146ff5761010080835404028352916020019161472a565b820191906000526020600020905b81548152906001019060200180831161470d57829003601f168201915b50505050506040518060400160405280600181526020017f320000000000000000000000000000000000000000000000000000000000000081525061476d6154d2565b6154d6565b73ffffffffffffffffffffffffffffffffffffffff8084166000908152600a6020908152604080832093861683529290522054612ff090849084906147b790856147bc565b61421f565b60008282018381101561483057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8111156148b0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180615fce602a913960400191505060405180910390fd5b6148b982614371565b1561490f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615f056025913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff909116600090815260096020526040902055565b612bab8585848487604051602001808481526020018381526020018260ff1660f81b815260010193505050506040516020818303038152906040526151c1565b60015474010000000000000000000000000000000000000000900460ff1615614a0257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff16614a6a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602181526020018061601e6021913960400191505060405180910390fd5b81614a7481614371565b15614aca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b6000614ad5846145e1565b905060008311614b30576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615e1e6029913960400191505060405180910390fd5b82811015614b89576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180615ff86026913960400191505060405180910390fd5b600b80548490039055614b9e84848303614837565b60408051848152905173ffffffffffffffffffffffffffffffffffffffff8616917fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5919081900360200190a260408051848152905160009173ffffffffffffffffffffffffffffffffffffffff8716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a350505050565b73ffffffffffffffffffffffffffffffffffffffff86163314614cac576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806160e86025913960400191505060405180910390fd5b614cb88783868661554a565b604080517fd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de860208083019190915273ffffffffffffffffffffffffffffffffffffffff808b1683850152891660608301526080820188905260a0820187905260c0820186905260e0808301869052835180840390910181526101009092019092528051910120614d4a9088908361560a565b614d548783615788565b613b4287878761439f565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821480614d8d5750428210155b614df857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f46696174546f6b656e56323a207065726d697420697320657870697265640000604482015290519081900360640190fd5b6000614ea0614e0561467d565b73ffffffffffffffffffffffffffffffffffffffff80891660008181526011602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98184015280840194909452938b166060840152608083018a905260a083019390935260c08083018990528151808403909101815260e09092019052805191012061580d565b905073"; + + bytes memory b2 = + hex"636ccea6528783856040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff16815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015614f2d578181015183820152602001614f15565b50505050905090810190601f168015614f5a5780820380516001836020036101000a031916815260200191505b5094505050505060206040518083038186803b158015614f7957600080fd5b505af4158015614f8d573d6000803e3d6000fd5b505050506040513d6020811015614fa357600080fd5b505161501057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f454950323631323a20696e76616c6964207369676e6174757265000000000000604482015290519081900360640190fd5b61501b86868661421f565b505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000818152600c6020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055600d8252918290207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90819055825181815292519093927f46980fca912ef9bcdbd36877427b6b90e860769f604e89c0e67720cece530d2092908290030190a25050565b612ff083836147b7846040518060600160405280602581526020016162cc6025913973ffffffffffffffffffffffffffffffffffffffff808a166000908152600a60209081526040808320938c16835292905220549190615847565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052612ff09084906158f8565b6151cb83836159d0565b615245837f158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a159742960001b8585604051602001808481526020018373ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050604051602081830303815290604052805190602001208361560a565b73ffffffffffffffffffffffffffffffffffffffff8316600081815260106020908152604080832086845290915280822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055518492917f1cdd46ff242716cdaa72d159d339a485b3438398348d68f09d7c8c0a59353d8191a3505050565b6152d78783868661554a565b604080517f7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a226760208083019190915273ffffffffffffffffffffffffffffffffffffffff808b1683850152891660608301526080820188905260a0820187905260c0820186905260e0808301869052835180840390910181526101009092019092528051910120614d4a9088908361560a565b613b4287878787868689604051602001808481526020018381526020018260ff1660f81b81526001019350505050604051602081830303815290604052614d5f565b6000466153b98484836154d6565b949350505050565b612f1289898989898988888b604051602001808481526020018381526020018260ff1660f81b815260010193505050506040516020818303038152906040526152cb565b612f1289898989898988888b604051602001808481526020018381526020018260ff1660f81b81526001019350505050604051602081830303815290604052614c3e565b8061545c57615457826145e1565b6154a5565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600960205260409020547f8000000000000000000000000000000000000000000000000000000000000000175b73ffffffffffffffffffffffffffffffffffffffff90921660009081526009602052604090209190915550565b4690565b8251602093840120825192840192909220604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8187015280820194909452606084019190915260808301919091523060a0808401919091528151808403909101815260c09092019052805191012090565b8142116155a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b815260200180615df3602b913960400191505060405180910390fd5b8042106155fa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162a76025913960400191505060405180910390fd5b61560484846159d0565b50505050565b73"; + + bytes memory b3 = + hex"636ccea6528461563661563061467d565b8661580d565b846040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff16815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b838110156156a557818101518382015260200161568d565b50505050905090810190601f1680156156d25780820380516001836020036101000a031916815260200191505b5094505050505060206040518083038186803b1580156156f157600080fd5b505af4158015615705573d6000803e3d6000fd5b505050506040513d602081101561571b57600080fd5b5051612ff057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f46696174546f6b656e56323a20696e76616c6964207369676e61747572650000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8216600081815260106020908152604080832085845290915280822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055518392917f98de503528ee59b575ef0c0a2576a82497bfc029a5685b209e9ec333479b10a591a35050565b6040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b600081848411156158f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b838110156158b557818101518382015260200161589d565b50505050905090810190601f1680156158e25780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b606061595a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16615a5a9092919063ffffffff16565b805190915015612ff05780806020019051602081101561597957600080fd5b5051612ff0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a8152602001806161d0602a913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216600090815260106020908152604080832084845290915290205460ff1615612c8f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e815260200180616222602e913960400191505060405180910390fd5b60606153b9848460008585615a6e85615bc5565b615ad957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b60208310615b4357805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101615b06565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114615ba5576040519150601f19603f3d011682016040523d82523d6000602084013e615baa565b606091505b5091509150615bba828286615bcb565b979650505050505050565b3b151590565b60608315615bda575081614830565b825115615bea5782518084602001fd5b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526020600482018181528451602484015284518593919283926044019190850190808383600083156158b557818101518382015260200161589d565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10615c8c57805160ff1916838001178555615cb9565b82800160010185558215615cb9579182015b82811115615cb9578251825591602001919060010190615c9e565b50615cc5929150615d55565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10615d28578280017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00823516178555615cb9565b82800160010185558215615cb9579182015b82811115615cb9578235825591602001919060010190615d3a565b5b80821115615cc55760008155600101615d5656fe46696174546f6b656e56325f323a20426c61636b6c697374696e672070726576696f75736c7920756e626c61636b6c6973746564206163636f756e742145524332303a207472616e7366657220746f20746865207a65726f20616464726573735061757361626c653a206e65772070617573657220697320746865207a65726f206164647265737346696174546f6b656e56323a20617574686f72697a6174696f6e206973206e6f74207965742076616c696446696174546f6b656e3a206275726e20616d6f756e74206e6f742067726561746572207468616e203046696174546f6b656e3a206d696e7420746f20746865207a65726f20616464726573734f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737346696174546f6b656e3a206e65772070617573657220697320746865207a65726f2061646472657373526573637561626c653a206e6577207265736375657220697320746865207a65726f206164647265737346696174546f6b656e56325f323a204163636f756e7420697320626c61636b6c697374656446696174546f6b656e3a206d696e7420616d6f756e74206e6f742067726561746572207468616e203045524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636546696174546f6b656e3a2063616c6c6572206973206e6f7420746865206d61737465724d696e746572426c61636b6c69737461626c653a2063616c6c6572206973206e6f742074686520626c61636b6c697374657246696174546f6b656e56325f323a2042616c616e636520657863656564732028325e323535202d20312946696174546f6b656e3a206275726e20616d6f756e7420657863656564732062616c616e636546696174546f6b656e3a2063616c6c6572206973206e6f742061206d696e74657246696174546f6b656e3a206e6577206d61737465724d696e74657220697320746865207a65726f2061646472657373526573637561626c653a2063616c6c6572206973206e6f7420746865207265736375657245524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636546696174546f6b656e3a206e657720626c61636b6c697374657220697320746865207a65726f206164647265737346696174546f6b656e56323a2063616c6c6572206d7573742062652074686520706179656546696174546f6b656e3a20636f6e747261637420697320616c726561647920696e697469616c697a656445524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737346696174546f6b656e3a206d696e7420616d6f756e742065786365656473206d696e746572416c6c6f77616e63655061757361626c653a2063616c6c6572206973206e6f7420746865207061757365725361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656446696174546f6b656e3a206e6577206f776e657220697320746865207a65726f206164647265737346696174546f6b656e56323a20617574686f72697a6174696f6e2069732075736564206f722063616e63656c6564426c61636b6c69737461626c653a206e657720626c61636b6c697374657220697320746865207a65726f2061646472657373426c61636b6c69737461626c653a206163636f756e7420697320626c61636b6c697374656446696174546f6b656e56323a20617574686f72697a6174696f6e206973206578706972656445524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa26469706673582212205b9c28831ca019c704546ef047ba19de251c8493a622e0f4ae1dff3520aaae2464736f6c634300060c0033"; + + bytes memory libAddress = abi.encodePacked(sigCheckerAddress); + + bytes memory fullBytecode = bytes.concat( + bytes.concat(bytes.concat(bytes.concat(b1, libAddress), b2), libAddress), b3 + ); + + address bridgedUsdcToken; + assembly { + bridgedUsdcToken := create(0, add(fullBytecode, 0x20), mload(fullBytecode)) + } + require(bridgedUsdcToken != address(0), "Failed to deploy contract"); + return bridgedUsdcToken; + } } From 4b86a99864df61138dd2bc46ef8c2fba3e681995 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 6 Jun 2024 16:54:47 +0200 Subject: [PATCH 05/20] Deploy and init FiatTokenArbitrumOrbitV2_2 in FOundry tests --- test-foundry/L2USDCCustomGateway.t.sol | 42 ++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/test-foundry/L2USDCCustomGateway.t.sol b/test-foundry/L2USDCCustomGateway.t.sol index 8267669dfa..1103615e70 100644 --- a/test-foundry/L2USDCCustomGateway.t.sol +++ b/test-foundry/L2USDCCustomGateway.t.sol @@ -9,6 +9,7 @@ import {L1USDCCustomGateway} from "contracts/tokenbridge/ethereum/gateway/L1USDC import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import {AddressAliasHelper} from "contracts/tokenbridge/libraries/AddressAliasHelper.sol"; import {L2GatewayToken} from "contracts/tokenbridge/libraries/L2GatewayToken.sol"; +import {TestUtil} from "./util/TestUtil.sol"; contract L2USDCCustomGatewayTest is L2ArbitrumGatewayTest { L2USDCCustomGateway public l2USDCGateway; @@ -21,8 +22,25 @@ contract L2USDCCustomGatewayTest is L2ArbitrumGatewayTest { l2USDCGateway = new L2USDCCustomGateway(); l2Gateway = L2ArbitrumGateway(address(l2USDCGateway)); - l2USDC = address(new L2USDC(address(l2USDCGateway), l1USDC)); - l2USDCGateway.initialize(l1Counterpart, router, l1USDC, l2USDC, owner); + // l2USDC = address(new L2USDC(address(l2USDCGateway), l1USDC)); + // l2USDCGateway.initialize(l1Counterpart, router, l1USDC, l2USDC, owner); + + address bridgedUsdcLogic = TestUtil.deployBridgedUsdcToken(); + l2USDC = TestUtil.deployProxy(bridgedUsdcLogic); + FiatTokenArbitrumOrbitV2_2(l2USDC).initialize( + "USDC token", + "USDC.e", + "USD", + uint8(6), + makeAddr("newMasterMinter"), + makeAddr("newPauser"), + makeAddr("newBlacklister"), + owner + ); + FiatTokenArbitrumOrbitV2_2(l2USDC).initializeV2("USDC"); + FiatTokenArbitrumOrbitV2_2(l2USDC).initializeV2_1(makeAddr("lostAndFound")); + FiatTokenArbitrumOrbitV2_2(l2USDC).initializeV2_2(new address[](0), "USDC.e"); + FiatTokenArbitrumOrbitV2_2(l2USDC).initializeArbitrumOrbit(address(l2USDCGateway), l1USDC); } /* solhint-disable func-name-mixedcase */ @@ -262,8 +280,20 @@ contract L2USDCCustomGatewayTest is L2ArbitrumGatewayTest { event WithdrawalsPaused(); } -contract L2USDC is L2GatewayToken { - constructor(address l2USDCGateway, address l1USDC) { - L2GatewayToken._initialize("L2 USDC", "USDC", 18, l2USDCGateway, l1USDC); - } +interface FiatTokenArbitrumOrbitV2_2 { + function initialize( + string memory tokenName, + string memory tokenSymbol, + string memory tokenCurrency, + uint8 tokenDecimals, + address newMasterMinter, + address newPauser, + address newBlacklister, + address newOwner + ) external; + function initializeV2(string calldata newName) external; + function initializeV2_1(address lostAndFound) external; + function initializeV2_2(address[] calldata accountsToBlacklist, string calldata newSymbol) + external; + function initializeArbitrumOrbit(address _l2Gateway, address _l1Token) external; } From bc9865b60eb3a3a8ff4d49eb563a2848f2633bac Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 6 Jun 2024 17:07:32 +0200 Subject: [PATCH 06/20] Add back initialization --- test-foundry/L2USDCCustomGateway.t.sol | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test-foundry/L2USDCCustomGateway.t.sol b/test-foundry/L2USDCCustomGateway.t.sol index 1103615e70..1f25c2963b 100644 --- a/test-foundry/L2USDCCustomGateway.t.sol +++ b/test-foundry/L2USDCCustomGateway.t.sol @@ -22,9 +22,6 @@ contract L2USDCCustomGatewayTest is L2ArbitrumGatewayTest { l2USDCGateway = new L2USDCCustomGateway(); l2Gateway = L2ArbitrumGateway(address(l2USDCGateway)); - // l2USDC = address(new L2USDC(address(l2USDCGateway), l1USDC)); - // l2USDCGateway.initialize(l1Counterpart, router, l1USDC, l2USDC, owner); - address bridgedUsdcLogic = TestUtil.deployBridgedUsdcToken(); l2USDC = TestUtil.deployProxy(bridgedUsdcLogic); FiatTokenArbitrumOrbitV2_2(l2USDC).initialize( @@ -41,6 +38,8 @@ contract L2USDCCustomGatewayTest is L2ArbitrumGatewayTest { FiatTokenArbitrumOrbitV2_2(l2USDC).initializeV2_1(makeAddr("lostAndFound")); FiatTokenArbitrumOrbitV2_2(l2USDC).initializeV2_2(new address[](0), "USDC.e"); FiatTokenArbitrumOrbitV2_2(l2USDC).initializeArbitrumOrbit(address(l2USDCGateway), l1USDC); + + l2USDCGateway.initialize(l1Counterpart, router, l1USDC, l2USDC, owner); } /* solhint-disable func-name-mixedcase */ From 59457fc47136edf6e8fa5d6704965331792c0fd7 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 6 Jun 2024 18:27:09 +0200 Subject: [PATCH 07/20] Use FiatTokenArbitrumOrbitV2_2 for usdc token --- test-e2e/orbitTokenBridge.ts | 35 ++++++++++++++++++++++++++++++---- test-foundry/util/TestUtil.sol | 2 -- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/test-e2e/orbitTokenBridge.ts b/test-e2e/orbitTokenBridge.ts index 4f5cd0c725..089bd547e9 100644 --- a/test-e2e/orbitTokenBridge.ts +++ b/test-e2e/orbitTokenBridge.ts @@ -706,10 +706,7 @@ describe('orbitTokenBridge', () => { console.log('L1 USDC address: ', l1Usdc.address) /// create l2 usdc behind proxy - const l2UsdcFactory = await new BridgedUsdcCustomToken__factory( - deployerL2Wallet - ).deploy() - const l2UsdcLogic = await l2UsdcFactory.deployed() + const l2UsdcLogic = await _deployBridgedUsdcToken(deployerL2Wallet) const tupL2UsdcFactory = await new TransparentUpgradeableProxy__factory( deployerL2Wallet ).deploy(l2UsdcLogic.address, proxyAdminL2.address, '0x') @@ -1181,3 +1178,33 @@ const getFeeToken = async (inbox: string, parentProvider: any) => { function sleep(ms: number) { return new Promise(resolve => setTimeout(resolve, ms)) } + +async function _deployBridgedUsdcToken(deployer: Wallet) { + /// deploy library + const sigCheckerLibBytecode = + '6106cd610026600b82828239805160001a60731461001957fe5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106100355760003560e01c80636ccea6521461003a575b600080fd5b6101026004803603606081101561005057600080fd5b73ffffffffffffffffffffffffffffffffffffffff8235169160208101359181019060608101604082013564010000000081111561008d57600080fd5b82018360208201111561009f57600080fd5b803590602001918460018302840111640100000000831117156100c157600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610116945050505050565b604080519115158252519081900360200190f35b600061012184610179565b610164578373ffffffffffffffffffffffffffffffffffffffff16610146848461017f565b73ffffffffffffffffffffffffffffffffffffffff16149050610172565b61016f848484610203565b90505b9392505050565b3b151590565b600081516041146101db576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806106296023913960400191505060405180910390fd5b60208201516040830151606084015160001a6101f98682858561042d565b9695505050505050565b60008060608573ffffffffffffffffffffffffffffffffffffffff16631626ba7e60e01b86866040516024018083815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561026f578181015183820152602001610257565b50505050905090810190601f16801561029c5780820380516001836020036101000a031916815260200191505b50604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009098169790971787525181519196909550859450925090508083835b6020831061036957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161032c565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d80600081146103c9576040519150601f19603f3d011682016040523d82523d6000602084013e6103ce565b606091505b50915091508180156103e257506020815110155b80156101f9575080517f1626ba7e00000000000000000000000000000000000000000000000000000000906020808401919081101561042057600080fd5b5051149695505050505050565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08211156104a8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806106726026913960400191505060405180910390fd5b8360ff16601b141580156104c057508360ff16601c14155b15610516576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602681526020018061064c6026913960400191505060405180910390fd5b600060018686868660405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015610572573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811661061f57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f45435265636f7665723a20696e76616c6964207369676e617475726500000000604482015290519081900360640190fd5b9594505050505056fe45435265636f7665723a20696e76616c6964207369676e6174757265206c656e67746845435265636f7665723a20696e76616c6964207369676e6174757265202776272076616c756545435265636f7665723a20696e76616c6964207369676e6174757265202773272076616c7565a2646970667358221220fc883ef3b50f607958f5dc584d21cf2984d25712b89b5e11c0d53a81068ace3664736f6c634300060c0033' + const sigCheckerFactory = new ethers.ContractFactory( + [], + sigCheckerLibBytecode, + deployer + ) + const sigCheckerLib = await sigCheckerFactory.deploy() + + // prepare bridged usdc bytecode + const bytecodeWithPlaceholder = + '60806040526001805460ff60a01b191690556000600b553480156200002357600080fd5b506200002f3362000035565b62000057565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b61632680620000676000396000f3fe608060405234801561001057600080fd5b50600436106103a45760003560e01c80638a6db9c3116101e9578063b7b728991161010f578063dd62ed3e116100ad578063ef55bec61161007c578063ef55bec614611216578063f2fde38b14611282578063f9f92be4146112b5578063fe575a87146112e8576103a4565b8063dd62ed3e1461112e578063e3ee160e14611169578063e5a6b10f146111d5578063e94a0102146111dd576103a4565b8063cf092995116100e9578063cf09299514610f74578063d505accf14611058578063d608ea64146110b6578063d916948714611126576103a4565b8063b7b7289914610e9c578063bd10243014610f64578063c2eeeebd14610f6c576103a4565b8063a0cc6a6811610187578063aa20e1e411610156578063aa20e1e414610dc0578063aa271e1a14610df3578063ad38bf2214610e26578063b2118a8d14610e59576103a4565b8063a0cc6a6814610d0b578063a297ea5e14610d13578063a457c2d714610d4e578063a9059cbb14610d87576103a4565b80638fa74a0e116101c35780638fa74a0e14610c1b57806395d89b4114610c235780639fd0506d14610c2b5780639fd5a6cf14610c33576103a4565b80638a6db9c314610ba75780638c2a993e14610bda5780638da5cb5b14610c13576103a4565b80633f4ba83a116102ce5780635a049a701161026c5780637ecebe001161023b5780637ecebe0014610a805780637f2eecc314610ab35780638456cb5914610abb57806388b7ab6314610ac3576103a4565b80635a049a70146109be5780635c975abb14610a0c57806370a0823114610a1457806374f4f54714610a47576103a4565b8063430239b4116102a8578063430239b4146108885780634e44d9561461094a57806354fd4d5014610983578063554bab3c1461098b576103a4565b80633f4ba83a1461082a57806340c10f191461083257806342966c681461086b576103a4565b80633092afd51161034657806335d99f351161031557806335d99f35146107b05780633644e515146107e157806338a63183146107e957806339509351146107f1576103a4565b80633092afd51461056b57806330adf81f1461059e578063313ce567146105a65780633357162b146105c4576103a4565b80631a895266116103825780631a8952661461048d57806323b872dd146104c25780632ab60045146105055780632fc81e0914610538576103a4565b806306fdde03146103a9578063095ea7b31461042657806318160ddd14610473575b600080fd5b6103b161131b565b6040805160208082528351818301528351919283929083019185019080838360005b838110156103eb5781810151838201526020016103d3565b50505050905090810190601f1680156104185780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61045f6004803603604081101561043c57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356113c7565b604080519115158252519081900360200190f35b61047b611468565b60408051918252519081900360200190f35b6104c0600480360360208110156104a357600080fd5b503573ffffffffffffffffffffffffffffffffffffffff1661146e565b005b61045f600480360360608110156104d857600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020810135909116906040013561152b565b6104c06004803603602081101561051b57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166117e6565b6104c06004803603602081101561054e57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611947565b61045f6004803603602081101561058157600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166119af565b61047b611aa8565b6105ae611acc565b6040805160ff9092168252519081900360200190f35b6104c060048036036101008110156105db57600080fd5b8101906020810181356401000000008111156105f657600080fd5b82018360208201111561060857600080fd5b8035906020019184600183028401116401000000008311171561062a57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929594936020810193503591505064010000000081111561067d57600080fd5b82018360208201111561068f57600080fd5b803590602001918460018302840111640100000000831117156106b157600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929594936020810193503591505064010000000081111561070457600080fd5b82018360208201111561071657600080fd5b8035906020019184600183028401116401000000008311171561073857600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050813560ff16925050602081013573ffffffffffffffffffffffffffffffffffffffff90811691604081013582169160608201358116916080013516611ad5565b6107b8611e17565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b61047b611e33565b6107b8611e42565b61045f6004803603604081101561080757600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135611e5e565b6104c0611ef6565b61045f6004803603604081101561084857600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135611fb9565b6104c06004803603602081101561088157600080fd5b503561238a565b6104c06004803603604081101561089e57600080fd5b8101906020810181356401000000008111156108b957600080fd5b8201836020820111156108cb57600080fd5b803590602001918460208302840111640100000000831117156108ed57600080fd5b91939092909160208101903564010000000081111561090b57600080fd5b82018360208201111561091d57600080fd5b8035906020019184600183028401116401000000008311171561093f57600080fd5b50909250905061262c565b61045f6004803603604081101561096057600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356127e3565b6103b1612976565b6104c0600480360360208110156109a157600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166129ad565b6104c0600480360360a08110156109d457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060208101359060ff6040820135169060608101359060800135612b14565b61045f612bb2565b61047b60048036036020811015610a2a57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612bd3565b6104c060048036036040811015610a5d57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135612be4565b61047b60048036036020811015610a9657600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612c93565b61047b612cbb565b6104c0612cdf565b6104c0600480360360e0811015610ad957600080fd5b73ffffffffffffffffffffffffffffffffffffffff823581169260208101359091169160408201359160608101359160808201359160a08101359181019060e0810160c0820135640100000000811115610b3257600080fd5b820183602082011115610b4457600080fd5b80359060200191846001830284011164010000000083111715610b6657600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612db9945050505050565b61047b60048036036020811015610bbd57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612f1d565b6104c060048036036040811015610bf057600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135612f45565b6107b8612ff5565b6107b8613011565b6103b1613036565b6107b86130af565b6104c0600480360360a0811015610c4957600080fd5b73ffffffffffffffffffffffffffffffffffffffff823581169260208101359091169160408201359160608101359181019060a081016080820135640100000000811115610c9657600080fd5b820183602082011115610ca857600080fd5b80359060200191846001830284011164010000000083111715610cca57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506130cb945050505050565b61047b613162565b6104c060048036036040811015610d2957600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020013516613186565b61045f60048036036040811015610d6457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356132f5565b61045f60048036036040811015610d9d57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813516906020013561338d565b6104c060048036036020811015610dd657600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166134f0565b61045f60048036036020811015610e0957600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16613657565b6104c060048036036020811015610e3c57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16613682565b6104c060048036036060811015610e6f57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135811691602081013590911690604001356137e9565b6104c060048036036060811015610eb257600080fd5b73ffffffffffffffffffffffffffffffffffffffff82351691602081013591810190606081016040820135640100000000811115610eef57600080fd5b820183602082011115610f0157600080fd5b80359060200191846001830284011164010000000083111715610f2357600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092955061387a945050505050565b6107b861390f565b6107b861392b565b6104c0600480360360e0811015610f8a57600080fd5b73ffffffffffffffffffffffffffffffffffffffff823581169260208101359091169160408201359160608101359160808201359160a08101359181019060e0810160c0820135640100000000811115610fe357600080fd5b820183602082011115610ff557600080fd5b8035906020019184600183028401116401000000008311171561101757600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550613950945050505050565b6104c0600480360360e081101561106e57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c00135613aa9565b6104c0600480360360208110156110cc57600080fd5b8101906020810181356401000000008111156110e757600080fd5b8201836020820111156110f957600080fd5b8035906020019184600183028401116401000000008311171561111b57600080fd5b509092509050613b4b565b61047b613c34565b61047b6004803603604081101561114457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020013516613c58565b6104c0600480360361012081101561118057600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060408101359060608101359060808101359060a08101359060ff60c0820135169060e0810135906101000135613c90565b6103b1613df8565b61045f600480360360408110156111f357600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135613e71565b6104c0600480360361012081101561122d57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060408101359060608101359060808101359060a08101359060ff60c0820135169060e0810135906101000135613ea9565b6104c06004803603602081101561129857600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16614004565b6104c0600480360360208110156112cb57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16614157565b61045f600480360360208110156112fe57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16614214565b6004805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156113bf5780601f10611394576101008083540402835291602001916113bf565b820191906000526020600020905b8154815290600101906020018083116113a257829003601f168201915b505050505081565b60015460009074010000000000000000000000000000000000000000900460ff161561145457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b61145f33848461421f565b50600192915050565b600b5490565b60025473ffffffffffffffffffffffffffffffffffffffff1633146114de576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c815260200180615fa2602c913960400191505060405180910390fd5b6114e781614366565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f117e3210bb9aa7d9baff172026820255c6f6c30ba8999d1c2fd88e2848137c4e90600090a250565b60015460009074010000000000000000000000000000000000000000900460ff16156115b857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336115c281614371565b15611618576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b8461162281614371565b15611678576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b8461168281614371565b156116d8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff87166000908152600a60209081526040808320338452909152902054851115611761576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260288152602001806160926028913960400191505060405180910390fd5b61176c87878761439f565b73ffffffffffffffffffffffffffffffffffffffff87166000908152600a602090815260408083203384529091529020546117a7908661456a565b73ffffffffffffffffffffffffffffffffffffffff88166000908152600a60209081526040808320338452909152902055600193505050509392505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461186c57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff81166118d8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180615edb602a913960400191505060405180910390fd5b600e80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517fe475e580d85111348e40d8ca33cfdd74c30fe1655c2d8537a13abc10065ffa5a90600090a250565b60125460ff1660011461195957600080fd5b6000611964306145e1565b905080156119775761197730838361439f565b6119803061462b565b5050601280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166002179055565b60085460009073ffffffffffffffffffffffffffffffffffffffff163314611a22576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615f796029913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166000818152600c6020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055600d909152808220829055517fe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb666929190a2506001919050565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60065460ff1681565b60085474010000000000000000000000000000000000000000900460ff1615611b49576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a81526020018061610d602a913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8416611bb5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f81526020018061603f602f913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8316611c21576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615eb26029913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216611c8d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e8152602001806160ba602e913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8116611cf9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260288152602001806161fa6028913960400191505060405180910390fd5b8751611d0c9060049060208b0190615c4b565b508651611d209060059060208a0190615c4b565b508551611d34906007906020890190615c4b565b50600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff8716179055600880547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff8781169190911790925560018054821686841617905560028054909116918416919091179055611dce81614636565b5050600880547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055505050505050565b60085473ffffffffffffffffffffffffffffffffffffffff1681565b6000611e3d61467d565b905090565b600e5473ffffffffffffffffffffffffffffffffffffffff1690565b60015460009074010000000000000000000000000000000000000000900460ff1615611eeb57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b61145f338484614772565b60015473ffffffffffffffffffffffffffffffffffffffff163314611f66576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806161ae6022913960400191505060405180910390fd5b600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690556040517f7805862f689e2f13df9f062ff482ad3ad112aca9e0847911ed832e158c525b3390600090a1565b60015460009074010000000000000000000000000000000000000000900460ff161561204657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff166120ae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602181526020018061601e6021913960400191505060405180910390fd5b336120b881614371565b1561210e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b8361211881614371565b1561216e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff85166121da576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180615e476023913960400191505060405180910390fd5b60008411612233576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615f2a6029913960400191505060405180910390fd5b336000908152600d60205260409020548085111561229c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e815260200180616180602e913960400191505060405180910390fd5b600b546122a990866147bc565b600b556122c8866122c3876122bd836145e1565b906147bc565b614837565b6122d2818661456a565b336000818152600d6020908152604091829020939093558051888152905173ffffffffffffffffffffffffffffffffffffffff8a16937fab8530f87dc9b59234c4623bf917212bb2536d647574c8e7e5da92c2ede0c9f8928290030190a360408051868152905173ffffffffffffffffffffffffffffffffffffffff8816916000917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a350600195945050505050565b60015474010000000000000000000000000000000000000000900460ff161561241457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff1661247c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602181526020018061601e6021913960400191505060405180910390fd5b3361248681614371565b156124dc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b60006124e7336145e1565b905060008311612542576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615e1e6029913960400191505060405180910390fd5b8281101561259b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180615ff86026913960400191505060405180910390fd5b600b546125a8908461456a565b600b556125b9336122c3838661456a565b60408051848152905133917fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5919081900360200190a260408051848152905160009133917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a3505050565b60125460ff1660021461263e57600080fd5b61264a60058383615cc9565b5060005b8381101561278c576003600086868481811061266657fe5b6020908102929092013573ffffffffffffffffffffffffffffffffffffffff168352508101919091526040016000205460ff166126ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603d815260200180615d6b603d913960400191505060405180910390fd5b61271f8585838181106126fd57fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff1661462b565b6003600086868481811061272f57fe5b6020908102929092013573ffffffffffffffffffffffffffffffffffffffff1683525081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905560010161264e565b506127963061462b565b505030600090815260036020819052604090912080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009081169091556012805490911690911790555050565b60015460009074010000000000000000000000000000000000000000900460ff161561287057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b60085473ffffffffffffffffffffffffffffffffffffffff1633146128e0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615f796029913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff83166000818152600c6020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055600d825291829020859055815185815291517f46980fca912ef9bcdbd36877427b6b90e860769f604e89c0e67720cece530d209281900390910190a250600192915050565b60408051808201909152600181527f3200000000000000000000000000000000000000000000000000000000000000602082015290565b60005473ffffffffffffffffffffffffffffffffffffffff163314612a3357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116612a9f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526028815260200180615dcb6028913960400191505060405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691909117918290556040519116907fb80482a293ca2e013eda8683c9bd7fc8347cfdaeea5ede58cba46df502c2a60490600090a250565b60015474010000000000000000000000000000000000000000900460ff1615612b9e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b612bab8585858585614938565b5050505050565b60015474010000000000000000000000000000000000000000900460ff1681565b6000612bde826145e1565b92915050565b612bec613011565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612c8557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4f4e4c595f474154455741590000000000000000000000000000000000000000604482015290519081900360640190fd5b612c8f8282614978565b5050565b73ffffffffffffffffffffffffffffffffffffffff1660009081526011602052604090205490565b7fd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de881565b60015473ffffffffffffffffffffffffffffffffffffffff163314612d4f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806161ae6022913960400191505060405180910390fd5b600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790556040517f6985a02210a168e66602d3235cb6db0e70f92b3ba4d376a33c0f3d9434bff62590600090a1565b60015474010000000000000000000000000000000000000000900460ff1615612e4357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b86612e4d81614371565b15612ea3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b86612ead81614371565b15612f03576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b612f1289898989898989614c3e565b505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff166000908152600d602052604090205490565b612f4d613011565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612fe657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4f4e4c595f474154455741590000000000000000000000000000000000000000604482015290519081900360640190fd5b612ff08282611fb9565b505050565b60005473ffffffffffffffffffffffffffffffffffffffff1690565b7fdbf6298cab77bb44ebfd5abb25ed2538c2a55f7404c47e83e6531361fba28c245490565b6005805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156113bf5780601f10611394576101008083540402835291602001916113bf565b60015473ffffffffffffffffffffffffffffffffffffffff1681565b60015474010000000000000000000000000000000000000000900460ff161561315557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b612bab8585858585614d5f565b7f7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a226781565b60125460ff1660031461319857600080fd5b73ffffffffffffffffffffffffffffffffffffffff821661321a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f494e56414c49445f474154455741590000000000000000000000000000000000604482015290519081900360640190fd5b6000613224613011565b73ffffffffffffffffffffffffffffffffffffffff16146132a657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f414c52454144595f494e49540000000000000000000000000000000000000000604482015290519081900360640190fd5b817fdbf6298cab77bb44ebfd5abb25ed2538c2a55f7404c47e83e6531361fba28c2455807f54352c0d7cc5793352a36344bfdcdcf68ba6258544ce1aed71f60a74d882c19155612c8f82615023565b60015460009074010000000000000000000000000000000000000000900460ff161561338257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b61145f3384846150d8565b60015460009074010000000000000000000000000000000000000000900460ff161561341a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b3361342481614371565b1561347a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b8361348481614371565b156134da576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b6134e533868661439f565b506001949350505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461357657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff81166135e2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f81526020018061603f602f913960400191505060405180910390fd5b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691909117918290556040519116907fdb66dfa9c6b8f5226fe9aac7e51897ae8ee94ac31dc70bb6c9900b2574b707e690600090a250565b73ffffffffffffffffffffffffffffffffffffffff166000908152600c602052604090205460ff1690565b60005473ffffffffffffffffffffffffffffffffffffffff16331461370857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116613774576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260328152602001806162506032913960400191505060405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691909117918290556040519116907fc67398012c111ce95ecb7429b933096c977380ee6c421175a71a4a4c6c88c06e90600090a250565b600e5473ffffffffffffffffffffffffffffffffffffffff163314613859576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602481526020018061606e6024913960400191505060405180910390fd5b612ff073ffffffffffffffffffffffffffffffffffffffff84168383615134565b60015474010000000000000000000000000000000000000000900460ff161561390457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b612ff08383836151c1565b60025473ffffffffffffffffffffffffffffffffffffffff1681565b7f54352c0d7cc5793352a36344bfdcdcf68ba6258544ce1aed71f60a74d882c1915490565b60015474010000000000000000000000000000000000000000900460ff16156139da57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b866139e481614371565b15613a3a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b86613a4481614371565b15613a9a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b612f12898989898989896152cb565b60015474010000000000000000000000000000000000000000900460ff1615613b3357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b613b4287878787878787615369565b50505050505050565b60085474010000000000000000000000000000000000000000900460ff168015613b78575060125460ff16155b613b8157600080fd5b613b8d60048383615cc9565b50613c0282828080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600181527f3200000000000000000000000000000000000000000000000000000000000000602082015291506153ab9050565b600f555050601280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b7f158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a159742981565b73ffffffffffffffffffffffffffffffffffffffff9182166000908152600a6020908152604080832093909416825291909152205490565b60015474010000000000000000000000000000000000000000900460ff1615613d1a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b88613d2481614371565b15613d7a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b88613d8481614371565b15613dda576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b613deb8b8b8b8b8b8b8b8b8b6153c1565b5050505050505050505050565b6007805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156113bf5780601f10611394576101008083540402835291602001916113bf565b73ffffffffffffffffffffffffffffffffffffffff919091166000908152601060209081526040808320938352929052205460ff1690565b60015474010000000000000000000000000000000000000000900460ff1615613f3357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b88613f3d81614371565b15613f93576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b88613f9d81614371565b15613ff3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b613deb8b8b8b8b8b8b8b8b8b615405565b60005473ffffffffffffffffffffffffffffffffffffffff16331461408a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff81166140f6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180615e6a6026913960400191505060405180910390fd5b6000546040805173ffffffffffffffffffffffffffffffffffffffff9283168152918316602083015280517f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09281900390910190a161415481614636565b50565b60025473ffffffffffffffffffffffffffffffffffffffff1633146141c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c815260200180615fa2602c913960400191505060405180910390fd5b6141d08161462b565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fffa4e6181777692565cf28528fc88fd1516ea86b56da075235fa575af6a4b85590600090a250565b6000612bde82614371565b73ffffffffffffffffffffffffffffffffffffffff831661428b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602481526020018061615c6024913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166142f7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180615e906022913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8084166000818152600a6020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b614154816000615449565b73ffffffffffffffffffffffffffffffffffffffff1660009081526009602052604090205460ff1c60011490565b73ffffffffffffffffffffffffffffffffffffffff831661440b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806161376025913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216614477576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180615da86023913960400191505060405180910390fd5b614480836145e1565b8111156144d8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180615f536026913960400191505060405180910390fd5b6144ef836122c3836144e9876145e1565b9061456a565b614500826122c3836122bd866145e1565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6000828211156145db57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b73ffffffffffffffffffffffffffffffffffffffff166000908152600960205260409020547f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690565b614154816001615449565b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6004805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152600093611e3d939192909183018282801561472a5780601f106146ff5761010080835404028352916020019161472a565b820191906000526020600020905b81548152906001019060200180831161470d57829003601f168201915b50505050506040518060400160405280600181526020017f320000000000000000000000000000000000000000000000000000000000000081525061476d6154d2565b6154d6565b73ffffffffffffffffffffffffffffffffffffffff8084166000908152600a6020908152604080832093861683529290522054612ff090849084906147b790856147bc565b61421f565b60008282018381101561483057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8111156148b0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180615fce602a913960400191505060405180910390fd5b6148b982614371565b1561490f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615f056025913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff909116600090815260096020526040902055565b612bab8585848487604051602001808481526020018381526020018260ff1660f81b815260010193505050506040516020818303038152906040526151c1565b60015474010000000000000000000000000000000000000000900460ff1615614a0257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff16614a6a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602181526020018061601e6021913960400191505060405180910390fd5b81614a7481614371565b15614aca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b6000614ad5846145e1565b905060008311614b30576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615e1e6029913960400191505060405180910390fd5b82811015614b89576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180615ff86026913960400191505060405180910390fd5b600b80548490039055614b9e84848303614837565b60408051848152905173ffffffffffffffffffffffffffffffffffffffff8616917fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5919081900360200190a260408051848152905160009173ffffffffffffffffffffffffffffffffffffffff8716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a350505050565b73ffffffffffffffffffffffffffffffffffffffff86163314614cac576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806160e86025913960400191505060405180910390fd5b614cb88783868661554a565b604080517fd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de860208083019190915273ffffffffffffffffffffffffffffffffffffffff808b1683850152891660608301526080820188905260a0820187905260c0820186905260e0808301869052835180840390910181526101009092019092528051910120614d4a9088908361560a565b614d548783615788565b613b4287878761439f565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821480614d8d5750428210155b614df857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f46696174546f6b656e56323a207065726d697420697320657870697265640000604482015290519081900360640190fd5b6000614ea0614e0561467d565b73ffffffffffffffffffffffffffffffffffffffff80891660008181526011602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98184015280840194909452938b166060840152608083018a905260a083019390935260c08083018990528151808403909101815260e09092019052805191012061580d565b905073__$715109b5d747ea58b675c6ea3f0dba8c60$__636ccea6528783856040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff16815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015614f2d578181015183820152602001614f15565b50505050905090810190601f168015614f5a5780820380516001836020036101000a031916815260200191505b5094505050505060206040518083038186803b158015614f7957600080fd5b505af4158015614f8d573d6000803e3d6000fd5b505050506040513d6020811015614fa357600080fd5b505161501057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f454950323631323a20696e76616c6964207369676e6174757265000000000000604482015290519081900360640190fd5b61501b86868661421f565b505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000818152600c6020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055600d8252918290207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90819055825181815292519093927f46980fca912ef9bcdbd36877427b6b90e860769f604e89c0e67720cece530d2092908290030190a25050565b612ff083836147b7846040518060600160405280602581526020016162cc6025913973ffffffffffffffffffffffffffffffffffffffff808a166000908152600a60209081526040808320938c16835292905220549190615847565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052612ff09084906158f8565b6151cb83836159d0565b615245837f158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a159742960001b8585604051602001808481526020018373ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050604051602081830303815290604052805190602001208361560a565b73ffffffffffffffffffffffffffffffffffffffff8316600081815260106020908152604080832086845290915280822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055518492917f1cdd46ff242716cdaa72d159d339a485b3438398348d68f09d7c8c0a59353d8191a3505050565b6152d78783868661554a565b604080517f7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a226760208083019190915273ffffffffffffffffffffffffffffffffffffffff808b1683850152891660608301526080820188905260a0820187905260c0820186905260e0808301869052835180840390910181526101009092019092528051910120614d4a9088908361560a565b613b4287878787868689604051602001808481526020018381526020018260ff1660f81b81526001019350505050604051602081830303815290604052614d5f565b6000466153b98484836154d6565b949350505050565b612f1289898989898988888b604051602001808481526020018381526020018260ff1660f81b815260010193505050506040516020818303038152906040526152cb565b612f1289898989898988888b604051602001808481526020018381526020018260ff1660f81b81526001019350505050604051602081830303815290604052614c3e565b8061545c57615457826145e1565b6154a5565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600960205260409020547f8000000000000000000000000000000000000000000000000000000000000000175b73ffffffffffffffffffffffffffffffffffffffff90921660009081526009602052604090209190915550565b4690565b8251602093840120825192840192909220604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8187015280820194909452606084019190915260808301919091523060a0808401919091528151808403909101815260c09092019052805191012090565b8142116155a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b815260200180615df3602b913960400191505060405180910390fd5b8042106155fa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162a76025913960400191505060405180910390fd5b61560484846159d0565b50505050565b73__$715109b5d747ea58b675c6ea3f0dba8c60$__636ccea6528461563661563061467d565b8661580d565b846040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff16815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b838110156156a557818101518382015260200161568d565b50505050905090810190601f1680156156d25780820380516001836020036101000a031916815260200191505b5094505050505060206040518083038186803b1580156156f157600080fd5b505af4158015615705573d6000803e3d6000fd5b505050506040513d602081101561571b57600080fd5b5051612ff057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f46696174546f6b656e56323a20696e76616c6964207369676e61747572650000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8216600081815260106020908152604080832085845290915280822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055518392917f98de503528ee59b575ef0c0a2576a82497bfc029a5685b209e9ec333479b10a591a35050565b6040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b600081848411156158f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b838110156158b557818101518382015260200161589d565b50505050905090810190601f1680156158e25780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b606061595a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16615a5a9092919063ffffffff16565b805190915015612ff05780806020019051602081101561597957600080fd5b5051612ff0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a8152602001806161d0602a913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216600090815260106020908152604080832084845290915290205460ff1615612c8f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e815260200180616222602e913960400191505060405180910390fd5b60606153b9848460008585615a6e85615bc5565b615ad957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b60208310615b4357805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101615b06565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114615ba5576040519150601f19603f3d011682016040523d82523d6000602084013e615baa565b606091505b5091509150615bba828286615bcb565b979650505050505050565b3b151590565b60608315615bda575081614830565b825115615bea5782518084602001fd5b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526020600482018181528451602484015284518593919283926044019190850190808383600083156158b557818101518382015260200161589d565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10615c8c57805160ff1916838001178555615cb9565b82800160010185558215615cb9579182015b82811115615cb9578251825591602001919060010190615c9e565b50615cc5929150615d55565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10615d28578280017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00823516178555615cb9565b82800160010185558215615cb9579182015b82811115615cb9578235825591602001919060010190615d3a565b5b80821115615cc55760008155600101615d5656fe46696174546f6b656e56325f323a20426c61636b6c697374696e672070726576696f75736c7920756e626c61636b6c6973746564206163636f756e742145524332303a207472616e7366657220746f20746865207a65726f20616464726573735061757361626c653a206e65772070617573657220697320746865207a65726f206164647265737346696174546f6b656e56323a20617574686f72697a6174696f6e206973206e6f74207965742076616c696446696174546f6b656e3a206275726e20616d6f756e74206e6f742067726561746572207468616e203046696174546f6b656e3a206d696e7420746f20746865207a65726f20616464726573734f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737346696174546f6b656e3a206e65772070617573657220697320746865207a65726f2061646472657373526573637561626c653a206e6577207265736375657220697320746865207a65726f206164647265737346696174546f6b656e56325f323a204163636f756e7420697320626c61636b6c697374656446696174546f6b656e3a206d696e7420616d6f756e74206e6f742067726561746572207468616e203045524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636546696174546f6b656e3a2063616c6c6572206973206e6f7420746865206d61737465724d696e746572426c61636b6c69737461626c653a2063616c6c6572206973206e6f742074686520626c61636b6c697374657246696174546f6b656e56325f323a2042616c616e636520657863656564732028325e323535202d20312946696174546f6b656e3a206275726e20616d6f756e7420657863656564732062616c616e636546696174546f6b656e3a2063616c6c6572206973206e6f742061206d696e74657246696174546f6b656e3a206e6577206d61737465724d696e74657220697320746865207a65726f2061646472657373526573637561626c653a2063616c6c6572206973206e6f7420746865207265736375657245524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636546696174546f6b656e3a206e657720626c61636b6c697374657220697320746865207a65726f206164647265737346696174546f6b656e56323a2063616c6c6572206d7573742062652074686520706179656546696174546f6b656e3a20636f6e747261637420697320616c726561647920696e697469616c697a656445524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737346696174546f6b656e3a206d696e7420616d6f756e742065786365656473206d696e746572416c6c6f77616e63655061757361626c653a2063616c6c6572206973206e6f7420746865207061757365725361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656446696174546f6b656e3a206e6577206f776e657220697320746865207a65726f206164647265737346696174546f6b656e56323a20617574686f72697a6174696f6e2069732075736564206f722063616e63656c6564426c61636b6c69737461626c653a206e657720626c61636b6c697374657220697320746865207a65726f2061646472657373426c61636b6c69737461626c653a206163636f756e7420697320626c61636b6c697374656446696174546f6b656e56323a20617574686f72697a6174696f6e206973206578706972656445524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa26469706673582212205b9c28831ca019c704546ef047ba19de251c8493a622e0f4ae1dff3520aaae2464736f6c634300060c0033' + const placeholder = '__$715109b5d747ea58b675c6ea3f0dba8c60$__' + const bridgedUsdcLogicBytecode = bytecodeWithPlaceholder + .split(placeholder) + .join(sigCheckerLib.address.replace(/^0x/, '')) + + // deploy bridged usdc logic + const bridgedUsdcLogicFactory = new ethers.ContractFactory( + [], + bridgedUsdcLogicBytecode, + deployer + ) + const bridgedUsdcLogic = await bridgedUsdcLogicFactory.deploy() + + return bridgedUsdcLogic +} diff --git a/test-foundry/util/TestUtil.sol b/test-foundry/util/TestUtil.sol index 51edcb835c..05375bac91 100644 --- a/test-foundry/util/TestUtil.sol +++ b/test-foundry/util/TestUtil.sol @@ -4,7 +4,6 @@ pragma solidity ^0.8.4; import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; import "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; - library TestUtil { function deployProxy(address logic) public returns (address) { ProxyAdmin pa = new ProxyAdmin(); @@ -23,7 +22,6 @@ library TestUtil { } require(sigCheckerAddress != address(0), "Failed to deploy contract"); - /// deploy bridged usdc token // insert lib address into bytecode From cb941dff8b11e15bd1d78943366f16ac4cc76ff4 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 6 Jun 2024 18:49:01 +0200 Subject: [PATCH 08/20] Update test --- .../test/BridgedUsdcCustomToken.sol | 26 ------------------- test-e2e/orbitTokenBridge.ts | 7 ++--- 2 files changed, 2 insertions(+), 31 deletions(-) delete mode 100644 contracts/tokenbridge/test/BridgedUsdcCustomToken.sol diff --git a/contracts/tokenbridge/test/BridgedUsdcCustomToken.sol b/contracts/tokenbridge/test/BridgedUsdcCustomToken.sol deleted file mode 100644 index f0a4059e72..0000000000 --- a/contracts/tokenbridge/test/BridgedUsdcCustomToken.sol +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.0; - -import {L2GatewayToken} from "../libraries/L2GatewayToken.sol"; - -/** - * @title A custom token contract that can be used as bridged USDC - * @dev At some point later bridged USDC can be upgraded to native USDC - */ -contract BridgedUsdcCustomToken is L2GatewayToken { - /** - * @notice initialize the token - * @param name_ ERC20 token name - * @param l2Gateway_ L2 gateway this token communicates with - * @param l1Counterpart_ L1 address of ERC20 - */ - function initialize(string memory name_, address l2Gateway_, address l1Counterpart_) public { - L2GatewayToken._initialize({ - name_: name_, - symbol_: "USDC.e", - decimals_: uint8(6), - l2Gateway_: l2Gateway_, - l1Counterpart_: l1Counterpart_ - }); - } -} diff --git a/test-e2e/orbitTokenBridge.ts b/test-e2e/orbitTokenBridge.ts index 089bd547e9..872f58fd1d 100644 --- a/test-e2e/orbitTokenBridge.ts +++ b/test-e2e/orbitTokenBridge.ts @@ -864,7 +864,7 @@ describe('orbitTokenBridge', () => { console.log('USDC burned') }) - it.only('can upgrade from bridged USDC to native USDC when fee token is used', async function () { + it('can upgrade from bridged USDC to native USDC when fee token is used', async function () { /// test applicable only for fee token based chains if (!nativeToken) { return @@ -924,10 +924,7 @@ describe('orbitTokenBridge', () => { console.log('L1 USDC address: ', l1Usdc.address) /// create l2 usdc behind proxy - const l2UsdcFactory = await new BridgedUsdcCustomToken__factory( - deployerL2Wallet - ).deploy() - const l2UsdcLogic = await l2UsdcFactory.deployed() + const l2UsdcLogic = await _deployBridgedUsdcToken(deployerL2Wallet) const tupL2UsdcFactory = await new TransparentUpgradeableProxy__factory( deployerL2Wallet ).deploy(l2UsdcLogic.address, proxyAdminL2.address, '0x') From 98d711e6b8f706b7013392a0ca11506fa53ed626 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Fri, 7 Jun 2024 11:11:40 +0200 Subject: [PATCH 09/20] Add initializtion of usdc token --- test-e2e/orbitTokenBridge.ts | 57 +++++++++++++++++++++----- test-foundry/L2USDCCustomGateway.t.sol | 18 -------- test-foundry/util/TestUtil.sol | 6 +-- 3 files changed, 50 insertions(+), 31 deletions(-) diff --git a/test-e2e/orbitTokenBridge.ts b/test-e2e/orbitTokenBridge.ts index 872f58fd1d..59a95e00f9 100644 --- a/test-e2e/orbitTokenBridge.ts +++ b/test-e2e/orbitTokenBridge.ts @@ -11,10 +11,10 @@ import { JsonRpcProvider } from '@ethersproject/providers' import { expect } from 'chai' import { setupTokenBridgeInLocalEnv } from '../scripts/local-deployment/localDeploymentLib' import { - BridgedUsdcCustomToken__factory, ERC20, ERC20__factory, IERC20Bridge__factory, + IERC20__factory, IInbox__factory, IOwnable__factory, L1FeeTokenUSDCCustomGateway__factory, @@ -35,6 +35,7 @@ import { TestOrbitCustomTokenL1__factory, TransparentUpgradeableProxy__factory, UpgradeExecutor__factory, + IFiatTokenArbitrumOrbitV22__factory, } from '../build/types' import { defaultAbiCoder } from 'ethers/lib/utils' import { BigNumber, Wallet, ethers } from 'ethers' @@ -711,17 +712,34 @@ describe('orbitTokenBridge', () => { deployerL2Wallet ).deploy(l2UsdcLogic.address, proxyAdminL2.address, '0x') const tupL2Usdc = await tupL2UsdcFactory.deployed() - const l2Usdc = BridgedUsdcCustomToken__factory.connect( + const l2UsdcInit = IFiatTokenArbitrumOrbitV22__factory.connect( tupL2Usdc.address, deployerL2Wallet ) await ( - await l2Usdc.initialize( - 'Bridged USDC Orbit', + await l2UsdcInit.initialize( + 'USDC token', + 'USDC.e', + 'USD', + 6, + ethers.Wallet.createRandom().address, + ethers.Wallet.createRandom().address, + ethers.Wallet.createRandom().address, + deployerL2Wallet.address + ) + ).wait() + await (await l2UsdcInit.initializeV2('USDC')).wait() + await ( + await l2UsdcInit.initializeV2_1(ethers.Wallet.createRandom().address) + ).wait() + await (await l2UsdcInit.initializeV2_2([], 'USDC.e')).wait() + await ( + await l2UsdcInit.initializeArbitrumOrbit( l2USDCCustomGateway.address, l1Usdc.address ) ).wait() + const l2Usdc = IERC20__factory.connect(l2UsdcInit.address, deployerL2Wallet) console.log('L2 USDC address: ', l2Usdc.address) /// initialize gateways @@ -929,17 +947,34 @@ describe('orbitTokenBridge', () => { deployerL2Wallet ).deploy(l2UsdcLogic.address, proxyAdminL2.address, '0x') const tupL2Usdc = await tupL2UsdcFactory.deployed() - const l2Usdc = BridgedUsdcCustomToken__factory.connect( + const l2UsdcInit = IFiatTokenArbitrumOrbitV22__factory.connect( tupL2Usdc.address, deployerL2Wallet ) await ( - await l2Usdc.initialize( - 'Bridged USDC Orbit', + await l2UsdcInit.initialize( + 'USDC token', + 'USDC.e', + 'USD', + 6, + ethers.Wallet.createRandom().address, + ethers.Wallet.createRandom().address, + ethers.Wallet.createRandom().address, + deployerL2Wallet.address + ) + ).wait() + await (await l2UsdcInit.initializeV2('USDC')).wait() + await ( + await l2UsdcInit.initializeV2_1(ethers.Wallet.createRandom().address) + ).wait() + await (await l2UsdcInit.initializeV2_2([], 'USDC.e')).wait() + await ( + await l2UsdcInit.initializeArbitrumOrbit( l2USDCCustomGateway.address, l1Usdc.address ) ).wait() + const l2Usdc = IERC20__factory.connect(l2UsdcInit.address, deployerL2Wallet) console.log('L2 USDC address: ', l2Usdc.address) /// initialize gateways @@ -1188,12 +1223,14 @@ async function _deployBridgedUsdcToken(deployer: Wallet) { const sigCheckerLib = await sigCheckerFactory.deploy() // prepare bridged usdc bytecode - const bytecodeWithPlaceholder = - '60806040526001805460ff60a01b191690556000600b553480156200002357600080fd5b506200002f3362000035565b62000057565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b61632680620000676000396000f3fe608060405234801561001057600080fd5b50600436106103a45760003560e01c80638a6db9c3116101e9578063b7b728991161010f578063dd62ed3e116100ad578063ef55bec61161007c578063ef55bec614611216578063f2fde38b14611282578063f9f92be4146112b5578063fe575a87146112e8576103a4565b8063dd62ed3e1461112e578063e3ee160e14611169578063e5a6b10f146111d5578063e94a0102146111dd576103a4565b8063cf092995116100e9578063cf09299514610f74578063d505accf14611058578063d608ea64146110b6578063d916948714611126576103a4565b8063b7b7289914610e9c578063bd10243014610f64578063c2eeeebd14610f6c576103a4565b8063a0cc6a6811610187578063aa20e1e411610156578063aa20e1e414610dc0578063aa271e1a14610df3578063ad38bf2214610e26578063b2118a8d14610e59576103a4565b8063a0cc6a6814610d0b578063a297ea5e14610d13578063a457c2d714610d4e578063a9059cbb14610d87576103a4565b80638fa74a0e116101c35780638fa74a0e14610c1b57806395d89b4114610c235780639fd0506d14610c2b5780639fd5a6cf14610c33576103a4565b80638a6db9c314610ba75780638c2a993e14610bda5780638da5cb5b14610c13576103a4565b80633f4ba83a116102ce5780635a049a701161026c5780637ecebe001161023b5780637ecebe0014610a805780637f2eecc314610ab35780638456cb5914610abb57806388b7ab6314610ac3576103a4565b80635a049a70146109be5780635c975abb14610a0c57806370a0823114610a1457806374f4f54714610a47576103a4565b8063430239b4116102a8578063430239b4146108885780634e44d9561461094a57806354fd4d5014610983578063554bab3c1461098b576103a4565b80633f4ba83a1461082a57806340c10f191461083257806342966c681461086b576103a4565b80633092afd51161034657806335d99f351161031557806335d99f35146107b05780633644e515146107e157806338a63183146107e957806339509351146107f1576103a4565b80633092afd51461056b57806330adf81f1461059e578063313ce567146105a65780633357162b146105c4576103a4565b80631a895266116103825780631a8952661461048d57806323b872dd146104c25780632ab60045146105055780632fc81e0914610538576103a4565b806306fdde03146103a9578063095ea7b31461042657806318160ddd14610473575b600080fd5b6103b161131b565b6040805160208082528351818301528351919283929083019185019080838360005b838110156103eb5781810151838201526020016103d3565b50505050905090810190601f1680156104185780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61045f6004803603604081101561043c57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356113c7565b604080519115158252519081900360200190f35b61047b611468565b60408051918252519081900360200190f35b6104c0600480360360208110156104a357600080fd5b503573ffffffffffffffffffffffffffffffffffffffff1661146e565b005b61045f600480360360608110156104d857600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020810135909116906040013561152b565b6104c06004803603602081101561051b57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166117e6565b6104c06004803603602081101561054e57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611947565b61045f6004803603602081101561058157600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166119af565b61047b611aa8565b6105ae611acc565b6040805160ff9092168252519081900360200190f35b6104c060048036036101008110156105db57600080fd5b8101906020810181356401000000008111156105f657600080fd5b82018360208201111561060857600080fd5b8035906020019184600183028401116401000000008311171561062a57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929594936020810193503591505064010000000081111561067d57600080fd5b82018360208201111561068f57600080fd5b803590602001918460018302840111640100000000831117156106b157600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929594936020810193503591505064010000000081111561070457600080fd5b82018360208201111561071657600080fd5b8035906020019184600183028401116401000000008311171561073857600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050813560ff16925050602081013573ffffffffffffffffffffffffffffffffffffffff90811691604081013582169160608201358116916080013516611ad5565b6107b8611e17565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b61047b611e33565b6107b8611e42565b61045f6004803603604081101561080757600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135611e5e565b6104c0611ef6565b61045f6004803603604081101561084857600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135611fb9565b6104c06004803603602081101561088157600080fd5b503561238a565b6104c06004803603604081101561089e57600080fd5b8101906020810181356401000000008111156108b957600080fd5b8201836020820111156108cb57600080fd5b803590602001918460208302840111640100000000831117156108ed57600080fd5b91939092909160208101903564010000000081111561090b57600080fd5b82018360208201111561091d57600080fd5b8035906020019184600183028401116401000000008311171561093f57600080fd5b50909250905061262c565b61045f6004803603604081101561096057600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356127e3565b6103b1612976565b6104c0600480360360208110156109a157600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166129ad565b6104c0600480360360a08110156109d457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060208101359060ff6040820135169060608101359060800135612b14565b61045f612bb2565b61047b60048036036020811015610a2a57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612bd3565b6104c060048036036040811015610a5d57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135612be4565b61047b60048036036020811015610a9657600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612c93565b61047b612cbb565b6104c0612cdf565b6104c0600480360360e0811015610ad957600080fd5b73ffffffffffffffffffffffffffffffffffffffff823581169260208101359091169160408201359160608101359160808201359160a08101359181019060e0810160c0820135640100000000811115610b3257600080fd5b820183602082011115610b4457600080fd5b80359060200191846001830284011164010000000083111715610b6657600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612db9945050505050565b61047b60048036036020811015610bbd57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612f1d565b6104c060048036036040811015610bf057600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135612f45565b6107b8612ff5565b6107b8613011565b6103b1613036565b6107b86130af565b6104c0600480360360a0811015610c4957600080fd5b73ffffffffffffffffffffffffffffffffffffffff823581169260208101359091169160408201359160608101359181019060a081016080820135640100000000811115610c9657600080fd5b820183602082011115610ca857600080fd5b80359060200191846001830284011164010000000083111715610cca57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506130cb945050505050565b61047b613162565b6104c060048036036040811015610d2957600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020013516613186565b61045f60048036036040811015610d6457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356132f5565b61045f60048036036040811015610d9d57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813516906020013561338d565b6104c060048036036020811015610dd657600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166134f0565b61045f60048036036020811015610e0957600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16613657565b6104c060048036036020811015610e3c57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16613682565b6104c060048036036060811015610e6f57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135811691602081013590911690604001356137e9565b6104c060048036036060811015610eb257600080fd5b73ffffffffffffffffffffffffffffffffffffffff82351691602081013591810190606081016040820135640100000000811115610eef57600080fd5b820183602082011115610f0157600080fd5b80359060200191846001830284011164010000000083111715610f2357600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092955061387a945050505050565b6107b861390f565b6107b861392b565b6104c0600480360360e0811015610f8a57600080fd5b73ffffffffffffffffffffffffffffffffffffffff823581169260208101359091169160408201359160608101359160808201359160a08101359181019060e0810160c0820135640100000000811115610fe357600080fd5b820183602082011115610ff557600080fd5b8035906020019184600183028401116401000000008311171561101757600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550613950945050505050565b6104c0600480360360e081101561106e57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c00135613aa9565b6104c0600480360360208110156110cc57600080fd5b8101906020810181356401000000008111156110e757600080fd5b8201836020820111156110f957600080fd5b8035906020019184600183028401116401000000008311171561111b57600080fd5b509092509050613b4b565b61047b613c34565b61047b6004803603604081101561114457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020013516613c58565b6104c0600480360361012081101561118057600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060408101359060608101359060808101359060a08101359060ff60c0820135169060e0810135906101000135613c90565b6103b1613df8565b61045f600480360360408110156111f357600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135613e71565b6104c0600480360361012081101561122d57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060408101359060608101359060808101359060a08101359060ff60c0820135169060e0810135906101000135613ea9565b6104c06004803603602081101561129857600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16614004565b6104c0600480360360208110156112cb57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16614157565b61045f600480360360208110156112fe57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16614214565b6004805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156113bf5780601f10611394576101008083540402835291602001916113bf565b820191906000526020600020905b8154815290600101906020018083116113a257829003601f168201915b505050505081565b60015460009074010000000000000000000000000000000000000000900460ff161561145457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b61145f33848461421f565b50600192915050565b600b5490565b60025473ffffffffffffffffffffffffffffffffffffffff1633146114de576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c815260200180615fa2602c913960400191505060405180910390fd5b6114e781614366565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f117e3210bb9aa7d9baff172026820255c6f6c30ba8999d1c2fd88e2848137c4e90600090a250565b60015460009074010000000000000000000000000000000000000000900460ff16156115b857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336115c281614371565b15611618576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b8461162281614371565b15611678576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b8461168281614371565b156116d8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff87166000908152600a60209081526040808320338452909152902054851115611761576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260288152602001806160926028913960400191505060405180910390fd5b61176c87878761439f565b73ffffffffffffffffffffffffffffffffffffffff87166000908152600a602090815260408083203384529091529020546117a7908661456a565b73ffffffffffffffffffffffffffffffffffffffff88166000908152600a60209081526040808320338452909152902055600193505050509392505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461186c57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff81166118d8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180615edb602a913960400191505060405180910390fd5b600e80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517fe475e580d85111348e40d8ca33cfdd74c30fe1655c2d8537a13abc10065ffa5a90600090a250565b60125460ff1660011461195957600080fd5b6000611964306145e1565b905080156119775761197730838361439f565b6119803061462b565b5050601280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166002179055565b60085460009073ffffffffffffffffffffffffffffffffffffffff163314611a22576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615f796029913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166000818152600c6020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055600d909152808220829055517fe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb666929190a2506001919050565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60065460ff1681565b60085474010000000000000000000000000000000000000000900460ff1615611b49576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a81526020018061610d602a913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8416611bb5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f81526020018061603f602f913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8316611c21576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615eb26029913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216611c8d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e8152602001806160ba602e913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8116611cf9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260288152602001806161fa6028913960400191505060405180910390fd5b8751611d0c9060049060208b0190615c4b565b508651611d209060059060208a0190615c4b565b508551611d34906007906020890190615c4b565b50600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff8716179055600880547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff8781169190911790925560018054821686841617905560028054909116918416919091179055611dce81614636565b5050600880547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055505050505050565b60085473ffffffffffffffffffffffffffffffffffffffff1681565b6000611e3d61467d565b905090565b600e5473ffffffffffffffffffffffffffffffffffffffff1690565b60015460009074010000000000000000000000000000000000000000900460ff1615611eeb57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b61145f338484614772565b60015473ffffffffffffffffffffffffffffffffffffffff163314611f66576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806161ae6022913960400191505060405180910390fd5b600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690556040517f7805862f689e2f13df9f062ff482ad3ad112aca9e0847911ed832e158c525b3390600090a1565b60015460009074010000000000000000000000000000000000000000900460ff161561204657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff166120ae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602181526020018061601e6021913960400191505060405180910390fd5b336120b881614371565b1561210e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b8361211881614371565b1561216e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff85166121da576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180615e476023913960400191505060405180910390fd5b60008411612233576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615f2a6029913960400191505060405180910390fd5b336000908152600d60205260409020548085111561229c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e815260200180616180602e913960400191505060405180910390fd5b600b546122a990866147bc565b600b556122c8866122c3876122bd836145e1565b906147bc565b614837565b6122d2818661456a565b336000818152600d6020908152604091829020939093558051888152905173ffffffffffffffffffffffffffffffffffffffff8a16937fab8530f87dc9b59234c4623bf917212bb2536d647574c8e7e5da92c2ede0c9f8928290030190a360408051868152905173ffffffffffffffffffffffffffffffffffffffff8816916000917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a350600195945050505050565b60015474010000000000000000000000000000000000000000900460ff161561241457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff1661247c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602181526020018061601e6021913960400191505060405180910390fd5b3361248681614371565b156124dc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b60006124e7336145e1565b905060008311612542576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615e1e6029913960400191505060405180910390fd5b8281101561259b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180615ff86026913960400191505060405180910390fd5b600b546125a8908461456a565b600b556125b9336122c3838661456a565b60408051848152905133917fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5919081900360200190a260408051848152905160009133917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a3505050565b60125460ff1660021461263e57600080fd5b61264a60058383615cc9565b5060005b8381101561278c576003600086868481811061266657fe5b6020908102929092013573ffffffffffffffffffffffffffffffffffffffff168352508101919091526040016000205460ff166126ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603d815260200180615d6b603d913960400191505060405180910390fd5b61271f8585838181106126fd57fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff1661462b565b6003600086868481811061272f57fe5b6020908102929092013573ffffffffffffffffffffffffffffffffffffffff1683525081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905560010161264e565b506127963061462b565b505030600090815260036020819052604090912080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009081169091556012805490911690911790555050565b60015460009074010000000000000000000000000000000000000000900460ff161561287057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b60085473ffffffffffffffffffffffffffffffffffffffff1633146128e0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615f796029913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff83166000818152600c6020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055600d825291829020859055815185815291517f46980fca912ef9bcdbd36877427b6b90e860769f604e89c0e67720cece530d209281900390910190a250600192915050565b60408051808201909152600181527f3200000000000000000000000000000000000000000000000000000000000000602082015290565b60005473ffffffffffffffffffffffffffffffffffffffff163314612a3357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116612a9f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526028815260200180615dcb6028913960400191505060405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691909117918290556040519116907fb80482a293ca2e013eda8683c9bd7fc8347cfdaeea5ede58cba46df502c2a60490600090a250565b60015474010000000000000000000000000000000000000000900460ff1615612b9e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b612bab8585858585614938565b5050505050565b60015474010000000000000000000000000000000000000000900460ff1681565b6000612bde826145e1565b92915050565b612bec613011565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612c8557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4f4e4c595f474154455741590000000000000000000000000000000000000000604482015290519081900360640190fd5b612c8f8282614978565b5050565b73ffffffffffffffffffffffffffffffffffffffff1660009081526011602052604090205490565b7fd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de881565b60015473ffffffffffffffffffffffffffffffffffffffff163314612d4f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806161ae6022913960400191505060405180910390fd5b600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790556040517f6985a02210a168e66602d3235cb6db0e70f92b3ba4d376a33c0f3d9434bff62590600090a1565b60015474010000000000000000000000000000000000000000900460ff1615612e4357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b86612e4d81614371565b15612ea3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b86612ead81614371565b15612f03576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b612f1289898989898989614c3e565b505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff166000908152600d602052604090205490565b612f4d613011565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612fe657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4f4e4c595f474154455741590000000000000000000000000000000000000000604482015290519081900360640190fd5b612ff08282611fb9565b505050565b60005473ffffffffffffffffffffffffffffffffffffffff1690565b7fdbf6298cab77bb44ebfd5abb25ed2538c2a55f7404c47e83e6531361fba28c245490565b6005805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156113bf5780601f10611394576101008083540402835291602001916113bf565b60015473ffffffffffffffffffffffffffffffffffffffff1681565b60015474010000000000000000000000000000000000000000900460ff161561315557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b612bab8585858585614d5f565b7f7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a226781565b60125460ff1660031461319857600080fd5b73ffffffffffffffffffffffffffffffffffffffff821661321a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f494e56414c49445f474154455741590000000000000000000000000000000000604482015290519081900360640190fd5b6000613224613011565b73ffffffffffffffffffffffffffffffffffffffff16146132a657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f414c52454144595f494e49540000000000000000000000000000000000000000604482015290519081900360640190fd5b817fdbf6298cab77bb44ebfd5abb25ed2538c2a55f7404c47e83e6531361fba28c2455807f54352c0d7cc5793352a36344bfdcdcf68ba6258544ce1aed71f60a74d882c19155612c8f82615023565b60015460009074010000000000000000000000000000000000000000900460ff161561338257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b61145f3384846150d8565b60015460009074010000000000000000000000000000000000000000900460ff161561341a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b3361342481614371565b1561347a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b8361348481614371565b156134da576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b6134e533868661439f565b506001949350505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461357657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff81166135e2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f81526020018061603f602f913960400191505060405180910390fd5b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691909117918290556040519116907fdb66dfa9c6b8f5226fe9aac7e51897ae8ee94ac31dc70bb6c9900b2574b707e690600090a250565b73ffffffffffffffffffffffffffffffffffffffff166000908152600c602052604090205460ff1690565b60005473ffffffffffffffffffffffffffffffffffffffff16331461370857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116613774576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260328152602001806162506032913960400191505060405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691909117918290556040519116907fc67398012c111ce95ecb7429b933096c977380ee6c421175a71a4a4c6c88c06e90600090a250565b600e5473ffffffffffffffffffffffffffffffffffffffff163314613859576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602481526020018061606e6024913960400191505060405180910390fd5b612ff073ffffffffffffffffffffffffffffffffffffffff84168383615134565b60015474010000000000000000000000000000000000000000900460ff161561390457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b612ff08383836151c1565b60025473ffffffffffffffffffffffffffffffffffffffff1681565b7f54352c0d7cc5793352a36344bfdcdcf68ba6258544ce1aed71f60a74d882c1915490565b60015474010000000000000000000000000000000000000000900460ff16156139da57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b866139e481614371565b15613a3a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b86613a4481614371565b15613a9a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b612f12898989898989896152cb565b60015474010000000000000000000000000000000000000000900460ff1615613b3357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b613b4287878787878787615369565b50505050505050565b60085474010000000000000000000000000000000000000000900460ff168015613b78575060125460ff16155b613b8157600080fd5b613b8d60048383615cc9565b50613c0282828080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600181527f3200000000000000000000000000000000000000000000000000000000000000602082015291506153ab9050565b600f555050601280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b7f158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a159742981565b73ffffffffffffffffffffffffffffffffffffffff9182166000908152600a6020908152604080832093909416825291909152205490565b60015474010000000000000000000000000000000000000000900460ff1615613d1a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b88613d2481614371565b15613d7a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b88613d8481614371565b15613dda576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b613deb8b8b8b8b8b8b8b8b8b6153c1565b5050505050505050505050565b6007805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156113bf5780601f10611394576101008083540402835291602001916113bf565b73ffffffffffffffffffffffffffffffffffffffff919091166000908152601060209081526040808320938352929052205460ff1690565b60015474010000000000000000000000000000000000000000900460ff1615613f3357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b88613f3d81614371565b15613f93576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b88613f9d81614371565b15613ff3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b613deb8b8b8b8b8b8b8b8b8b615405565b60005473ffffffffffffffffffffffffffffffffffffffff16331461408a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff81166140f6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180615e6a6026913960400191505060405180910390fd5b6000546040805173ffffffffffffffffffffffffffffffffffffffff9283168152918316602083015280517f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09281900390910190a161415481614636565b50565b60025473ffffffffffffffffffffffffffffffffffffffff1633146141c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c815260200180615fa2602c913960400191505060405180910390fd5b6141d08161462b565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fffa4e6181777692565cf28528fc88fd1516ea86b56da075235fa575af6a4b85590600090a250565b6000612bde82614371565b73ffffffffffffffffffffffffffffffffffffffff831661428b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602481526020018061615c6024913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166142f7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180615e906022913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8084166000818152600a6020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b614154816000615449565b73ffffffffffffffffffffffffffffffffffffffff1660009081526009602052604090205460ff1c60011490565b73ffffffffffffffffffffffffffffffffffffffff831661440b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806161376025913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216614477576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180615da86023913960400191505060405180910390fd5b614480836145e1565b8111156144d8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180615f536026913960400191505060405180910390fd5b6144ef836122c3836144e9876145e1565b9061456a565b614500826122c3836122bd866145e1565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6000828211156145db57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b73ffffffffffffffffffffffffffffffffffffffff166000908152600960205260409020547f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690565b614154816001615449565b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6004805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152600093611e3d939192909183018282801561472a5780601f106146ff5761010080835404028352916020019161472a565b820191906000526020600020905b81548152906001019060200180831161470d57829003601f168201915b50505050506040518060400160405280600181526020017f320000000000000000000000000000000000000000000000000000000000000081525061476d6154d2565b6154d6565b73ffffffffffffffffffffffffffffffffffffffff8084166000908152600a6020908152604080832093861683529290522054612ff090849084906147b790856147bc565b61421f565b60008282018381101561483057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8111156148b0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180615fce602a913960400191505060405180910390fd5b6148b982614371565b1561490f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615f056025913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff909116600090815260096020526040902055565b612bab8585848487604051602001808481526020018381526020018260ff1660f81b815260010193505050506040516020818303038152906040526151c1565b60015474010000000000000000000000000000000000000000900460ff1615614a0257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff16614a6a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602181526020018061601e6021913960400191505060405180910390fd5b81614a7481614371565b15614aca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b6000614ad5846145e1565b905060008311614b30576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615e1e6029913960400191505060405180910390fd5b82811015614b89576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180615ff86026913960400191505060405180910390fd5b600b80548490039055614b9e84848303614837565b60408051848152905173ffffffffffffffffffffffffffffffffffffffff8616917fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5919081900360200190a260408051848152905160009173ffffffffffffffffffffffffffffffffffffffff8716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a350505050565b73ffffffffffffffffffffffffffffffffffffffff86163314614cac576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806160e86025913960400191505060405180910390fd5b614cb88783868661554a565b604080517fd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de860208083019190915273ffffffffffffffffffffffffffffffffffffffff808b1683850152891660608301526080820188905260a0820187905260c0820186905260e0808301869052835180840390910181526101009092019092528051910120614d4a9088908361560a565b614d548783615788565b613b4287878761439f565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821480614d8d5750428210155b614df857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f46696174546f6b656e56323a207065726d697420697320657870697265640000604482015290519081900360640190fd5b6000614ea0614e0561467d565b73ffffffffffffffffffffffffffffffffffffffff80891660008181526011602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98184015280840194909452938b166060840152608083018a905260a083019390935260c08083018990528151808403909101815260e09092019052805191012061580d565b905073__$715109b5d747ea58b675c6ea3f0dba8c60$__636ccea6528783856040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff16815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015614f2d578181015183820152602001614f15565b50505050905090810190601f168015614f5a5780820380516001836020036101000a031916815260200191505b5094505050505060206040518083038186803b158015614f7957600080fd5b505af4158015614f8d573d6000803e3d6000fd5b505050506040513d6020811015614fa357600080fd5b505161501057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f454950323631323a20696e76616c6964207369676e6174757265000000000000604482015290519081900360640190fd5b61501b86868661421f565b505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000818152600c6020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055600d8252918290207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90819055825181815292519093927f46980fca912ef9bcdbd36877427b6b90e860769f604e89c0e67720cece530d2092908290030190a25050565b612ff083836147b7846040518060600160405280602581526020016162cc6025913973ffffffffffffffffffffffffffffffffffffffff808a166000908152600a60209081526040808320938c16835292905220549190615847565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052612ff09084906158f8565b6151cb83836159d0565b615245837f158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a159742960001b8585604051602001808481526020018373ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050604051602081830303815290604052805190602001208361560a565b73ffffffffffffffffffffffffffffffffffffffff8316600081815260106020908152604080832086845290915280822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055518492917f1cdd46ff242716cdaa72d159d339a485b3438398348d68f09d7c8c0a59353d8191a3505050565b6152d78783868661554a565b604080517f7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a226760208083019190915273ffffffffffffffffffffffffffffffffffffffff808b1683850152891660608301526080820188905260a0820187905260c0820186905260e0808301869052835180840390910181526101009092019092528051910120614d4a9088908361560a565b613b4287878787868689604051602001808481526020018381526020018260ff1660f81b81526001019350505050604051602081830303815290604052614d5f565b6000466153b98484836154d6565b949350505050565b612f1289898989898988888b604051602001808481526020018381526020018260ff1660f81b815260010193505050506040516020818303038152906040526152cb565b612f1289898989898988888b604051602001808481526020018381526020018260ff1660f81b81526001019350505050604051602081830303815290604052614c3e565b8061545c57615457826145e1565b6154a5565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600960205260409020547f8000000000000000000000000000000000000000000000000000000000000000175b73ffffffffffffffffffffffffffffffffffffffff90921660009081526009602052604090209190915550565b4690565b8251602093840120825192840192909220604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8187015280820194909452606084019190915260808301919091523060a0808401919091528151808403909101815260c09092019052805191012090565b8142116155a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b815260200180615df3602b913960400191505060405180910390fd5b8042106155fa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162a76025913960400191505060405180910390fd5b61560484846159d0565b50505050565b73__$715109b5d747ea58b675c6ea3f0dba8c60$__636ccea6528461563661563061467d565b8661580d565b846040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff16815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b838110156156a557818101518382015260200161568d565b50505050905090810190601f1680156156d25780820380516001836020036101000a031916815260200191505b5094505050505060206040518083038186803b1580156156f157600080fd5b505af4158015615705573d6000803e3d6000fd5b505050506040513d602081101561571b57600080fd5b5051612ff057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f46696174546f6b656e56323a20696e76616c6964207369676e61747572650000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8216600081815260106020908152604080832085845290915280822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055518392917f98de503528ee59b575ef0c0a2576a82497bfc029a5685b209e9ec333479b10a591a35050565b6040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b600081848411156158f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b838110156158b557818101518382015260200161589d565b50505050905090810190601f1680156158e25780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b606061595a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16615a5a9092919063ffffffff16565b805190915015612ff05780806020019051602081101561597957600080fd5b5051612ff0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a8152602001806161d0602a913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216600090815260106020908152604080832084845290915290205460ff1615612c8f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e815260200180616222602e913960400191505060405180910390fd5b60606153b9848460008585615a6e85615bc5565b615ad957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b60208310615b4357805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101615b06565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114615ba5576040519150601f19603f3d011682016040523d82523d6000602084013e615baa565b606091505b5091509150615bba828286615bcb565b979650505050505050565b3b151590565b60608315615bda575081614830565b825115615bea5782518084602001fd5b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526020600482018181528451602484015284518593919283926044019190850190808383600083156158b557818101518382015260200161589d565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10615c8c57805160ff1916838001178555615cb9565b82800160010185558215615cb9579182015b82811115615cb9578251825591602001919060010190615c9e565b50615cc5929150615d55565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10615d28578280017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00823516178555615cb9565b82800160010185558215615cb9579182015b82811115615cb9578235825591602001919060010190615d3a565b5b80821115615cc55760008155600101615d5656fe46696174546f6b656e56325f323a20426c61636b6c697374696e672070726576696f75736c7920756e626c61636b6c6973746564206163636f756e742145524332303a207472616e7366657220746f20746865207a65726f20616464726573735061757361626c653a206e65772070617573657220697320746865207a65726f206164647265737346696174546f6b656e56323a20617574686f72697a6174696f6e206973206e6f74207965742076616c696446696174546f6b656e3a206275726e20616d6f756e74206e6f742067726561746572207468616e203046696174546f6b656e3a206d696e7420746f20746865207a65726f20616464726573734f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737346696174546f6b656e3a206e65772070617573657220697320746865207a65726f2061646472657373526573637561626c653a206e6577207265736375657220697320746865207a65726f206164647265737346696174546f6b656e56325f323a204163636f756e7420697320626c61636b6c697374656446696174546f6b656e3a206d696e7420616d6f756e74206e6f742067726561746572207468616e203045524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636546696174546f6b656e3a2063616c6c6572206973206e6f7420746865206d61737465724d696e746572426c61636b6c69737461626c653a2063616c6c6572206973206e6f742074686520626c61636b6c697374657246696174546f6b656e56325f323a2042616c616e636520657863656564732028325e323535202d20312946696174546f6b656e3a206275726e20616d6f756e7420657863656564732062616c616e636546696174546f6b656e3a2063616c6c6572206973206e6f742061206d696e74657246696174546f6b656e3a206e6577206d61737465724d696e74657220697320746865207a65726f2061646472657373526573637561626c653a2063616c6c6572206973206e6f7420746865207265736375657245524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636546696174546f6b656e3a206e657720626c61636b6c697374657220697320746865207a65726f206164647265737346696174546f6b656e56323a2063616c6c6572206d7573742062652074686520706179656546696174546f6b656e3a20636f6e747261637420697320616c726561647920696e697469616c697a656445524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737346696174546f6b656e3a206d696e7420616d6f756e742065786365656473206d696e746572416c6c6f77616e63655061757361626c653a2063616c6c6572206973206e6f7420746865207061757365725361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656446696174546f6b656e3a206e6577206f776e657220697320746865207a65726f206164647265737346696174546f6b656e56323a20617574686f72697a6174696f6e2069732075736564206f722063616e63656c6564426c61636b6c69737461626c653a206e657720626c61636b6c697374657220697320746865207a65726f2061646472657373426c61636b6c69737461626c653a206163636f756e7420697320626c61636b6c697374656446696174546f6b656e56323a20617574686f72697a6174696f6e206973206578706972656445524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa26469706673582212205b9c28831ca019c704546ef047ba19de251c8493a622e0f4ae1dff3520aaae2464736f6c634300060c0033' + const bytecodeWithPlaceholder: string = + '0x60806040526001805460ff60a01b191690556000600b553480156200002357600080fd5b506200002f3362000035565b62000057565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b615f6480620000676000396000f3fe608060405234801561001057600080fd5b506004361061038e5760003560e01c806388b7ab63116101de578063b2118a8d1161010f578063dd62ed3e116100ad578063ef55bec61161007c578063ef55bec614611044578063f2fde38b146110b0578063f9f92be4146110e3578063fe575a87146111165761038e565b8063dd62ed3e14610f5c578063e3ee160e14610f97578063e5a6b10f14611003578063e94a01021461100b5761038e565b8063c2eeeebd116100e9578063c2eeeebd14610e7e578063d505accf14610e86578063d608ea6414610ee4578063d916948714610f545761038e565b8063b2118a8d14610d6b578063b7b7289914610dae578063bd10243014610e765761038e565b8063a0cc6a681161017c578063a9059cbb11610156578063a9059cbb14610c99578063aa20e1e414610cd2578063aa271e1a14610d05578063ad38bf2214610d385761038e565b8063a0cc6a6814610c1d578063a297ea5e14610c25578063a457c2d714610c605761038e565b80638da5cb5b116101b85780638da5cb5b14610bfd5780638fa74a0e14610c0557806395d89b4114610c0d5780639fd0506d14610c155761038e565b806388b7ab6314610aad5780638a6db9c314610b915780638c2a993e14610bc45761038e565b806339509351116102c3578063554bab3c1161026157806374f4f5471161023057806374f4f54714610a315780637ecebe0014610a6a5780637f2eecc314610a9d5780638456cb5914610aa55761038e565b8063554bab3c146109755780635a049a70146109a85780635c975abb146109f657806370a08231146109fe5761038e565b806342966c681161029d57806342966c6814610855578063430239b4146108725780634e44d9561461093457806354fd4d501461096d5761038e565b806339509351146107db5780633f4ba83a1461081457806340c10f191461081c5761038e565b80633092afd5116103305780633357162b1161030a5780633357162b146105ae57806335d99f351461079a5780633644e515146107cb57806338a63183146107d35761038e565b80633092afd51461055557806330adf81f14610588578063313ce567146105905761038e565b80631a8952661161036c5780631a8952661461047757806323b872dd146104ac5780632ab60045146104ef5780632fc81e09146105225761038e565b806306fdde0314610393578063095ea7b31461041057806318160ddd1461045d575b600080fd5b61039b611149565b6040805160208082528351818301528351919283929083019185019080838360005b838110156103d55781810151838201526020016103bd565b50505050905090810190601f1680156104025780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6104496004803603604081101561042657600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356111f5565b604080519115158252519081900360200190f35b610465611296565b60408051918252519081900360200190f35b6104aa6004803603602081101561048d57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff1661129c565b005b610449600480360360608110156104c257600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060400135611359565b6104aa6004803603602081101561050557600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611614565b6104aa6004803603602081101561053857600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611775565b6104496004803603602081101561056b57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166117dd565b6104656118d6565b6105986118fa565b6040805160ff9092168252519081900360200190f35b6104aa60048036036101008110156105c557600080fd5b8101906020810181356401000000008111156105e057600080fd5b8201836020820111156105f257600080fd5b8035906020019184600183028401116401000000008311171561061457600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929594936020810193503591505064010000000081111561066757600080fd5b82018360208201111561067957600080fd5b8035906020019184600183028401116401000000008311171561069b57600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092959493602081019350359150506401000000008111156106ee57600080fd5b82018360208201111561070057600080fd5b8035906020019184600183028401116401000000008311171561072257600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050813560ff16925050602081013573ffffffffffffffffffffffffffffffffffffffff90811691604081013582169160608201358116916080013516611903565b6107a2611c45565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b610465611c61565b6107a2611c70565b610449600480360360408110156107f157600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135611c8c565b6104aa611d24565b6104496004803603604081101561083257600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135611de7565b6104aa6004803603602081101561086b57600080fd5b50356121b8565b6104aa6004803603604081101561088857600080fd5b8101906020810181356401000000008111156108a357600080fd5b8201836020820111156108b557600080fd5b803590602001918460208302840111640100000000831117156108d757600080fd5b9193909290916020810190356401000000008111156108f557600080fd5b82018360208201111561090757600080fd5b8035906020019184600183028401116401000000008311171561092957600080fd5b50909250905061245a565b6104496004803603604081101561094a57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135612611565b61039b6127a4565b6104aa6004803603602081101561098b57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166127db565b6104aa600480360360a08110156109be57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060208101359060ff6040820135169060608101359060800135612942565b6104496129e0565b61046560048036036020811015610a1457600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612a01565b6104aa60048036036040811015610a4757600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135612a12565b61046560048036036020811015610a8057600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612ac1565b610465612ae9565b6104aa612b0d565b6104aa600480360360e0811015610ac357600080fd5b73ffffffffffffffffffffffffffffffffffffffff823581169260208101359091169160408201359160608101359160808201359160a08101359181019060e0810160c0820135640100000000811115610b1c57600080fd5b820183602082011115610b2e57600080fd5b80359060200191846001830284011164010000000083111715610b5057600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612be7945050505050565b61046560048036036020811015610ba757600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612d4b565b6104aa60048036036040811015610bda57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135612d73565b6107a2612e23565b6107a2612e3f565b61039b612e64565b6107a2612edd565b610465612ef9565b6104aa60048036036040811015610c3b57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020013516612f1d565b61044960048036036040811015610c7657600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813516906020013561308c565b61044960048036036040811015610caf57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135613124565b6104aa60048036036020811015610ce857600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16613287565b61044960048036036020811015610d1b57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166133ee565b6104aa60048036036020811015610d4e57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16613419565b6104aa60048036036060811015610d8157600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060400135613580565b6104aa60048036036060811015610dc457600080fd5b73ffffffffffffffffffffffffffffffffffffffff82351691602081013591810190606081016040820135640100000000811115610e0157600080fd5b820183602082011115610e1357600080fd5b80359060200191846001830284011164010000000083111715610e3557600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550613611945050505050565b6107a26136a6565b6107a26136c2565b6104aa600480360360e0811015610e9c57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c001356136e7565b6104aa60048036036020811015610efa57600080fd5b810190602081018135640100000000811115610f1557600080fd5b820183602082011115610f2757600080fd5b80359060200191846001830284011164010000000083111715610f4957600080fd5b509092509050613789565b610465613872565b61046560048036036040811015610f7257600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020013516613896565b6104aa6004803603610120811015610fae57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060408101359060608101359060808101359060a08101359060ff60c0820135169060e08101359061010001356138ce565b61039b613a36565b6104496004803603604081101561102157600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135613aaf565b6104aa600480360361012081101561105b57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060408101359060608101359060808101359060a08101359060ff60c0820135169060e0810135906101000135613ae7565b6104aa600480360360208110156110c657600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16613c42565b6104aa600480360360208110156110f957600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16613d95565b6104496004803603602081101561112c57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16613e52565b6004805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156111ed5780601f106111c2576101008083540402835291602001916111ed565b820191906000526020600020905b8154815290600101906020018083116111d057829003601f168201915b505050505081565b60015460009074010000000000000000000000000000000000000000900460ff161561128257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b61128d338484613e5d565b50600192915050565b600b5490565b60025473ffffffffffffffffffffffffffffffffffffffff16331461130c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c815260200180615be0602c913960400191505060405180910390fd5b61131581613fa4565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f117e3210bb9aa7d9baff172026820255c6f6c30ba8999d1c2fd88e2848137c4e90600090a250565b60015460009074010000000000000000000000000000000000000000900460ff16156113e657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336113f081613faf565b15611446576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b8461145081613faf565b156114a6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b846114b081613faf565b15611506576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff87166000908152600a6020908152604080832033845290915290205485111561158f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526028815260200180615cd06028913960400191505060405180910390fd5b61159a878787613fdd565b73ffffffffffffffffffffffffffffffffffffffff87166000908152600a602090815260408083203384529091529020546115d590866141a8565b73ffffffffffffffffffffffffffffffffffffffff88166000908152600a60209081526040808320338452909152902055600193505050509392505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461169a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116611706576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180615b19602a913960400191505060405180910390fd5b600e80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517fe475e580d85111348e40d8ca33cfdd74c30fe1655c2d8537a13abc10065ffa5a90600090a250565b60125460ff1660011461178757600080fd5b60006117923061421f565b905080156117a5576117a5308383613fdd565b6117ae30614269565b5050601280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166002179055565b60085460009073ffffffffffffffffffffffffffffffffffffffff163314611850576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615bb76029913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166000818152600c6020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055600d909152808220829055517fe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb666929190a2506001919050565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60065460ff1681565b60085474010000000000000000000000000000000000000000900460ff1615611977576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180615d4b602a913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff84166119e3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f815260200180615c7d602f913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8316611a4f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615af06029913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216611abb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e815260200180615cf8602e913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8116611b27576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526028815260200180615e386028913960400191505060405180910390fd5b8751611b3a9060049060208b0190615889565b508651611b4e9060059060208a0190615889565b508551611b62906007906020890190615889565b50600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff8716179055600880547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff8781169190911790925560018054821686841617905560028054909116918416919091179055611bfc81614274565b5050600880547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055505050505050565b60085473ffffffffffffffffffffffffffffffffffffffff1681565b6000611c6b6142bb565b905090565b600e5473ffffffffffffffffffffffffffffffffffffffff1690565b60015460009074010000000000000000000000000000000000000000900460ff1615611d1957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b61128d3384846143b0565b60015473ffffffffffffffffffffffffffffffffffffffff163314611d94576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180615dec6022913960400191505060405180910390fd5b600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690556040517f7805862f689e2f13df9f062ff482ad3ad112aca9e0847911ed832e158c525b3390600090a1565b60015460009074010000000000000000000000000000000000000000900460ff1615611e7457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff16611edc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180615c5c6021913960400191505060405180910390fd5b33611ee681613faf565b15611f3c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b83611f4681613faf565b15611f9c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8516612008576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180615a856023913960400191505060405180910390fd5b60008411612061576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615b686029913960400191505060405180910390fd5b336000908152600d6020526040902054808511156120ca576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e815260200180615dbe602e913960400191505060405180910390fd5b600b546120d790866143fa565b600b556120f6866120f1876120eb8361421f565b906143fa565b614475565b61210081866141a8565b336000818152600d6020908152604091829020939093558051888152905173ffffffffffffffffffffffffffffffffffffffff8a16937fab8530f87dc9b59234c4623bf917212bb2536d647574c8e7e5da92c2ede0c9f8928290030190a360408051868152905173ffffffffffffffffffffffffffffffffffffffff8816916000917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a350600195945050505050565b60015474010000000000000000000000000000000000000000900460ff161561224257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff166122aa576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180615c5c6021913960400191505060405180910390fd5b336122b481613faf565b1561230a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b60006123153361421f565b905060008311612370576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615a5c6029913960400191505060405180910390fd5b828110156123c9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180615c366026913960400191505060405180910390fd5b600b546123d690846141a8565b600b556123e7336120f183866141a8565b60408051848152905133917fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5919081900360200190a260408051848152905160009133917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a3505050565b60125460ff1660021461246c57600080fd5b61247860058383615907565b5060005b838110156125ba576003600086868481811061249457fe5b6020908102929092013573ffffffffffffffffffffffffffffffffffffffff168352508101919091526040016000205460ff1661251c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603d8152602001806159a9603d913960400191505060405180910390fd5b61254d85858381811061252b57fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff16614269565b6003600086868481811061255d57fe5b6020908102929092013573ffffffffffffffffffffffffffffffffffffffff1683525081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905560010161247c565b506125c430614269565b505030600090815260036020819052604090912080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009081169091556012805490911690911790555050565b60015460009074010000000000000000000000000000000000000000900460ff161561269e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b60085473ffffffffffffffffffffffffffffffffffffffff16331461270e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615bb76029913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff83166000818152600c6020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055600d825291829020859055815185815291517f46980fca912ef9bcdbd36877427b6b90e860769f604e89c0e67720cece530d209281900390910190a250600192915050565b60408051808201909152600181527f3200000000000000000000000000000000000000000000000000000000000000602082015290565b60005473ffffffffffffffffffffffffffffffffffffffff16331461286157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff81166128cd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526028815260200180615a096028913960400191505060405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691909117918290556040519116907fb80482a293ca2e013eda8683c9bd7fc8347cfdaeea5ede58cba46df502c2a60490600090a250565b60015474010000000000000000000000000000000000000000900460ff16156129cc57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6129d98585858585614576565b5050505050565b60015474010000000000000000000000000000000000000000900460ff1681565b6000612a0c8261421f565b92915050565b612a1a612e3f565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612ab357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4f4e4c595f474154455741590000000000000000000000000000000000000000604482015290519081900360640190fd5b612abd82826145b6565b5050565b73ffffffffffffffffffffffffffffffffffffffff1660009081526011602052604090205490565b7fd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de881565b60015473ffffffffffffffffffffffffffffffffffffffff163314612b7d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180615dec6022913960400191505060405180910390fd5b600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790556040517f6985a02210a168e66602d3235cb6db0e70f92b3ba4d376a33c0f3d9434bff62590600090a1565b60015474010000000000000000000000000000000000000000900460ff1615612c7157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b86612c7b81613faf565b15612cd1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b86612cdb81613faf565b15612d31576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b612d408989898989898961487c565b505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff166000908152600d602052604090205490565b612d7b612e3f565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612e1457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4f4e4c595f474154455741590000000000000000000000000000000000000000604482015290519081900360640190fd5b612e1e8282611de7565b505050565b60005473ffffffffffffffffffffffffffffffffffffffff1690565b7fdbf6298cab77bb44ebfd5abb25ed2538c2a55f7404c47e83e6531361fba28c245490565b6005805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156111ed5780601f106111c2576101008083540402835291602001916111ed565b60015473ffffffffffffffffffffffffffffffffffffffff1681565b7f7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a226781565b60125460ff16600314612f2f57600080fd5b73ffffffffffffffffffffffffffffffffffffffff8216612fb157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f494e56414c49445f474154455741590000000000000000000000000000000000604482015290519081900360640190fd5b6000612fbb612e3f565b73ffffffffffffffffffffffffffffffffffffffff161461303d57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f414c52454144595f494e49540000000000000000000000000000000000000000604482015290519081900360640190fd5b817fdbf6298cab77bb44ebfd5abb25ed2538c2a55f7404c47e83e6531361fba28c2455807f54352c0d7cc5793352a36344bfdcdcf68ba6258544ce1aed71f60a74d882c19155612abd8261499d565b60015460009074010000000000000000000000000000000000000000900460ff161561311957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b61128d338484614a52565b60015460009074010000000000000000000000000000000000000000900460ff16156131b157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336131bb81613faf565b15613211576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b8361321b81613faf565b15613271576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b61327c338686613fdd565b506001949350505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461330d57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116613379576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f815260200180615c7d602f913960400191505060405180910390fd5b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691909117918290556040519116907fdb66dfa9c6b8f5226fe9aac7e51897ae8ee94ac31dc70bb6c9900b2574b707e690600090a250565b73ffffffffffffffffffffffffffffffffffffffff166000908152600c602052604090205460ff1690565b60005473ffffffffffffffffffffffffffffffffffffffff16331461349f57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff811661350b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526032815260200180615e8e6032913960400191505060405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691909117918290556040519116907fc67398012c111ce95ecb7429b933096c977380ee6c421175a71a4a4c6c88c06e90600090a250565b600e5473ffffffffffffffffffffffffffffffffffffffff1633146135f0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526024815260200180615cac6024913960400191505060405180910390fd5b612e1e73ffffffffffffffffffffffffffffffffffffffff84168383614aae565b60015474010000000000000000000000000000000000000000900460ff161561369b57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b612e1e838383614b3b565b60025473ffffffffffffffffffffffffffffffffffffffff1681565b7f54352c0d7cc5793352a36344bfdcdcf68ba6258544ce1aed71f60a74d882c1915490565b60015474010000000000000000000000000000000000000000900460ff161561377157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b61378087878787878787614c45565b50505050505050565b60085474010000000000000000000000000000000000000000900460ff1680156137b6575060125460ff16155b6137bf57600080fd5b6137cb60048383615907565b5061384082828080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600181527f320000000000000000000000000000000000000000000000000000000000000060208201529150614c879050565b600f555050601280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b7f158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a159742981565b73ffffffffffffffffffffffffffffffffffffffff9182166000908152600a6020908152604080832093909416825291909152205490565b60015474010000000000000000000000000000000000000000900460ff161561395857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b8861396281613faf565b156139b8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b886139c281613faf565b15613a18576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b613a298b8b8b8b8b8b8b8b8b614c9d565b5050505050505050505050565b6007805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156111ed5780601f106111c2576101008083540402835291602001916111ed565b73ffffffffffffffffffffffffffffffffffffffff919091166000908152601060209081526040808320938352929052205460ff1690565b60015474010000000000000000000000000000000000000000900460ff1615613b7157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b88613b7b81613faf565b15613bd1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b88613bdb81613faf565b15613c31576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b613a298b8b8b8b8b8b8b8b8b614ce1565b60005473ffffffffffffffffffffffffffffffffffffffff163314613cc857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116613d34576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180615aa86026913960400191505060405180910390fd5b6000546040805173ffffffffffffffffffffffffffffffffffffffff9283168152918316602083015280517f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09281900390910190a1613d9281614274565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314613e05576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c815260200180615be0602c913960400191505060405180910390fd5b613e0e81614269565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fffa4e6181777692565cf28528fc88fd1516ea86b56da075235fa575af6a4b85590600090a250565b6000612a0c82613faf565b73ffffffffffffffffffffffffffffffffffffffff8316613ec9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526024815260200180615d9a6024913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216613f35576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180615ace6022913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8084166000818152600a6020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b613d92816000614d25565b73ffffffffffffffffffffffffffffffffffffffff1660009081526009602052604090205460ff1c60011490565b73ffffffffffffffffffffffffffffffffffffffff8316614049576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615d756025913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166140b5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806159e66023913960400191505060405180910390fd5b6140be8361421f565b811115614116576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180615b916026913960400191505060405180910390fd5b61412d836120f1836141278761421f565b906141a8565b61413e826120f1836120eb8661421f565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b60008282111561421957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b73ffffffffffffffffffffffffffffffffffffffff166000908152600960205260409020547f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690565b613d92816001614d25565b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6004805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152600093611c6b93919290918301828280156143685780601f1061433d57610100808354040283529160200191614368565b820191906000526020600020905b81548152906001019060200180831161434b57829003601f168201915b50505050506040518060400160405280600181526020017f32000000000000000000000000000000000000000000000000000000000000008152506143ab614dae565b614db2565b73ffffffffffffffffffffffffffffffffffffffff8084166000908152600a6020908152604080832093861683529290522054612e1e90849084906143f590856143fa565b613e5d565b60008282018381101561446e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8111156144ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180615c0c602a913960400191505060405180910390fd5b6144f782613faf565b1561454d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615b436025913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff909116600090815260096020526040902055565b6129d98585848487604051602001808481526020018381526020018260ff1660f81b81526001019350505050604051602081830303815290604052614b3b565b60015474010000000000000000000000000000000000000000900460ff161561464057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff166146a8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180615c5c6021913960400191505060405180910390fd5b816146b281613faf565b15614708576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b60006147138461421f565b90506000831161476e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615a5c6029913960400191505060405180910390fd5b828110156147c7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180615c366026913960400191505060405180910390fd5b600b805484900390556147dc84848303614475565b60408051848152905173ffffffffffffffffffffffffffffffffffffffff8616917fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5919081900360200190a260408051848152905160009173ffffffffffffffffffffffffffffffffffffffff8716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a350505050565b73ffffffffffffffffffffffffffffffffffffffff861633146148ea576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615d266025913960400191505060405180910390fd5b6148f687838686614e26565b604080517fd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de860208083019190915273ffffffffffffffffffffffffffffffffffffffff808b1683850152891660608301526080820188905260a0820187905260c0820186905260e080830186905283518084039091018152610100909201909252805191012061498890889083614ee6565b6149928783615064565b613780878787613fdd565b73ffffffffffffffffffffffffffffffffffffffff81166000818152600c6020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055600d8252918290207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90819055825181815292519093927f46980fca912ef9bcdbd36877427b6b90e860769f604e89c0e67720cece530d2092908290030190a25050565b612e1e83836143f584604051806060016040528060258152602001615f0a6025913973ffffffffffffffffffffffffffffffffffffffff808a166000908152600a60209081526040808320938c168352929052205491906150e9565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052612e1e90849061519a565b614b458383615272565b614bbf837f158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a159742960001b8585604051602001808481526020018373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200193505050506040516020818303038152906040528051906020012083614ee6565b73ffffffffffffffffffffffffffffffffffffffff8316600081815260106020908152604080832086845290915280822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055518492917f1cdd46ff242716cdaa72d159d339a485b3438398348d68f09d7c8c0a59353d8191a3505050565b61378087878787868689604051602001808481526020018381526020018260ff1660f81b815260010193505050506040516020818303038152906040526152fc565b600046614c95848483614db2565b949350505050565b612d4089898989898988888b604051602001808481526020018381526020018260ff1660f81b815260010193505050506040516020818303038152906040526155c0565b612d4089898989898988888b604051602001808481526020018381526020018260ff1660f81b8152600101935050505060405160208183030381529060405261487c565b80614d3857614d338261421f565b614d81565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600960205260409020547f8000000000000000000000000000000000000000000000000000000000000000175b73ffffffffffffffffffffffffffffffffffffffff90921660009081526009602052604090209190915550565b4690565b8251602093840120825192840192909220604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8187015280820194909452606084019190915260808301919091523060a0808401919091528151808403909101815260c09092019052805191012090565b814211614e7e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b815260200180615a31602b913960400191505060405180910390fd5b804210614ed6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ee56025913960400191505060405180910390fd5b614ee08484615272565b50505050565b73__$715109b5d747ea58b675c6ea3f0dba8c60$__636ccea65284614f12614f0c6142bb565b8661565e565b846040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff16815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015614f81578181015183820152602001614f69565b50505050905090810190601f168015614fae5780820380516001836020036101000a031916815260200191505b5094505050505060206040518083038186803b158015614fcd57600080fd5b505af4158015614fe1573d6000803e3d6000fd5b505050506040513d6020811015614ff757600080fd5b5051612e1e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f46696174546f6b656e56323a20696e76616c6964207369676e61747572650000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8216600081815260106020908152604080832085845290915280822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055518392917f98de503528ee59b575ef0c0a2576a82497bfc029a5685b209e9ec333479b10a591a35050565b60008184841115615192576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561515757818101518382015260200161513f565b50505050905090810190601f1680156151845780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b60606151fc826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166156989092919063ffffffff16565b805190915015612e1e5780806020019051602081101561521b57600080fd5b5051612e1e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180615e0e602a913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216600090815260106020908152604080832084845290915290205460ff1615612abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e815260200180615e60602e913960400191505060405180910390fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82148061532a5750428210155b61539557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f46696174546f6b656e56323a207065726d697420697320657870697265640000604482015290519081900360640190fd5b600061543d6153a26142bb565b73ffffffffffffffffffffffffffffffffffffffff80891660008181526011602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98184015280840194909452938b166060840152608083018a905260a083019390935260c08083018990528151808403909101815260e09092019052805191012061565e565b905073__$715109b5d747ea58b675c6ea3f0dba8c60$__636ccea6528783856040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff16815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b838110156154ca5781810151838201526020016154b2565b50505050905090810190601f1680156154f75780820380516001836020036101000a031916815260200191505b5094505050505060206040518083038186803b15801561551657600080fd5b505af415801561552a573d6000803e3d6000fd5b505050506040513d602081101561554057600080fd5b50516155ad57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f454950323631323a20696e76616c6964207369676e6174757265000000000000604482015290519081900360640190fd5b6155b8868686613e5d565b505050505050565b6155cc87838686614e26565b604080517f7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a226760208083019190915273ffffffffffffffffffffffffffffffffffffffff808b1683850152891660608301526080820188905260a0820187905260c0820186905260e080830186905283518084039091018152610100909201909252805191012061498890889083614ee6565b6040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b6060614c958484600085856156ac85615803565b61571757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b6020831061578157805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101615744565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d80600081146157e3576040519150601f19603f3d011682016040523d82523d6000602084013e6157e8565b606091505b50915091506157f8828286615809565b979650505050505050565b3b151590565b6060831561581857508161446e565b8251156158285782518084602001fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181815284516024840152845185939192839260440191908501908083836000831561515757818101518382015260200161513f565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106158ca57805160ff19168380011785556158f7565b828001600101855582156158f7579182015b828111156158f75782518255916020019190600101906158dc565b50615903929150615993565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10615966578280017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008235161785556158f7565b828001600101855582156158f7579182015b828111156158f7578235825591602001919060010190615978565b5b80821115615903576000815560010161599456fe46696174546f6b656e56325f323a20426c61636b6c697374696e672070726576696f75736c7920756e626c61636b6c6973746564206163636f756e742145524332303a207472616e7366657220746f20746865207a65726f20616464726573735061757361626c653a206e65772070617573657220697320746865207a65726f206164647265737346696174546f6b656e56323a20617574686f72697a6174696f6e206973206e6f74207965742076616c696446696174546f6b656e3a206275726e20616d6f756e74206e6f742067726561746572207468616e203046696174546f6b656e3a206d696e7420746f20746865207a65726f20616464726573734f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737346696174546f6b656e3a206e65772070617573657220697320746865207a65726f2061646472657373526573637561626c653a206e6577207265736375657220697320746865207a65726f206164647265737346696174546f6b656e56325f323a204163636f756e7420697320626c61636b6c697374656446696174546f6b656e3a206d696e7420616d6f756e74206e6f742067726561746572207468616e203045524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636546696174546f6b656e3a2063616c6c6572206973206e6f7420746865206d61737465724d696e746572426c61636b6c69737461626c653a2063616c6c6572206973206e6f742074686520626c61636b6c697374657246696174546f6b656e56325f323a2042616c616e636520657863656564732028325e323535202d20312946696174546f6b656e3a206275726e20616d6f756e7420657863656564732062616c616e636546696174546f6b656e3a2063616c6c6572206973206e6f742061206d696e74657246696174546f6b656e3a206e6577206d61737465724d696e74657220697320746865207a65726f2061646472657373526573637561626c653a2063616c6c6572206973206e6f7420746865207265736375657245524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636546696174546f6b656e3a206e657720626c61636b6c697374657220697320746865207a65726f206164647265737346696174546f6b656e56323a2063616c6c6572206d7573742062652074686520706179656546696174546f6b656e3a20636f6e747261637420697320616c726561647920696e697469616c697a656445524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737346696174546f6b656e3a206d696e7420616d6f756e742065786365656473206d696e746572416c6c6f77616e63655061757361626c653a2063616c6c6572206973206e6f7420746865207061757365725361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656446696174546f6b656e3a206e6577206f776e657220697320746865207a65726f206164647265737346696174546f6b656e56323a20617574686f72697a6174696f6e2069732075736564206f722063616e63656c6564426c61636b6c69737461626c653a206e657720626c61636b6c697374657220697320746865207a65726f2061646472657373426c61636b6c69737461626c653a206163636f756e7420697320626c61636b6c697374656446696174546f6b656e56323a20617574686f72697a6174696f6e206973206578706972656445524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122038d731178b4dd0e027fef834bc8ab43420dd9ff02d6c94216b764f26362e531d64736f6c634300060c0033' const placeholder = '__$715109b5d747ea58b675c6ea3f0dba8c60$__' + + const libAddressStripped = sigCheckerLib.address.replace(/^0x/, '') const bridgedUsdcLogicBytecode = bytecodeWithPlaceholder .split(placeholder) - .join(sigCheckerLib.address.replace(/^0x/, '')) + .join(libAddressStripped) // deploy bridged usdc logic const bridgedUsdcLogicFactory = new ethers.ContractFactory( diff --git a/test-foundry/L2USDCCustomGateway.t.sol b/test-foundry/L2USDCCustomGateway.t.sol index 1f25c2963b..33c698701a 100644 --- a/test-foundry/L2USDCCustomGateway.t.sol +++ b/test-foundry/L2USDCCustomGateway.t.sol @@ -278,21 +278,3 @@ contract L2USDCCustomGatewayTest is L2ArbitrumGatewayTest { //// event WithdrawalsPaused(); } - -interface FiatTokenArbitrumOrbitV2_2 { - function initialize( - string memory tokenName, - string memory tokenSymbol, - string memory tokenCurrency, - uint8 tokenDecimals, - address newMasterMinter, - address newPauser, - address newBlacklister, - address newOwner - ) external; - function initializeV2(string calldata newName) external; - function initializeV2_1(address lostAndFound) external; - function initializeV2_2(address[] calldata accountsToBlacklist, string calldata newSymbol) - external; - function initializeArbitrumOrbit(address _l2Gateway, address _l1Token) external; -} diff --git a/test-foundry/util/TestUtil.sol b/test-foundry/util/TestUtil.sol index 05375bac91..348781329a 100644 --- a/test-foundry/util/TestUtil.sol +++ b/test-foundry/util/TestUtil.sol @@ -26,13 +26,13 @@ library TestUtil { // insert lib address into bytecode bytes memory b1 = - hex"60806040526001805460ff60a01b191690556000600b553480156200002357600080fd5b506200002f3362000035565b62000057565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b61632680620000676000396000f3fe608060405234801561001057600080fd5b50600436106103a45760003560e01c80638a6db9c3116101e9578063b7b728991161010f578063dd62ed3e116100ad578063ef55bec61161007c578063ef55bec614611216578063f2fde38b14611282578063f9f92be4146112b5578063fe575a87146112e8576103a4565b8063dd62ed3e1461112e578063e3ee160e14611169578063e5a6b10f146111d5578063e94a0102146111dd576103a4565b8063cf092995116100e9578063cf09299514610f74578063d505accf14611058578063d608ea64146110b6578063d916948714611126576103a4565b8063b7b7289914610e9c578063bd10243014610f64578063c2eeeebd14610f6c576103a4565b8063a0cc6a6811610187578063aa20e1e411610156578063aa20e1e414610dc0578063aa271e1a14610df3578063ad38bf2214610e26578063b2118a8d14610e59576103a4565b8063a0cc6a6814610d0b578063a297ea5e14610d13578063a457c2d714610d4e578063a9059cbb14610d87576103a4565b80638fa74a0e116101c35780638fa74a0e14610c1b57806395d89b4114610c235780639fd0506d14610c2b5780639fd5a6cf14610c33576103a4565b80638a6db9c314610ba75780638c2a993e14610bda5780638da5cb5b14610c13576103a4565b80633f4ba83a116102ce5780635a049a701161026c5780637ecebe001161023b5780637ecebe0014610a805780637f2eecc314610ab35780638456cb5914610abb57806388b7ab6314610ac3576103a4565b80635a049a70146109be5780635c975abb14610a0c57806370a0823114610a1457806374f4f54714610a47576103a4565b8063430239b4116102a8578063430239b4146108885780634e44d9561461094a57806354fd4d5014610983578063554bab3c1461098b576103a4565b80633f4ba83a1461082a57806340c10f191461083257806342966c681461086b576103a4565b80633092afd51161034657806335d99f351161031557806335d99f35146107b05780633644e515146107e157806338a63183146107e957806339509351146107f1576103a4565b80633092afd51461056b57806330adf81f1461059e578063313ce567146105a65780633357162b146105c4576103a4565b80631a895266116103825780631a8952661461048d57806323b872dd146104c25780632ab60045146105055780632fc81e0914610538576103a4565b806306fdde03146103a9578063095ea7b31461042657806318160ddd14610473575b600080fd5b6103b161131b565b6040805160208082528351818301528351919283929083019185019080838360005b838110156103eb5781810151838201526020016103d3565b50505050905090810190601f1680156104185780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61045f6004803603604081101561043c57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356113c7565b604080519115158252519081900360200190f35b61047b611468565b60408051918252519081900360200190f35b6104c0600480360360208110156104a357600080fd5b503573ffffffffffffffffffffffffffffffffffffffff1661146e565b005b61045f600480360360608110156104d857600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020810135909116906040013561152b565b6104c06004803603602081101561051b57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166117e6565b6104c06004803603602081101561054e57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611947565b61045f6004803603602081101561058157600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166119af565b61047b611aa8565b6105ae611acc565b6040805160ff9092168252519081900360200190f35b6104c060048036036101008110156105db57600080fd5b8101906020810181356401000000008111156105f657600080fd5b82018360208201111561060857600080fd5b8035906020019184600183028401116401000000008311171561062a57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929594936020810193503591505064010000000081111561067d57600080fd5b82018360208201111561068f57600080fd5b803590602001918460018302840111640100000000831117156106b157600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929594936020810193503591505064010000000081111561070457600080fd5b82018360208201111561071657600080fd5b8035906020019184600183028401116401000000008311171561073857600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050813560ff16925050602081013573ffffffffffffffffffffffffffffffffffffffff90811691604081013582169160608201358116916080013516611ad5565b6107b8611e17565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b61047b611e33565b6107b8611e42565b61045f6004803603604081101561080757600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135611e5e565b6104c0611ef6565b61045f6004803603604081101561084857600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135611fb9565b6104c06004803603602081101561088157600080fd5b503561238a565b6104c06004803603604081101561089e57600080fd5b8101906020810181356401000000008111156108b957600080fd5b8201836020820111156108cb57600080fd5b803590602001918460208302840111640100000000831117156108ed57600080fd5b91939092909160208101903564010000000081111561090b57600080fd5b82018360208201111561091d57600080fd5b8035906020019184600183028401116401000000008311171561093f57600080fd5b50909250905061262c565b61045f6004803603604081101561096057600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356127e3565b6103b1612976565b6104c0600480360360208110156109a157600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166129ad565b6104c0600480360360a08110156109d457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060208101359060ff6040820135169060608101359060800135612b14565b61045f612bb2565b61047b60048036036020811015610a2a57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612bd3565b6104c060048036036040811015610a5d57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135612be4565b61047b60048036036020811015610a9657600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612c93565b61047b612cbb565b6104c0612cdf565b6104c0600480360360e0811015610ad957600080fd5b73ffffffffffffffffffffffffffffffffffffffff823581169260208101359091169160408201359160608101359160808201359160a08101359181019060e0810160c0820135640100000000811115610b3257600080fd5b820183602082011115610b4457600080fd5b80359060200191846001830284011164010000000083111715610b6657600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612db9945050505050565b61047b60048036036020811015610bbd57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612f1d565b6104c060048036036040811015610bf057600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135612f45565b6107b8612ff5565b6107b8613011565b6103b1613036565b6107b86130af565b6104c0600480360360a0811015610c4957600080fd5b73ffffffffffffffffffffffffffffffffffffffff823581169260208101359091169160408201359160608101359181019060a081016080820135640100000000811115610c9657600080fd5b820183602082011115610ca857600080fd5b80359060200191846001830284011164010000000083111715610cca57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506130cb945050505050565b61047b613162565b6104c060048036036040811015610d2957600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020013516613186565b61045f60048036036040811015610d6457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356132f5565b61045f60048036036040811015610d9d57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813516906020013561338d565b6104c060048036036020811015610dd657600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166134f0565b61045f60048036036020811015610e0957600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16613657565b6104c060048036036020811015610e3c57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16613682565b6104c060048036036060811015610e6f57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135811691602081013590911690604001356137e9565b6104c060048036036060811015610eb257600080fd5b73ffffffffffffffffffffffffffffffffffffffff82351691602081013591810190606081016040820135640100000000811115610eef57600080fd5b820183602082011115610f0157600080fd5b80359060200191846001830284011164010000000083111715610f2357600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092955061387a945050505050565b6107b861390f565b6107b861392b565b6104c0600480360360e0811015610f8a57600080fd5b73ffffffffffffffffffffffffffffffffffffffff823581169260208101359091169160408201359160608101359160808201359160a08101359181019060e0810160c0820135640100000000811115610fe357600080fd5b820183602082011115610ff557600080fd5b8035906020019184600183028401116401000000008311171561101757600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550613950945050505050565b6104c0600480360360e081101561106e57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c00135613aa9565b6104c0600480360360208110156110cc57600080fd5b8101906020810181356401000000008111156110e757600080fd5b8201836020820111156110f957600080fd5b8035906020019184600183028401116401000000008311171561111b57600080fd5b509092509050613b4b565b61047b613c34565b61047b6004803603604081101561114457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020013516613c58565b6104c0600480360361012081101561118057600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060408101359060608101359060808101359060a08101359060ff60c0820135169060e0810135906101000135613c90565b6103b1613df8565b61045f600480360360408110156111f357600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135613e71565b6104c0600480360361012081101561122d57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060408101359060608101359060808101359060a08101359060ff60c0820135169060e0810135906101000135613ea9565b6104c06004803603602081101561129857600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16614004565b6104c0600480360360208110156112cb57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16614157565b61045f600480360360208110156112fe57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16614214565b6004805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156113bf5780601f10611394576101008083540402835291602001916113bf565b820191906000526020600020905b8154815290600101906020018083116113a257829003601f168201915b505050505081565b60015460009074010000000000000000000000000000000000000000900460ff161561145457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b61145f33848461421f565b50600192915050565b600b5490565b60025473ffffffffffffffffffffffffffffffffffffffff1633146114de576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c815260200180615fa2602c913960400191505060405180910390fd5b6114e781614366565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f117e3210bb9aa7d9baff172026820255c6f6c30ba8999d1c2fd88e2848137c4e90600090a250565b60015460009074010000000000000000000000000000000000000000900460ff16156115b857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336115c281614371565b15611618576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b8461162281614371565b15611678576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b8461168281614371565b156116d8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff87166000908152600a60209081526040808320338452909152902054851115611761576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260288152602001806160926028913960400191505060405180910390fd5b61176c87878761439f565b73ffffffffffffffffffffffffffffffffffffffff87166000908152600a602090815260408083203384529091529020546117a7908661456a565b73ffffffffffffffffffffffffffffffffffffffff88166000908152600a60209081526040808320338452909152902055600193505050509392505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461186c57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff81166118d8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180615edb602a913960400191505060405180910390fd5b600e80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517fe475e580d85111348e40d8ca33cfdd74c30fe1655c2d8537a13abc10065ffa5a90600090a250565b60125460ff1660011461195957600080fd5b6000611964306145e1565b905080156119775761197730838361439f565b6119803061462b565b5050601280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166002179055565b60085460009073ffffffffffffffffffffffffffffffffffffffff163314611a22576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615f796029913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166000818152600c6020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055600d909152808220829055517fe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb666929190a2506001919050565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60065460ff1681565b60085474010000000000000000000000000000000000000000900460ff1615611b49576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a81526020018061610d602a913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8416611bb5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f81526020018061603f602f913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8316611c21576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615eb26029913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216611c8d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e8152602001806160ba602e913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8116611cf9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260288152602001806161fa6028913960400191505060405180910390fd5b8751611d0c9060049060208b0190615c4b565b508651611d209060059060208a0190615c4b565b508551611d34906007906020890190615c4b565b50600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff8716179055600880547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff8781169190911790925560018054821686841617905560028054909116918416919091179055611dce81614636565b5050600880547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055505050505050565b60085473ffffffffffffffffffffffffffffffffffffffff1681565b6000611e3d61467d565b905090565b600e5473ffffffffffffffffffffffffffffffffffffffff1690565b60015460009074010000000000000000000000000000000000000000900460ff1615611eeb57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b61145f338484614772565b60015473ffffffffffffffffffffffffffffffffffffffff163314611f66576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806161ae6022913960400191505060405180910390fd5b600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690556040517f7805862f689e2f13df9f062ff482ad3ad112aca9e0847911ed832e158c525b3390600090a1565b60015460009074010000000000000000000000000000000000000000900460ff161561204657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff166120ae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602181526020018061601e6021913960400191505060405180910390fd5b336120b881614371565b1561210e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b8361211881614371565b1561216e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff85166121da576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180615e476023913960400191505060405180910390fd5b60008411612233576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615f2a6029913960400191505060405180910390fd5b336000908152600d60205260409020548085111561229c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e815260200180616180602e913960400191505060405180910390fd5b600b546122a990866147bc565b600b556122c8866122c3876122bd836145e1565b906147bc565b614837565b6122d2818661456a565b336000818152600d6020908152604091829020939093558051888152905173ffffffffffffffffffffffffffffffffffffffff8a16937fab8530f87dc9b59234c4623bf917212bb2536d647574c8e7e5da92c2ede0c9f8928290030190a360408051868152905173ffffffffffffffffffffffffffffffffffffffff8816916000917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a350600195945050505050565b60015474010000000000000000000000000000000000000000900460ff161561241457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff1661247c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602181526020018061601e6021913960400191505060405180910390fd5b3361248681614371565b156124dc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b60006124e7336145e1565b905060008311612542576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615e1e6029913960400191505060405180910390fd5b8281101561259b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180615ff86026913960400191505060405180910390fd5b600b546125a8908461456a565b600b556125b9336122c3838661456a565b60408051848152905133917fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5919081900360200190a260408051848152905160009133917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a3505050565b60125460ff1660021461263e57600080fd5b61264a60058383615cc9565b5060005b8381101561278c576003600086868481811061266657fe5b6020908102929092013573ffffffffffffffffffffffffffffffffffffffff168352508101919091526040016000205460ff166126ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603d815260200180615d6b603d913960400191505060405180910390fd5b61271f8585838181106126fd57fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff1661462b565b6003600086868481811061272f57fe5b6020908102929092013573ffffffffffffffffffffffffffffffffffffffff1683525081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905560010161264e565b506127963061462b565b505030600090815260036020819052604090912080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009081169091556012805490911690911790555050565b60015460009074010000000000000000000000000000000000000000900460ff161561287057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b60085473ffffffffffffffffffffffffffffffffffffffff1633146128e0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615f796029913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff83166000818152600c6020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055600d825291829020859055815185815291517f46980fca912ef9bcdbd36877427b6b90e860769f604e89c0e67720cece530d209281900390910190a250600192915050565b60408051808201909152600181527f3200000000000000000000000000000000000000000000000000000000000000602082015290565b60005473ffffffffffffffffffffffffffffffffffffffff163314612a3357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116612a9f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526028815260200180615dcb6028913960400191505060405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691909117918290556040519116907fb80482a293ca2e013eda8683c9bd7fc8347cfdaeea5ede58cba46df502c2a60490600090a250565b60015474010000000000000000000000000000000000000000900460ff1615612b9e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b612bab8585858585614938565b5050505050565b60015474010000000000000000000000000000000000000000900460ff1681565b6000612bde826145e1565b92915050565b612bec613011565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612c8557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4f4e4c595f474154455741590000000000000000000000000000000000000000604482015290519081900360640190fd5b612c8f8282614978565b5050565b73ffffffffffffffffffffffffffffffffffffffff1660009081526011602052604090205490565b7fd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de881565b60015473ffffffffffffffffffffffffffffffffffffffff163314612d4f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806161ae6022913960400191505060405180910390fd5b600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790556040517f6985a02210a168e66602d3235cb6db0e70f92b3ba4d376a33c0f3d9434bff62590600090a1565b60015474010000000000000000000000000000000000000000900460ff1615612e4357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b86612e4d81614371565b15612ea3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b86612ead81614371565b15612f03576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b612f1289898989898989614c3e565b505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff166000908152600d602052604090205490565b612f4d613011565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612fe657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4f4e4c595f474154455741590000000000000000000000000000000000000000604482015290519081900360640190fd5b612ff08282611fb9565b505050565b60005473ffffffffffffffffffffffffffffffffffffffff1690565b7fdbf6298cab77bb44ebfd5abb25ed2538c2a55f7404c47e83e6531361fba28c245490565b6005805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156113bf5780601f10611394576101008083540402835291602001916113bf565b60015473ffffffffffffffffffffffffffffffffffffffff1681565b60015474010000000000000000000000000000000000000000900460ff161561315557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b612bab8585858585614d5f565b7f7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a226781565b60125460ff1660031461319857600080fd5b73ffffffffffffffffffffffffffffffffffffffff821661321a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f494e56414c49445f474154455741590000000000000000000000000000000000604482015290519081900360640190fd5b6000613224613011565b73ffffffffffffffffffffffffffffffffffffffff16146132a657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f414c52454144595f494e49540000000000000000000000000000000000000000604482015290519081900360640190fd5b817fdbf6298cab77bb44ebfd5abb25ed2538c2a55f7404c47e83e6531361fba28c2455807f54352c0d7cc5793352a36344bfdcdcf68ba6258544ce1aed71f60a74d882c19155612c8f82615023565b60015460009074010000000000000000000000000000000000000000900460ff161561338257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b61145f3384846150d8565b60015460009074010000000000000000000000000000000000000000900460ff161561341a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b3361342481614371565b1561347a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b8361348481614371565b156134da576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b6134e533868661439f565b506001949350505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461357657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff81166135e2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f81526020018061603f602f913960400191505060405180910390fd5b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691909117918290556040519116907fdb66dfa9c6b8f5226fe9aac7e51897ae8ee94ac31dc70bb6c9900b2574b707e690600090a250565b73ffffffffffffffffffffffffffffffffffffffff166000908152600c602052604090205460ff1690565b60005473ffffffffffffffffffffffffffffffffffffffff16331461370857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116613774576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260328152602001806162506032913960400191505060405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691909117918290556040519116907fc67398012c111ce95ecb7429b933096c977380ee6c421175a71a4a4c6c88c06e90600090a250565b600e5473ffffffffffffffffffffffffffffffffffffffff163314613859576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602481526020018061606e6024913960400191505060405180910390fd5b612ff073ffffffffffffffffffffffffffffffffffffffff84168383615134565b60015474010000000000000000000000000000000000000000900460ff161561390457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b612ff08383836151c1565b60025473ffffffffffffffffffffffffffffffffffffffff1681565b7f54352c0d7cc5793352a36344bfdcdcf68ba6258544ce1aed71f60a74d882c1915490565b60015474010000000000000000000000000000000000000000900460ff16156139da57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b866139e481614371565b15613a3a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b86613a4481614371565b15613a9a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b612f12898989898989896152cb565b60015474010000000000000000000000000000000000000000900460ff1615613b3357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b613b4287878787878787615369565b50505050505050565b60085474010000000000000000000000000000000000000000900460ff168015613b78575060125460ff16155b613b8157600080fd5b613b8d60048383615cc9565b50613c0282828080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600181527f3200000000000000000000000000000000000000000000000000000000000000602082015291506153ab9050565b600f555050601280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b7f158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a159742981565b73ffffffffffffffffffffffffffffffffffffffff9182166000908152600a6020908152604080832093909416825291909152205490565b60015474010000000000000000000000000000000000000000900460ff1615613d1a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b88613d2481614371565b15613d7a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b88613d8481614371565b15613dda576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b613deb8b8b8b8b8b8b8b8b8b6153c1565b5050505050505050505050565b6007805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156113bf5780601f10611394576101008083540402835291602001916113bf565b73ffffffffffffffffffffffffffffffffffffffff919091166000908152601060209081526040808320938352929052205460ff1690565b60015474010000000000000000000000000000000000000000900460ff1615613f3357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b88613f3d81614371565b15613f93576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b88613f9d81614371565b15613ff3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b613deb8b8b8b8b8b8b8b8b8b615405565b60005473ffffffffffffffffffffffffffffffffffffffff16331461408a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff81166140f6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180615e6a6026913960400191505060405180910390fd5b6000546040805173ffffffffffffffffffffffffffffffffffffffff9283168152918316602083015280517f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09281900390910190a161415481614636565b50565b60025473ffffffffffffffffffffffffffffffffffffffff1633146141c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c815260200180615fa2602c913960400191505060405180910390fd5b6141d08161462b565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fffa4e6181777692565cf28528fc88fd1516ea86b56da075235fa575af6a4b85590600090a250565b6000612bde82614371565b73ffffffffffffffffffffffffffffffffffffffff831661428b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602481526020018061615c6024913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166142f7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180615e906022913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8084166000818152600a6020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b614154816000615449565b73ffffffffffffffffffffffffffffffffffffffff1660009081526009602052604090205460ff1c60011490565b73ffffffffffffffffffffffffffffffffffffffff831661440b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806161376025913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216614477576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180615da86023913960400191505060405180910390fd5b614480836145e1565b8111156144d8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180615f536026913960400191505060405180910390fd5b6144ef836122c3836144e9876145e1565b9061456a565b614500826122c3836122bd866145e1565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6000828211156145db57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b73ffffffffffffffffffffffffffffffffffffffff166000908152600960205260409020547f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690565b614154816001615449565b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6004805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152600093611e3d939192909183018282801561472a5780601f106146ff5761010080835404028352916020019161472a565b820191906000526020600020905b81548152906001019060200180831161470d57829003601f168201915b50505050506040518060400160405280600181526020017f320000000000000000000000000000000000000000000000000000000000000081525061476d6154d2565b6154d6565b73ffffffffffffffffffffffffffffffffffffffff8084166000908152600a6020908152604080832093861683529290522054612ff090849084906147b790856147bc565b61421f565b60008282018381101561483057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8111156148b0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180615fce602a913960400191505060405180910390fd5b6148b982614371565b1561490f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615f056025913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff909116600090815260096020526040902055565b612bab8585848487604051602001808481526020018381526020018260ff1660f81b815260010193505050506040516020818303038152906040526151c1565b60015474010000000000000000000000000000000000000000900460ff1615614a0257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff16614a6a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602181526020018061601e6021913960400191505060405180910390fd5b81614a7481614371565b15614aca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162826025913960400191505060405180910390fd5b6000614ad5846145e1565b905060008311614b30576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615e1e6029913960400191505060405180910390fd5b82811015614b89576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180615ff86026913960400191505060405180910390fd5b600b80548490039055614b9e84848303614837565b60408051848152905173ffffffffffffffffffffffffffffffffffffffff8616917fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5919081900360200190a260408051848152905160009173ffffffffffffffffffffffffffffffffffffffff8716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a350505050565b73ffffffffffffffffffffffffffffffffffffffff86163314614cac576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806160e86025913960400191505060405180910390fd5b614cb88783868661554a565b604080517fd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de860208083019190915273ffffffffffffffffffffffffffffffffffffffff808b1683850152891660608301526080820188905260a0820187905260c0820186905260e0808301869052835180840390910181526101009092019092528051910120614d4a9088908361560a565b614d548783615788565b613b4287878761439f565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821480614d8d5750428210155b614df857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f46696174546f6b656e56323a207065726d697420697320657870697265640000604482015290519081900360640190fd5b6000614ea0614e0561467d565b73ffffffffffffffffffffffffffffffffffffffff80891660008181526011602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98184015280840194909452938b166060840152608083018a905260a083019390935260c08083018990528151808403909101815260e09092019052805191012061580d565b905073"; + hex"60806040526001805460ff60a01b191690556000600b553480156200002357600080fd5b506200002f3362000035565b62000057565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b615f6480620000676000396000f3fe608060405234801561001057600080fd5b506004361061038e5760003560e01c806388b7ab63116101de578063b2118a8d1161010f578063dd62ed3e116100ad578063ef55bec61161007c578063ef55bec614611044578063f2fde38b146110b0578063f9f92be4146110e3578063fe575a87146111165761038e565b8063dd62ed3e14610f5c578063e3ee160e14610f97578063e5a6b10f14611003578063e94a01021461100b5761038e565b8063c2eeeebd116100e9578063c2eeeebd14610e7e578063d505accf14610e86578063d608ea6414610ee4578063d916948714610f545761038e565b8063b2118a8d14610d6b578063b7b7289914610dae578063bd10243014610e765761038e565b8063a0cc6a681161017c578063a9059cbb11610156578063a9059cbb14610c99578063aa20e1e414610cd2578063aa271e1a14610d05578063ad38bf2214610d385761038e565b8063a0cc6a6814610c1d578063a297ea5e14610c25578063a457c2d714610c605761038e565b80638da5cb5b116101b85780638da5cb5b14610bfd5780638fa74a0e14610c0557806395d89b4114610c0d5780639fd0506d14610c155761038e565b806388b7ab6314610aad5780638a6db9c314610b915780638c2a993e14610bc45761038e565b806339509351116102c3578063554bab3c1161026157806374f4f5471161023057806374f4f54714610a315780637ecebe0014610a6a5780637f2eecc314610a9d5780638456cb5914610aa55761038e565b8063554bab3c146109755780635a049a70146109a85780635c975abb146109f657806370a08231146109fe5761038e565b806342966c681161029d57806342966c6814610855578063430239b4146108725780634e44d9561461093457806354fd4d501461096d5761038e565b806339509351146107db5780633f4ba83a1461081457806340c10f191461081c5761038e565b80633092afd5116103305780633357162b1161030a5780633357162b146105ae57806335d99f351461079a5780633644e515146107cb57806338a63183146107d35761038e565b80633092afd51461055557806330adf81f14610588578063313ce567146105905761038e565b80631a8952661161036c5780631a8952661461047757806323b872dd146104ac5780632ab60045146104ef5780632fc81e09146105225761038e565b806306fdde0314610393578063095ea7b31461041057806318160ddd1461045d575b600080fd5b61039b611149565b6040805160208082528351818301528351919283929083019185019080838360005b838110156103d55781810151838201526020016103bd565b50505050905090810190601f1680156104025780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6104496004803603604081101561042657600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356111f5565b604080519115158252519081900360200190f35b610465611296565b60408051918252519081900360200190f35b6104aa6004803603602081101561048d57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff1661129c565b005b610449600480360360608110156104c257600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060400135611359565b6104aa6004803603602081101561050557600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611614565b6104aa6004803603602081101561053857600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611775565b6104496004803603602081101561056b57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166117dd565b6104656118d6565b6105986118fa565b6040805160ff9092168252519081900360200190f35b6104aa60048036036101008110156105c557600080fd5b8101906020810181356401000000008111156105e057600080fd5b8201836020820111156105f257600080fd5b8035906020019184600183028401116401000000008311171561061457600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929594936020810193503591505064010000000081111561066757600080fd5b82018360208201111561067957600080fd5b8035906020019184600183028401116401000000008311171561069b57600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092959493602081019350359150506401000000008111156106ee57600080fd5b82018360208201111561070057600080fd5b8035906020019184600183028401116401000000008311171561072257600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050813560ff16925050602081013573ffffffffffffffffffffffffffffffffffffffff90811691604081013582169160608201358116916080013516611903565b6107a2611c45565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b610465611c61565b6107a2611c70565b610449600480360360408110156107f157600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135611c8c565b6104aa611d24565b6104496004803603604081101561083257600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135611de7565b6104aa6004803603602081101561086b57600080fd5b50356121b8565b6104aa6004803603604081101561088857600080fd5b8101906020810181356401000000008111156108a357600080fd5b8201836020820111156108b557600080fd5b803590602001918460208302840111640100000000831117156108d757600080fd5b9193909290916020810190356401000000008111156108f557600080fd5b82018360208201111561090757600080fd5b8035906020019184600183028401116401000000008311171561092957600080fd5b50909250905061245a565b6104496004803603604081101561094a57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135612611565b61039b6127a4565b6104aa6004803603602081101561098b57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166127db565b6104aa600480360360a08110156109be57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060208101359060ff6040820135169060608101359060800135612942565b6104496129e0565b61046560048036036020811015610a1457600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612a01565b6104aa60048036036040811015610a4757600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135612a12565b61046560048036036020811015610a8057600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612ac1565b610465612ae9565b6104aa612b0d565b6104aa600480360360e0811015610ac357600080fd5b73ffffffffffffffffffffffffffffffffffffffff823581169260208101359091169160408201359160608101359160808201359160a08101359181019060e0810160c0820135640100000000811115610b1c57600080fd5b820183602082011115610b2e57600080fd5b80359060200191846001830284011164010000000083111715610b5057600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612be7945050505050565b61046560048036036020811015610ba757600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612d4b565b6104aa60048036036040811015610bda57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135612d73565b6107a2612e23565b6107a2612e3f565b61039b612e64565b6107a2612edd565b610465612ef9565b6104aa60048036036040811015610c3b57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020013516612f1d565b61044960048036036040811015610c7657600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813516906020013561308c565b61044960048036036040811015610caf57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135613124565b6104aa60048036036020811015610ce857600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16613287565b61044960048036036020811015610d1b57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166133ee565b6104aa60048036036020811015610d4e57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16613419565b6104aa60048036036060811015610d8157600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060400135613580565b6104aa60048036036060811015610dc457600080fd5b73ffffffffffffffffffffffffffffffffffffffff82351691602081013591810190606081016040820135640100000000811115610e0157600080fd5b820183602082011115610e1357600080fd5b80359060200191846001830284011164010000000083111715610e3557600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550613611945050505050565b6107a26136a6565b6107a26136c2565b6104aa600480360360e0811015610e9c57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c001356136e7565b6104aa60048036036020811015610efa57600080fd5b810190602081018135640100000000811115610f1557600080fd5b820183602082011115610f2757600080fd5b80359060200191846001830284011164010000000083111715610f4957600080fd5b509092509050613789565b610465613872565b61046560048036036040811015610f7257600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020013516613896565b6104aa6004803603610120811015610fae57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060408101359060608101359060808101359060a08101359060ff60c0820135169060e08101359061010001356138ce565b61039b613a36565b6104496004803603604081101561102157600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135613aaf565b6104aa600480360361012081101561105b57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060408101359060608101359060808101359060a08101359060ff60c0820135169060e0810135906101000135613ae7565b6104aa600480360360208110156110c657600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16613c42565b6104aa600480360360208110156110f957600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16613d95565b6104496004803603602081101561112c57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16613e52565b6004805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156111ed5780601f106111c2576101008083540402835291602001916111ed565b820191906000526020600020905b8154815290600101906020018083116111d057829003601f168201915b505050505081565b60015460009074010000000000000000000000000000000000000000900460ff161561128257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b61128d338484613e5d565b50600192915050565b600b5490565b60025473ffffffffffffffffffffffffffffffffffffffff16331461130c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c815260200180615be0602c913960400191505060405180910390fd5b61131581613fa4565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f117e3210bb9aa7d9baff172026820255c6f6c30ba8999d1c2fd88e2848137c4e90600090a250565b60015460009074010000000000000000000000000000000000000000900460ff16156113e657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336113f081613faf565b15611446576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b8461145081613faf565b156114a6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b846114b081613faf565b15611506576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff87166000908152600a6020908152604080832033845290915290205485111561158f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526028815260200180615cd06028913960400191505060405180910390fd5b61159a878787613fdd565b73ffffffffffffffffffffffffffffffffffffffff87166000908152600a602090815260408083203384529091529020546115d590866141a8565b73ffffffffffffffffffffffffffffffffffffffff88166000908152600a60209081526040808320338452909152902055600193505050509392505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461169a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116611706576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180615b19602a913960400191505060405180910390fd5b600e80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517fe475e580d85111348e40d8ca33cfdd74c30fe1655c2d8537a13abc10065ffa5a90600090a250565b60125460ff1660011461178757600080fd5b60006117923061421f565b905080156117a5576117a5308383613fdd565b6117ae30614269565b5050601280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166002179055565b60085460009073ffffffffffffffffffffffffffffffffffffffff163314611850576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615bb76029913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166000818152600c6020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055600d909152808220829055517fe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb666929190a2506001919050565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60065460ff1681565b60085474010000000000000000000000000000000000000000900460ff1615611977576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180615d4b602a913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff84166119e3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f815260200180615c7d602f913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8316611a4f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615af06029913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216611abb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e815260200180615cf8602e913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8116611b27576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526028815260200180615e386028913960400191505060405180910390fd5b8751611b3a9060049060208b0190615889565b508651611b4e9060059060208a0190615889565b508551611b62906007906020890190615889565b50600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff8716179055600880547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff8781169190911790925560018054821686841617905560028054909116918416919091179055611bfc81614274565b5050600880547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055505050505050565b60085473ffffffffffffffffffffffffffffffffffffffff1681565b6000611c6b6142bb565b905090565b600e5473ffffffffffffffffffffffffffffffffffffffff1690565b60015460009074010000000000000000000000000000000000000000900460ff1615611d1957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b61128d3384846143b0565b60015473ffffffffffffffffffffffffffffffffffffffff163314611d94576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180615dec6022913960400191505060405180910390fd5b600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690556040517f7805862f689e2f13df9f062ff482ad3ad112aca9e0847911ed832e158c525b3390600090a1565b60015460009074010000000000000000000000000000000000000000900460ff1615611e7457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff16611edc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180615c5c6021913960400191505060405180910390fd5b33611ee681613faf565b15611f3c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b83611f4681613faf565b15611f9c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8516612008576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180615a856023913960400191505060405180910390fd5b60008411612061576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615b686029913960400191505060405180910390fd5b336000908152600d6020526040902054808511156120ca576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e815260200180615dbe602e913960400191505060405180910390fd5b600b546120d790866143fa565b600b556120f6866120f1876120eb8361421f565b906143fa565b614475565b61210081866141a8565b336000818152600d6020908152604091829020939093558051888152905173ffffffffffffffffffffffffffffffffffffffff8a16937fab8530f87dc9b59234c4623bf917212bb2536d647574c8e7e5da92c2ede0c9f8928290030190a360408051868152905173ffffffffffffffffffffffffffffffffffffffff8816916000917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a350600195945050505050565b60015474010000000000000000000000000000000000000000900460ff161561224257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff166122aa576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180615c5c6021913960400191505060405180910390fd5b336122b481613faf565b1561230a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b60006123153361421f565b905060008311612370576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615a5c6029913960400191505060405180910390fd5b828110156123c9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180615c366026913960400191505060405180910390fd5b600b546123d690846141a8565b600b556123e7336120f183866141a8565b60408051848152905133917fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5919081900360200190a260408051848152905160009133917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a3505050565b60125460ff1660021461246c57600080fd5b61247860058383615907565b5060005b838110156125ba576003600086868481811061249457fe5b6020908102929092013573ffffffffffffffffffffffffffffffffffffffff168352508101919091526040016000205460ff1661251c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603d8152602001806159a9603d913960400191505060405180910390fd5b61254d85858381811061252b57fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff16614269565b6003600086868481811061255d57fe5b6020908102929092013573ffffffffffffffffffffffffffffffffffffffff1683525081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905560010161247c565b506125c430614269565b505030600090815260036020819052604090912080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009081169091556012805490911690911790555050565b60015460009074010000000000000000000000000000000000000000900460ff161561269e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b60085473ffffffffffffffffffffffffffffffffffffffff16331461270e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615bb76029913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff83166000818152600c6020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055600d825291829020859055815185815291517f46980fca912ef9bcdbd36877427b6b90e860769f604e89c0e67720cece530d209281900390910190a250600192915050565b60408051808201909152600181527f3200000000000000000000000000000000000000000000000000000000000000602082015290565b60005473ffffffffffffffffffffffffffffffffffffffff16331461286157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff81166128cd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526028815260200180615a096028913960400191505060405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691909117918290556040519116907fb80482a293ca2e013eda8683c9bd7fc8347cfdaeea5ede58cba46df502c2a60490600090a250565b60015474010000000000000000000000000000000000000000900460ff16156129cc57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6129d98585858585614576565b5050505050565b60015474010000000000000000000000000000000000000000900460ff1681565b6000612a0c8261421f565b92915050565b612a1a612e3f565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612ab357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4f4e4c595f474154455741590000000000000000000000000000000000000000604482015290519081900360640190fd5b612abd82826145b6565b5050565b73ffffffffffffffffffffffffffffffffffffffff1660009081526011602052604090205490565b7fd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de881565b60015473ffffffffffffffffffffffffffffffffffffffff163314612b7d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180615dec6022913960400191505060405180910390fd5b600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790556040517f6985a02210a168e66602d3235cb6db0e70f92b3ba4d376a33c0f3d9434bff62590600090a1565b60015474010000000000000000000000000000000000000000900460ff1615612c7157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b86612c7b81613faf565b15612cd1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b86612cdb81613faf565b15612d31576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b612d408989898989898961487c565b505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff166000908152600d602052604090205490565b612d7b612e3f565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612e1457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4f4e4c595f474154455741590000000000000000000000000000000000000000604482015290519081900360640190fd5b612e1e8282611de7565b505050565b60005473ffffffffffffffffffffffffffffffffffffffff1690565b7fdbf6298cab77bb44ebfd5abb25ed2538c2a55f7404c47e83e6531361fba28c245490565b6005805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156111ed5780601f106111c2576101008083540402835291602001916111ed565b60015473ffffffffffffffffffffffffffffffffffffffff1681565b7f7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a226781565b60125460ff16600314612f2f57600080fd5b73ffffffffffffffffffffffffffffffffffffffff8216612fb157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f494e56414c49445f474154455741590000000000000000000000000000000000604482015290519081900360640190fd5b6000612fbb612e3f565b73ffffffffffffffffffffffffffffffffffffffff161461303d57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f414c52454144595f494e49540000000000000000000000000000000000000000604482015290519081900360640190fd5b817fdbf6298cab77bb44ebfd5abb25ed2538c2a55f7404c47e83e6531361fba28c2455807f54352c0d7cc5793352a36344bfdcdcf68ba6258544ce1aed71f60a74d882c19155612abd8261499d565b60015460009074010000000000000000000000000000000000000000900460ff161561311957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b61128d338484614a52565b60015460009074010000000000000000000000000000000000000000900460ff16156131b157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336131bb81613faf565b15613211576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b8361321b81613faf565b15613271576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b61327c338686613fdd565b506001949350505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461330d57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116613379576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f815260200180615c7d602f913960400191505060405180910390fd5b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691909117918290556040519116907fdb66dfa9c6b8f5226fe9aac7e51897ae8ee94ac31dc70bb6c9900b2574b707e690600090a250565b73ffffffffffffffffffffffffffffffffffffffff166000908152600c602052604090205460ff1690565b60005473ffffffffffffffffffffffffffffffffffffffff16331461349f57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff811661350b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526032815260200180615e8e6032913960400191505060405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691909117918290556040519116907fc67398012c111ce95ecb7429b933096c977380ee6c421175a71a4a4c6c88c06e90600090a250565b600e5473ffffffffffffffffffffffffffffffffffffffff1633146135f0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526024815260200180615cac6024913960400191505060405180910390fd5b612e1e73ffffffffffffffffffffffffffffffffffffffff84168383614aae565b60015474010000000000000000000000000000000000000000900460ff161561369b57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b612e1e838383614b3b565b60025473ffffffffffffffffffffffffffffffffffffffff1681565b7f54352c0d7cc5793352a36344bfdcdcf68ba6258544ce1aed71f60a74d882c1915490565b60015474010000000000000000000000000000000000000000900460ff161561377157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b61378087878787878787614c45565b50505050505050565b60085474010000000000000000000000000000000000000000900460ff1680156137b6575060125460ff16155b6137bf57600080fd5b6137cb60048383615907565b5061384082828080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600181527f320000000000000000000000000000000000000000000000000000000000000060208201529150614c879050565b600f555050601280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b7f158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a159742981565b73ffffffffffffffffffffffffffffffffffffffff9182166000908152600a6020908152604080832093909416825291909152205490565b60015474010000000000000000000000000000000000000000900460ff161561395857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b8861396281613faf565b156139b8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b886139c281613faf565b15613a18576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b613a298b8b8b8b8b8b8b8b8b614c9d565b5050505050505050505050565b6007805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156111ed5780601f106111c2576101008083540402835291602001916111ed565b73ffffffffffffffffffffffffffffffffffffffff919091166000908152601060209081526040808320938352929052205460ff1690565b60015474010000000000000000000000000000000000000000900460ff1615613b7157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b88613b7b81613faf565b15613bd1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b88613bdb81613faf565b15613c31576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b613a298b8b8b8b8b8b8b8b8b614ce1565b60005473ffffffffffffffffffffffffffffffffffffffff163314613cc857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116613d34576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180615aa86026913960400191505060405180910390fd5b6000546040805173ffffffffffffffffffffffffffffffffffffffff9283168152918316602083015280517f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09281900390910190a1613d9281614274565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314613e05576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c815260200180615be0602c913960400191505060405180910390fd5b613e0e81614269565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fffa4e6181777692565cf28528fc88fd1516ea86b56da075235fa575af6a4b85590600090a250565b6000612a0c82613faf565b73ffffffffffffffffffffffffffffffffffffffff8316613ec9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526024815260200180615d9a6024913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216613f35576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180615ace6022913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8084166000818152600a6020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b613d92816000614d25565b73ffffffffffffffffffffffffffffffffffffffff1660009081526009602052604090205460ff1c60011490565b73ffffffffffffffffffffffffffffffffffffffff8316614049576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615d756025913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166140b5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806159e66023913960400191505060405180910390fd5b6140be8361421f565b811115614116576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180615b916026913960400191505060405180910390fd5b61412d836120f1836141278761421f565b906141a8565b61413e826120f1836120eb8661421f565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b60008282111561421957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b73ffffffffffffffffffffffffffffffffffffffff166000908152600960205260409020547f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690565b613d92816001614d25565b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6004805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152600093611c6b93919290918301828280156143685780601f1061433d57610100808354040283529160200191614368565b820191906000526020600020905b81548152906001019060200180831161434b57829003601f168201915b50505050506040518060400160405280600181526020017f32000000000000000000000000000000000000000000000000000000000000008152506143ab614dae565b614db2565b73ffffffffffffffffffffffffffffffffffffffff8084166000908152600a6020908152604080832093861683529290522054612e1e90849084906143f590856143fa565b613e5d565b60008282018381101561446e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8111156144ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180615c0c602a913960400191505060405180910390fd5b6144f782613faf565b1561454d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615b436025913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff909116600090815260096020526040902055565b6129d98585848487604051602001808481526020018381526020018260ff1660f81b81526001019350505050604051602081830303815290604052614b3b565b60015474010000000000000000000000000000000000000000900460ff161561464057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff166146a8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180615c5c6021913960400191505060405180910390fd5b816146b281613faf565b15614708576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b60006147138461421f565b90506000831161476e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615a5c6029913960400191505060405180910390fd5b828110156147c7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180615c366026913960400191505060405180910390fd5b600b805484900390556147dc84848303614475565b60408051848152905173ffffffffffffffffffffffffffffffffffffffff8616917fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5919081900360200190a260408051848152905160009173ffffffffffffffffffffffffffffffffffffffff8716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a350505050565b73ffffffffffffffffffffffffffffffffffffffff861633146148ea576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615d266025913960400191505060405180910390fd5b6148f687838686614e26565b604080517fd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de860208083019190915273ffffffffffffffffffffffffffffffffffffffff808b1683850152891660608301526080820188905260a0820187905260c0820186905260e080830186905283518084039091018152610100909201909252805191012061498890889083614ee6565b6149928783615064565b613780878787613fdd565b73ffffffffffffffffffffffffffffffffffffffff81166000818152600c6020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055600d8252918290207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90819055825181815292519093927f46980fca912ef9bcdbd36877427b6b90e860769f604e89c0e67720cece530d2092908290030190a25050565b612e1e83836143f584604051806060016040528060258152602001615f0a6025913973ffffffffffffffffffffffffffffffffffffffff808a166000908152600a60209081526040808320938c168352929052205491906150e9565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052612e1e90849061519a565b614b458383615272565b614bbf837f158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a159742960001b8585604051602001808481526020018373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200193505050506040516020818303038152906040528051906020012083614ee6565b73ffffffffffffffffffffffffffffffffffffffff8316600081815260106020908152604080832086845290915280822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055518492917f1cdd46ff242716cdaa72d159d339a485b3438398348d68f09d7c8c0a59353d8191a3505050565b61378087878787868689604051602001808481526020018381526020018260ff1660f81b815260010193505050506040516020818303038152906040526152fc565b600046614c95848483614db2565b949350505050565b612d4089898989898988888b604051602001808481526020018381526020018260ff1660f81b815260010193505050506040516020818303038152906040526155c0565b612d4089898989898988888b604051602001808481526020018381526020018260ff1660f81b8152600101935050505060405160208183030381529060405261487c565b80614d3857614d338261421f565b614d81565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600960205260409020547f8000000000000000000000000000000000000000000000000000000000000000175b73ffffffffffffffffffffffffffffffffffffffff90921660009081526009602052604090209190915550565b4690565b8251602093840120825192840192909220604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8187015280820194909452606084019190915260808301919091523060a0808401919091528151808403909101815260c09092019052805191012090565b814211614e7e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b815260200180615a31602b913960400191505060405180910390fd5b804210614ed6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ee56025913960400191505060405180910390fd5b614ee08484615272565b50505050565b73"; bytes memory b2 = - hex"636ccea6528783856040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff16815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015614f2d578181015183820152602001614f15565b50505050905090810190601f168015614f5a5780820380516001836020036101000a031916815260200191505b5094505050505060206040518083038186803b158015614f7957600080fd5b505af4158015614f8d573d6000803e3d6000fd5b505050506040513d6020811015614fa357600080fd5b505161501057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f454950323631323a20696e76616c6964207369676e6174757265000000000000604482015290519081900360640190fd5b61501b86868661421f565b505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000818152600c6020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055600d8252918290207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90819055825181815292519093927f46980fca912ef9bcdbd36877427b6b90e860769f604e89c0e67720cece530d2092908290030190a25050565b612ff083836147b7846040518060600160405280602581526020016162cc6025913973ffffffffffffffffffffffffffffffffffffffff808a166000908152600a60209081526040808320938c16835292905220549190615847565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052612ff09084906158f8565b6151cb83836159d0565b615245837f158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a159742960001b8585604051602001808481526020018373ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050604051602081830303815290604052805190602001208361560a565b73ffffffffffffffffffffffffffffffffffffffff8316600081815260106020908152604080832086845290915280822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055518492917f1cdd46ff242716cdaa72d159d339a485b3438398348d68f09d7c8c0a59353d8191a3505050565b6152d78783868661554a565b604080517f7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a226760208083019190915273ffffffffffffffffffffffffffffffffffffffff808b1683850152891660608301526080820188905260a0820187905260c0820186905260e0808301869052835180840390910181526101009092019092528051910120614d4a9088908361560a565b613b4287878787868689604051602001808481526020018381526020018260ff1660f81b81526001019350505050604051602081830303815290604052614d5f565b6000466153b98484836154d6565b949350505050565b612f1289898989898988888b604051602001808481526020018381526020018260ff1660f81b815260010193505050506040516020818303038152906040526152cb565b612f1289898989898988888b604051602001808481526020018381526020018260ff1660f81b81526001019350505050604051602081830303815290604052614c3e565b8061545c57615457826145e1565b6154a5565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600960205260409020547f8000000000000000000000000000000000000000000000000000000000000000175b73ffffffffffffffffffffffffffffffffffffffff90921660009081526009602052604090209190915550565b4690565b8251602093840120825192840192909220604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8187015280820194909452606084019190915260808301919091523060a0808401919091528151808403909101815260c09092019052805191012090565b8142116155a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b815260200180615df3602b913960400191505060405180910390fd5b8042106155fa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806162a76025913960400191505060405180910390fd5b61560484846159d0565b50505050565b73"; + hex"636ccea65284614f12614f0c6142bb565b8661565e565b846040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff16815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015614f81578181015183820152602001614f69565b50505050905090810190601f168015614fae5780820380516001836020036101000a031916815260200191505b5094505050505060206040518083038186803b158015614fcd57600080fd5b505af4158015614fe1573d6000803e3d6000fd5b505050506040513d6020811015614ff757600080fd5b5051612e1e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f46696174546f6b656e56323a20696e76616c6964207369676e61747572650000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8216600081815260106020908152604080832085845290915280822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055518392917f98de503528ee59b575ef0c0a2576a82497bfc029a5685b209e9ec333479b10a591a35050565b60008184841115615192576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561515757818101518382015260200161513f565b50505050905090810190601f1680156151845780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b60606151fc826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166156989092919063ffffffff16565b805190915015612e1e5780806020019051602081101561521b57600080fd5b5051612e1e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180615e0e602a913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216600090815260106020908152604080832084845290915290205460ff1615612abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e815260200180615e60602e913960400191505060405180910390fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82148061532a5750428210155b61539557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f46696174546f6b656e56323a207065726d697420697320657870697265640000604482015290519081900360640190fd5b600061543d6153a26142bb565b73ffffffffffffffffffffffffffffffffffffffff80891660008181526011602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98184015280840194909452938b166060840152608083018a905260a083019390935260c08083018990528151808403909101815260e09092019052805191012061565e565b905073"; bytes memory b3 = - hex"636ccea6528461563661563061467d565b8661580d565b846040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff16815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b838110156156a557818101518382015260200161568d565b50505050905090810190601f1680156156d25780820380516001836020036101000a031916815260200191505b5094505050505060206040518083038186803b1580156156f157600080fd5b505af4158015615705573d6000803e3d6000fd5b505050506040513d602081101561571b57600080fd5b5051612ff057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f46696174546f6b656e56323a20696e76616c6964207369676e61747572650000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8216600081815260106020908152604080832085845290915280822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055518392917f98de503528ee59b575ef0c0a2576a82497bfc029a5685b209e9ec333479b10a591a35050565b6040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b600081848411156158f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b838110156158b557818101518382015260200161589d565b50505050905090810190601f1680156158e25780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b606061595a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16615a5a9092919063ffffffff16565b805190915015612ff05780806020019051602081101561597957600080fd5b5051612ff0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a8152602001806161d0602a913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216600090815260106020908152604080832084845290915290205460ff1615612c8f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e815260200180616222602e913960400191505060405180910390fd5b60606153b9848460008585615a6e85615bc5565b615ad957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b60208310615b4357805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101615b06565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114615ba5576040519150601f19603f3d011682016040523d82523d6000602084013e615baa565b606091505b5091509150615bba828286615bcb565b979650505050505050565b3b151590565b60608315615bda575081614830565b825115615bea5782518084602001fd5b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526020600482018181528451602484015284518593919283926044019190850190808383600083156158b557818101518382015260200161589d565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10615c8c57805160ff1916838001178555615cb9565b82800160010185558215615cb9579182015b82811115615cb9578251825591602001919060010190615c9e565b50615cc5929150615d55565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10615d28578280017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00823516178555615cb9565b82800160010185558215615cb9579182015b82811115615cb9578235825591602001919060010190615d3a565b5b80821115615cc55760008155600101615d5656fe46696174546f6b656e56325f323a20426c61636b6c697374696e672070726576696f75736c7920756e626c61636b6c6973746564206163636f756e742145524332303a207472616e7366657220746f20746865207a65726f20616464726573735061757361626c653a206e65772070617573657220697320746865207a65726f206164647265737346696174546f6b656e56323a20617574686f72697a6174696f6e206973206e6f74207965742076616c696446696174546f6b656e3a206275726e20616d6f756e74206e6f742067726561746572207468616e203046696174546f6b656e3a206d696e7420746f20746865207a65726f20616464726573734f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737346696174546f6b656e3a206e65772070617573657220697320746865207a65726f2061646472657373526573637561626c653a206e6577207265736375657220697320746865207a65726f206164647265737346696174546f6b656e56325f323a204163636f756e7420697320626c61636b6c697374656446696174546f6b656e3a206d696e7420616d6f756e74206e6f742067726561746572207468616e203045524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636546696174546f6b656e3a2063616c6c6572206973206e6f7420746865206d61737465724d696e746572426c61636b6c69737461626c653a2063616c6c6572206973206e6f742074686520626c61636b6c697374657246696174546f6b656e56325f323a2042616c616e636520657863656564732028325e323535202d20312946696174546f6b656e3a206275726e20616d6f756e7420657863656564732062616c616e636546696174546f6b656e3a2063616c6c6572206973206e6f742061206d696e74657246696174546f6b656e3a206e6577206d61737465724d696e74657220697320746865207a65726f2061646472657373526573637561626c653a2063616c6c6572206973206e6f7420746865207265736375657245524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636546696174546f6b656e3a206e657720626c61636b6c697374657220697320746865207a65726f206164647265737346696174546f6b656e56323a2063616c6c6572206d7573742062652074686520706179656546696174546f6b656e3a20636f6e747261637420697320616c726561647920696e697469616c697a656445524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737346696174546f6b656e3a206d696e7420616d6f756e742065786365656473206d696e746572416c6c6f77616e63655061757361626c653a2063616c6c6572206973206e6f7420746865207061757365725361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656446696174546f6b656e3a206e6577206f776e657220697320746865207a65726f206164647265737346696174546f6b656e56323a20617574686f72697a6174696f6e2069732075736564206f722063616e63656c6564426c61636b6c69737461626c653a206e657720626c61636b6c697374657220697320746865207a65726f2061646472657373426c61636b6c69737461626c653a206163636f756e7420697320626c61636b6c697374656446696174546f6b656e56323a20617574686f72697a6174696f6e206973206578706972656445524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa26469706673582212205b9c28831ca019c704546ef047ba19de251c8493a622e0f4ae1dff3520aaae2464736f6c634300060c0033"; + hex"636ccea6528783856040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff16815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b838110156154ca5781810151838201526020016154b2565b50505050905090810190601f1680156154f75780820380516001836020036101000a031916815260200191505b5094505050505060206040518083038186803b15801561551657600080fd5b505af415801561552a573d6000803e3d6000fd5b505050506040513d602081101561554057600080fd5b50516155ad57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f454950323631323a20696e76616c6964207369676e6174757265000000000000604482015290519081900360640190fd5b6155b8868686613e5d565b505050505050565b6155cc87838686614e26565b604080517f7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a226760208083019190915273ffffffffffffffffffffffffffffffffffffffff808b1683850152891660608301526080820188905260a0820187905260c0820186905260e080830186905283518084039091018152610100909201909252805191012061498890889083614ee6565b6040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b6060614c958484600085856156ac85615803565b61571757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b6020831061578157805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101615744565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d80600081146157e3576040519150601f19603f3d011682016040523d82523d6000602084013e6157e8565b606091505b50915091506157f8828286615809565b979650505050505050565b3b151590565b6060831561581857508161446e565b8251156158285782518084602001fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181815284516024840152845185939192839260440191908501908083836000831561515757818101518382015260200161513f565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106158ca57805160ff19168380011785556158f7565b828001600101855582156158f7579182015b828111156158f75782518255916020019190600101906158dc565b50615903929150615993565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10615966578280017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008235161785556158f7565b828001600101855582156158f7579182015b828111156158f7578235825591602001919060010190615978565b5b80821115615903576000815560010161599456fe46696174546f6b656e56325f323a20426c61636b6c697374696e672070726576696f75736c7920756e626c61636b6c6973746564206163636f756e742145524332303a207472616e7366657220746f20746865207a65726f20616464726573735061757361626c653a206e65772070617573657220697320746865207a65726f206164647265737346696174546f6b656e56323a20617574686f72697a6174696f6e206973206e6f74207965742076616c696446696174546f6b656e3a206275726e20616d6f756e74206e6f742067726561746572207468616e203046696174546f6b656e3a206d696e7420746f20746865207a65726f20616464726573734f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737346696174546f6b656e3a206e65772070617573657220697320746865207a65726f2061646472657373526573637561626c653a206e6577207265736375657220697320746865207a65726f206164647265737346696174546f6b656e56325f323a204163636f756e7420697320626c61636b6c697374656446696174546f6b656e3a206d696e7420616d6f756e74206e6f742067726561746572207468616e203045524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636546696174546f6b656e3a2063616c6c6572206973206e6f7420746865206d61737465724d696e746572426c61636b6c69737461626c653a2063616c6c6572206973206e6f742074686520626c61636b6c697374657246696174546f6b656e56325f323a2042616c616e636520657863656564732028325e323535202d20312946696174546f6b656e3a206275726e20616d6f756e7420657863656564732062616c616e636546696174546f6b656e3a2063616c6c6572206973206e6f742061206d696e74657246696174546f6b656e3a206e6577206d61737465724d696e74657220697320746865207a65726f2061646472657373526573637561626c653a2063616c6c6572206973206e6f7420746865207265736375657245524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636546696174546f6b656e3a206e657720626c61636b6c697374657220697320746865207a65726f206164647265737346696174546f6b656e56323a2063616c6c6572206d7573742062652074686520706179656546696174546f6b656e3a20636f6e747261637420697320616c726561647920696e697469616c697a656445524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737346696174546f6b656e3a206d696e7420616d6f756e742065786365656473206d696e746572416c6c6f77616e63655061757361626c653a2063616c6c6572206973206e6f7420746865207061757365725361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656446696174546f6b656e3a206e6577206f776e657220697320746865207a65726f206164647265737346696174546f6b656e56323a20617574686f72697a6174696f6e2069732075736564206f722063616e63656c6564426c61636b6c69737461626c653a206e657720626c61636b6c697374657220697320746865207a65726f2061646472657373426c61636b6c69737461626c653a206163636f756e7420697320626c61636b6c697374656446696174546f6b656e56323a20617574686f72697a6174696f6e206973206578706972656445524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122038d731178b4dd0e027fef834bc8ab43420dd9ff02d6c94216b764f26362e531d64736f6c634300060c0033"; bytes memory libAddress = abi.encodePacked(sigCheckerAddress); From 5b1f6bf240025b26416b87e56ab829ef4641c21a Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Fri, 7 Jun 2024 11:17:01 +0200 Subject: [PATCH 10/20] Update refs --- .../libraries/FiatTokenV2_2_ArbCompatible.sol | 2748 ----------------- .../test/IFiatTokenArbitrumOrbitV2_2.sol | 20 + test-foundry/L2USDCCustomGateway.t.sol | 12 +- 3 files changed, 27 insertions(+), 2753 deletions(-) delete mode 100644 contracts/tokenbridge/libraries/FiatTokenV2_2_ArbCompatible.sol create mode 100644 contracts/tokenbridge/test/IFiatTokenArbitrumOrbitV2_2.sol diff --git a/contracts/tokenbridge/libraries/FiatTokenV2_2_ArbCompatible.sol b/contracts/tokenbridge/libraries/FiatTokenV2_2_ArbCompatible.sol deleted file mode 100644 index 3dd60b9bcc..0000000000 --- a/contracts/tokenbridge/libraries/FiatTokenV2_2_ArbCompatible.sol +++ /dev/null @@ -1,2748 +0,0 @@ -pragma solidity ^0.8.0; - -// contracts/interface/IERC1271.sol -/** - * Copyright 2023 Circle Internet Financial, LTD. All rights reserved. - * - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @dev Interface of the ERC1271 standard signature validation method for - * contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271]. - */ -interface IERC1271 { - /** - * @dev Should return whether the signature provided is valid for the provided data - * @param hash Hash of the data to be signed - * @param signature Signature byte array associated with the provided data hash - * @return magicValue bytes4 magic value 0x1626ba7e when function passes - */ - function isValidSignature(bytes32 hash, bytes memory signature) - external - view - returns (bytes4 magicValue); -} - -// contracts/util/ECRecover.sol -/** - * Copyright 2023 Circle Internet Financial, LTD. All rights reserved. - * - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @title ECRecover - * @notice A library that provides a safe ECDSA recovery function - */ -library ECRecover { - /** - * @notice Recover signer's address from a signed message - * @dev Adapted from: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/65e4ffde586ec89af3b7e9140bdc9235d1254853/contracts/cryptography/ECDSA.sol - * Modifications: Accept v, r, and s as separate arguments - * @param digest Keccak-256 hash digest of the signed message - * @param v v of the signature - * @param r r of the signature - * @param s s of the signature - * @return Signer address - */ - function recover(bytes32 digest, uint8 v, bytes32 r, bytes32 s) - internal - pure - returns (address) - { - // 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 (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): 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) { - revert("ECRecover: invalid signature 's' value"); - } - - if (v != 27 && v != 28) { - revert("ECRecover: invalid signature 'v' value"); - } - - // If the signature is valid (and not malleable), return the signer address - address signer = ecrecover(digest, v, r, s); - require(signer != address(0), "ECRecover: invalid signature"); - - return signer; - } - - /** - * @notice Recover signer's address from a signed message - * @dev Adapted from: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/0053ee040a7ff1dbc39691c9e67a69f564930a88/contracts/utils/cryptography/ECDSA.sol - * @param digest Keccak-256 hash digest of the signed message - * @param signature Signature byte array associated with hash - * @return Signer address - */ - function recover(bytes32 digest, bytes memory signature) internal pure returns (address) { - require(signature.length == 65, "ECRecover: invalid signature length"); - - 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 recover(digest, v, r, s); - } -} - -// contracts/util/EIP712.sol -/** - * Copyright 2023 Circle Internet Financial, LTD. All rights reserved. - * - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @title EIP712 - * @notice A library that provides EIP712 helper functions - */ -library EIP712 { - /** - * @notice Make EIP712 domain separator - * @param name Contract name - * @param version Contract version - * @param chainId Blockchain ID - * @return Domain separator - */ - function makeDomainSeparator(string memory name, string memory version, uint256 chainId) - internal - view - returns (bytes32) - { - return keccak256( - abi.encode( - // keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)") - 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f, - keccak256(bytes(name)), - keccak256(bytes(version)), - chainId, - address(this) - ) - ); - } - - /** - * @notice Make EIP712 domain separator - * @param name Contract name - * @param version Contract version - * @return Domain separator - */ - function makeDomainSeparator(string memory name, string memory version) - internal - view - returns (bytes32) - { - uint256 chainId; - assembly { - chainId := chainid() - } - return makeDomainSeparator(name, version, chainId); - } -} - -// contracts/util/MessageHashUtils.sol -/** - * Copyright 2023 Circle Internet Financial, LTD. All rights reserved. - * - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @dev Signature message hash utilities for producing digests to be consumed by {ECDSA} recovery or signing. - * - * The library provides methods for generating a hash of a message that conforms to the - * https://eips.ethereum.org/EIPS/eip-191[EIP 191] and https://eips.ethereum.org/EIPS/eip-712[EIP 712] - * specifications. - */ -library MessageHashUtils { - /** - * @dev Returns the keccak256 digest of an EIP-712 typed data (EIP-191 version `0x01`). - * Adapted from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/21bb89ef5bfc789b9333eb05e3ba2b7b284ac77c/contracts/utils/cryptography/MessageHashUtils.sol - * - * The digest is calculated from a `domainSeparator` and a `structHash`, by prefixing them with - * `\x19\x01` and hashing the result. It corresponds to the hash signed by the - * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] JSON-RPC method as part of EIP-712. - * - * @param domainSeparator Domain separator - * @param structHash Hashed EIP-712 data struct - * @return digest The keccak256 digest of an EIP-712 typed data - */ - function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) - internal - pure - returns (bytes32 digest) - { - assembly { - let ptr := mload(0x40) - mstore(ptr, "\x19\x01") - mstore(add(ptr, 0x02), domainSeparator) - mstore(add(ptr, 0x22), structHash) - digest := keccak256(ptr, 0x42) - } - } -} - -// contracts/v1/Ownable.sol -/** - * - * Copyright (c) 2018 zOS Global Limited. - * Copyright (c) 2018-2020 CENTRE SECZ - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/** - * @notice The Ownable contract has an owner address, and provides basic - * authorization control functions - * @dev Forked from https://github.com/OpenZeppelin/openzeppelin-labs/blob/3887ab77b8adafba4a26ace002f3a684c1a3388b/upgradeability_ownership/contracts/ownership/Ownable.sol - * Modifications: - * 1. Consolidate OwnableStorage into this contract (7/13/18) - * 2. Reformat, conform to Solidity 0.6 syntax, and add error messages (5/13/20) - * 3. Make public functions external (5/27/20) - */ -contract Ownable { - // Owner of the contract - address private _owner; - - /** - * @dev Event to show ownership has been transferred - * @param previousOwner representing the address of the previous owner - * @param newOwner representing the address of the new owner - */ - event OwnershipTransferred(address previousOwner, address newOwner); - - /** - * @dev The constructor sets the original owner of the contract to the sender account. - */ - constructor() { - setOwner(msg.sender); - } - - /** - * @dev Tells the address of the owner - * @return the address of the owner - */ - function owner() external view returns (address) { - return _owner; - } - - /** - * @dev Sets a new owner address - */ - function setOwner(address newOwner) internal { - _owner = newOwner; - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - require(msg.sender == _owner, "Ownable: caller is not the owner"); - _; - } - - /** - * @dev Allows the current owner to transfer control of the contract to a newOwner. - * @param newOwner The address to transfer ownership to. - */ - function transferOwnership(address newOwner) external onlyOwner { - require(newOwner != address(0), "Ownable: new owner is the zero address"); - emit OwnershipTransferred(_owner, newOwner); - setOwner(newOwner); - } -} - -// contracts/v2/EIP712Domain.sol -/** - * Copyright 2023 Circle Internet Financial, LTD. All rights reserved. - * - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// solhint-disable func-name-mixedcase - -/** - * @title EIP712 Domain - */ -contract EIP712Domain { - // was originally DOMAIN_SEPARATOR - // but that has been moved to a method so we can override it in V2_2+ - bytes32 internal _DEPRECATED_CACHED_DOMAIN_SEPARATOR; - - /** - * @notice Get the EIP712 Domain Separator. - * @return The bytes32 EIP712 domain separator. - */ - function DOMAIN_SEPARATOR() external view returns (bytes32) { - return _domainSeparator(); - } - - /** - * @dev Internal method to get the EIP712 Domain Separator. - * @return The bytes32 EIP712 domain separator. - */ - function _domainSeparator() internal view virtual returns (bytes32) { - return _DEPRECATED_CACHED_DOMAIN_SEPARATOR; - } -} - -// node_modules/@openzeppelin/contracts/math/SafeMath.sol - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - */ -library SafeMath { - /** - * @dev Returns the addition of two unsigned integers, with an overflow flag. - * - * _Available since v3.4._ - */ - function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { - uint256 c = a + b; - if (c < a) return (false, 0); - return (true, c); - } - - /** - * @dev Returns the substraction of two unsigned integers, with an overflow flag. - * - * _Available since v3.4._ - */ - function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { - if (b > a) return (false, 0); - return (true, a - b); - } - - /** - * @dev Returns the multiplication of two unsigned integers, with an overflow flag. - * - * _Available since v3.4._ - */ - function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) return (true, 0); - uint256 c = a * b; - if (c / a != b) return (false, 0); - return (true, c); - } - - /** - * @dev Returns the division of two unsigned integers, with a division by zero flag. - * - * _Available since v3.4._ - */ - function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { - if (b == 0) return (false, 0); - return (true, a / b); - } - - /** - * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. - * - * _Available since v3.4._ - */ - function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { - if (b == 0) return (false, 0); - return (true, a % b); - } - - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - require(b <= a, "SafeMath: subtraction overflow"); - return a - b; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - if (a == 0) return 0; - uint256 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers, reverting on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - require(b > 0, "SafeMath: division by zero"); - return a / b; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * reverting when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - require(b > 0, "SafeMath: modulo by zero"); - return a % b; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting with custom message on - * overflow (when the result is negative). - * - * CAUTION: This function is deprecated because it requires allocating memory for the error - * message unnecessarily. For custom revert reasons use {trySub}. - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b, string memory errorMessage) - internal - pure - returns (uint256) - { - require(b <= a, errorMessage); - return a - b; - } - - /** - * @dev Returns the integer division of two unsigned integers, reverting with custom message on - * division by zero. The result is rounded towards zero. - * - * CAUTION: This function is deprecated because it requires allocating memory for the error - * message unnecessarily. For custom revert reasons use {tryDiv}. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b, string memory errorMessage) - internal - pure - returns (uint256) - { - require(b > 0, errorMessage); - return a / b; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * reverting with custom message when dividing by zero. - * - * CAUTION: This function is deprecated because it requires allocating memory for the error - * message unnecessarily. For custom revert reasons use {tryMod}. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b, string memory errorMessage) - internal - pure - returns (uint256) - { - require(b > 0, errorMessage); - return a % b; - } -} - -// node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol - -/** - * @dev Interface of the ERC20 standard as defined in the EIP. - */ -interface IERC20 { - /** - * @dev Returns the amount of tokens in existence. - */ - function totalSupply() external view returns (uint256); - - /** - * @dev Returns the amount of tokens owned by `account`. - */ - function balanceOf(address account) external view returns (uint256); - - /** - * @dev Moves `amount` tokens from the caller's account to `recipient`. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transfer(address recipient, uint256 amount) external returns (bool); - - /** - * @dev Returns the remaining number of tokens that `spender` will be - * allowed to spend on behalf of `owner` through {transferFrom}. This is - * zero by default. - * - * This value changes when {approve} or {transferFrom} are called. - */ - function allowance(address owner, address spender) external view returns (uint256); - - /** - * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * IMPORTANT: Beware that changing an allowance with this method brings the risk - * that someone may use both the old and the new allowance by unfortunate - * transaction ordering. One possible solution to mitigate this race - * condition is to first reduce the spender's allowance to 0 and set the - * desired value afterwards: - * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 - * - * Emits an {Approval} event. - */ - function approve(address spender, uint256 amount) external returns (bool); - - /** - * @dev Moves `amount` tokens from `sender` to `recipient` using the - * allowance mechanism. `amount` is then deducted from the caller's - * allowance. - * - * Returns a boolean value indicating whether the operation succeeded. - * - * Emits a {Transfer} event. - */ - function transferFrom(address sender, address recipient, uint256 amount) - external - returns (bool); - - /** - * @dev Emitted when `value` tokens are moved from one account (`from`) to - * another (`to`). - * - * Note that `value` may be zero. - */ - event Transfer(address indexed from, address indexed to, uint256 value); - - /** - * @dev Emitted when the allowance of a `spender` for an `owner` is set by - * a call to {approve}. `value` is the new allowance. - */ - event Approval(address indexed owner, address indexed spender, uint256 value); -} - -// node_modules/@openzeppelin/contracts/utils/Address.sol - -/** - * @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 - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize, which returns 0 for contracts in - // construction, since the code is only stored at the end of the - // constructor execution. - - uint256 size; - // solhint-disable-next-line no-inline-assembly - assembly { - size := extcodesize(account) - } - return size > 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"); - - // solhint-disable-next-line avoid-low-level-calls, avoid-call-value - (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 functionCall(target, data, "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"); - require(isContract(target), "Address: call to non-contract"); - - // solhint-disable-next-line avoid-low-level-calls - (bool success, bytes memory returndata) = target.call{value: value}(data); - return _verifyCallResult(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) - { - require(isContract(target), "Address: static call to non-contract"); - - // solhint-disable-next-line avoid-low-level-calls - (bool success, bytes memory returndata) = target.staticcall(data); - return _verifyCallResult(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) - { - require(isContract(target), "Address: delegate call to non-contract"); - - // solhint-disable-next-line avoid-low-level-calls - (bool success, bytes memory returndata) = target.delegatecall(data); - return _verifyCallResult(success, returndata, errorMessage); - } - - function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) - private - pure - returns (bytes memory) - { - if (success) { - return returndata; - } else { - // 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 - - // solhint-disable-next-line no-inline-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } - } -} - -// contracts/v1/AbstractFiatTokenV1.sol -/** - * Copyright 2023 Circle Internet Financial, LTD. All rights reserved. - * - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -abstract contract AbstractFiatTokenV1 is IERC20 { - function _approve(address owner, address spender, uint256 value) internal virtual; - - function _transfer(address from, address to, uint256 value) internal virtual; -} - -// contracts/v1/Blacklistable.sol -/** - * Copyright 2023 Circle Internet Financial, LTD. All rights reserved. - * - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @title Blacklistable Token - * @dev Allows accounts to be blacklisted by a "blacklister" role - */ -abstract contract Blacklistable is Ownable { - address public blacklister; - mapping(address => bool) internal _deprecatedBlacklisted; - - event Blacklisted(address indexed _account); - event UnBlacklisted(address indexed _account); - event BlacklisterChanged(address indexed newBlacklister); - - /** - * @dev Throws if called by any account other than the blacklister. - */ - modifier onlyBlacklister() { - require(msg.sender == blacklister, "Blacklistable: caller is not the blacklister"); - _; - } - - /** - * @dev Throws if argument account is blacklisted. - * @param _account The address to check. - */ - modifier notBlacklisted(address _account) { - require(!_isBlacklisted(_account), "Blacklistable: account is blacklisted"); - _; - } - - /** - * @notice Checks if account is blacklisted. - * @param _account The address to check. - * @return True if the account is blacklisted, false if the account is not blacklisted. - */ - function isBlacklisted(address _account) external view returns (bool) { - return _isBlacklisted(_account); - } - - /** - * @notice Adds account to blacklist. - * @param _account The address to blacklist. - */ - function blacklist(address _account) external onlyBlacklister { - _blacklist(_account); - emit Blacklisted(_account); - } - - /** - * @notice Removes account from blacklist. - * @param _account The address to remove from the blacklist. - */ - function unBlacklist(address _account) external onlyBlacklister { - _unBlacklist(_account); - emit UnBlacklisted(_account); - } - - /** - * @notice Updates the blacklister address. - * @param _newBlacklister The address of the new blacklister. - */ - function updateBlacklister(address _newBlacklister) external onlyOwner { - require(_newBlacklister != address(0), "Blacklistable: new blacklister is the zero address"); - blacklister = _newBlacklister; - emit BlacklisterChanged(blacklister); - } - - /** - * @dev Checks if account is blacklisted. - * @param _account The address to check. - * @return true if the account is blacklisted, false otherwise. - */ - function _isBlacklisted(address _account) internal view virtual returns (bool); - - /** - * @dev Helper method that blacklists an account. - * @param _account The address to blacklist. - */ - function _blacklist(address _account) internal virtual; - - /** - * @dev Helper method that unblacklists an account. - * @param _account The address to unblacklist. - */ - function _unBlacklist(address _account) internal virtual; -} - -// contracts/v1/Pausable.sol -/** - * - * Copyright (c) 2016 Smart Contract Solutions, Inc. - * Copyright (c) 2018-2020 CENTRE SECZ - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/** - * @notice Base contract which allows children to implement an emergency stop - * mechanism - * @dev Forked from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/feb665136c0dae9912e08397c1a21c4af3651ef3/contracts/lifecycle/Pausable.sol - * Modifications: - * 1. Added pauser role, switched pause/unpause to be onlyPauser (6/14/2018) - * 2. Removed whenNotPause/whenPaused from pause/unpause (6/14/2018) - * 3. Removed whenPaused (6/14/2018) - * 4. Switches ownable library to use ZeppelinOS (7/12/18) - * 5. Remove constructor (7/13/18) - * 6. Reformat, conform to Solidity 0.6 syntax and add error messages (5/13/20) - * 7. Make public functions external (5/27/20) - */ -contract Pausable is Ownable { - event Pause(); - event Unpause(); - event PauserChanged(address indexed newAddress); - - address public pauser; - bool public paused = false; - - /** - * @dev Modifier to make a function callable only when the contract is not paused. - */ - modifier whenNotPaused() { - require(!paused, "Pausable: paused"); - _; - } - - /** - * @dev throws if called by any account other than the pauser - */ - modifier onlyPauser() { - require(msg.sender == pauser, "Pausable: caller is not the pauser"); - _; - } - - /** - * @dev called by the owner to pause, triggers stopped state - */ - function pause() external onlyPauser { - paused = true; - emit Pause(); - } - - /** - * @dev called by the owner to unpause, returns to normal state - */ - function unpause() external onlyPauser { - paused = false; - emit Unpause(); - } - - /** - * @notice Updates the pauser address. - * @param _newPauser The address of the new pauser. - */ - function updatePauser(address _newPauser) external onlyOwner { - require(_newPauser != address(0), "Pausable: new pauser is the zero address"); - pauser = _newPauser; - emit PauserChanged(pauser); - } -} - -// contracts/util/SignatureChecker.sol -/** - * Copyright 2023 Circle Internet Financial, LTD. All rights reserved. - * - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @dev Signature verification helper that can be used instead of `ECRecover.recover` to seamlessly support both ECDSA - * signatures from externally owned accounts (EOAs) as well as ERC1271 signatures from smart contract wallets. - * - * Adapted from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/21bb89ef5bfc789b9333eb05e3ba2b7b284ac77c/contracts/utils/cryptography/SignatureChecker.sol - */ -library SignatureChecker { - /** - * @dev Checks if a signature is valid for a given signer and data hash. If the signer is a smart contract, the - * signature is validated against that smart contract using ERC1271, otherwise it's validated using `ECRecover.recover`. - * @param signer Address of the claimed signer - * @param digest Keccak-256 hash digest of the signed message - * @param signature Signature byte array associated with hash - */ - function isValidSignatureNow(address signer, bytes32 digest, bytes memory signature) - external - view - returns (bool) - { - if (!isContract(signer)) { - return ECRecover.recover(digest, signature) == signer; - } - return isValidERC1271SignatureNow(signer, digest, signature); - } - - /** - * @dev Checks if a signature is valid for a given signer and data hash. The signature is validated - * against the signer smart contract using ERC1271. - * @param signer Address of the claimed signer - * @param digest Keccak-256 hash digest of the signed message - * @param signature Signature byte array associated with hash - * - * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus - * change through time. It could return true at block N and false at block N+1 (or the opposite). - */ - function isValidERC1271SignatureNow(address signer, bytes32 digest, bytes memory signature) - internal - view - returns (bool) - { - (bool success, bytes memory result) = signer.staticcall( - abi.encodeWithSelector(IERC1271.isValidSignature.selector, digest, signature) - ); - return ( - success && result.length >= 32 - && abi.decode(result, (bytes32)) == bytes32(IERC1271.isValidSignature.selector) - ); - } - - /** - * @dev Checks if the input address is a smart contract. - */ - function isContract(address addr) internal view returns (bool) { - uint256 size; - assembly { - size := extcodesize(addr) - } - return size > 0; - } -} - -// contracts/v2/AbstractFiatTokenV2.sol -/** - * Copyright 2023 Circle Internet Financial, LTD. All rights reserved. - * - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -abstract contract AbstractFiatTokenV2 is AbstractFiatTokenV1 { - function _increaseAllowance(address owner, address spender, uint256 increment) - internal - virtual; - - function _decreaseAllowance(address owner, address spender, uint256 decrement) - internal - virtual; -} - -// node_modules/@openzeppelin/contracts/token/ERC20/SafeERC20.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 SafeMath for uint256; - 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' - // solhint-disable-next-line max-line-length - 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).add(value); - _callOptionalReturn( - token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance) - ); - } - - function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { - uint256 newAllowance = token.allowance(address(this), spender).sub( - value, "SafeERC20: decreased allowance below zero" - ); - _callOptionalReturn( - token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance) - ); - } - - /** - * @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 - // solhint-disable-next-line max-line-length - require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); - } - } -} - -// contracts/v1.1/Rescuable.sol -/** - * Copyright 2023 Circle Internet Financial, LTD. All rights reserved. - * - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -contract Rescuable is Ownable { - using SafeERC20 for IERC20; - - address private _rescuer; - - event RescuerChanged(address indexed newRescuer); - - /** - * @notice Returns current rescuer - * @return Rescuer's address - */ - function rescuer() external view returns (address) { - return _rescuer; - } - - /** - * @notice Revert if called by any account other than the rescuer. - */ - modifier onlyRescuer() { - require(msg.sender == _rescuer, "Rescuable: caller is not the rescuer"); - _; - } - - /** - * @notice Rescue ERC20 tokens locked up in this contract. - * @param tokenContract ERC20 token contract address - * @param to Recipient address - * @param amount Amount to withdraw - */ - function rescueERC20(IERC20 tokenContract, address to, uint256 amount) external onlyRescuer { - tokenContract.safeTransfer(to, amount); - } - - /** - * @notice Updates the rescuer address. - * @param newRescuer The address of the new rescuer. - */ - function updateRescuer(address newRescuer) external onlyOwner { - require(newRescuer != address(0), "Rescuable: new rescuer is the zero address"); - _rescuer = newRescuer; - emit RescuerChanged(newRescuer); - } -} - -// contracts/v1/FiatTokenV1.sol -/** - * Copyright 2023 Circle Internet Financial, LTD. All rights reserved. - * - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @title FiatToken - * @dev ERC20 Token backed by fiat reserves - */ -contract FiatTokenV1 is AbstractFiatTokenV1, Ownable, Pausable, Blacklistable { - using SafeMath for uint256; - - string public name; - string public symbol; - uint8 public decimals; - string public currency; - address public masterMinter; - bool internal initialized; - - /// @dev A mapping that stores the balance and blacklist states for a given address. - /// The first bit defines whether the address is blacklisted (1 if blacklisted, 0 otherwise). - /// The last 255 bits define the balance for the address. - mapping(address => uint256) internal balanceAndBlacklistStates; - mapping(address => mapping(address => uint256)) internal allowed; - uint256 internal totalSupply_ = 0; - mapping(address => bool) internal minters; - mapping(address => uint256) internal minterAllowed; - - event Mint(address indexed minter, address indexed to, uint256 amount); - event Burn(address indexed burner, uint256 amount); - event MinterConfigured(address indexed minter, uint256 minterAllowedAmount); - event MinterRemoved(address indexed oldMinter); - event MasterMinterChanged(address indexed newMasterMinter); - - /** - * @notice Initializes the fiat token contract. - * @param tokenName The name of the fiat token. - * @param tokenSymbol The symbol of the fiat token. - * @param tokenCurrency The fiat currency that the token represents. - * @param tokenDecimals The number of decimals that the token uses. - * @param newMasterMinter The masterMinter address for the fiat token. - * @param newPauser The pauser address for the fiat token. - * @param newBlacklister The blacklister address for the fiat token. - * @param newOwner The owner of the fiat token. - */ - function initialize( - string memory tokenName, - string memory tokenSymbol, - string memory tokenCurrency, - uint8 tokenDecimals, - address newMasterMinter, - address newPauser, - address newBlacklister, - address newOwner - ) public { - require(!initialized, "FiatToken: contract is already initialized"); - require(newMasterMinter != address(0), "FiatToken: new masterMinter is the zero address"); - require(newPauser != address(0), "FiatToken: new pauser is the zero address"); - require(newBlacklister != address(0), "FiatToken: new blacklister is the zero address"); - require(newOwner != address(0), "FiatToken: new owner is the zero address"); - - name = tokenName; - symbol = tokenSymbol; - currency = tokenCurrency; - decimals = tokenDecimals; - masterMinter = newMasterMinter; - pauser = newPauser; - blacklister = newBlacklister; - setOwner(newOwner); - initialized = true; - } - - /** - * @dev Throws if called by any account other than a minter. - */ - modifier onlyMinters() { - require(minters[msg.sender], "FiatToken: caller is not a minter"); - _; - } - - /** - * @notice Mints fiat tokens to an address. - * @param _to The address that will receive the minted tokens. - * @param _amount The amount of tokens to mint. Must be less than or equal - * to the minterAllowance of the caller. - * @return True if the operation was successful. - */ - function mint(address _to, uint256 _amount) - public - whenNotPaused - onlyMinters - notBlacklisted(msg.sender) - notBlacklisted(_to) - returns (bool) - { - require(_to != address(0), "FiatToken: mint to the zero address"); - require(_amount > 0, "FiatToken: mint amount not greater than 0"); - - uint256 mintingAllowedAmount = minterAllowed[msg.sender]; - require(_amount <= mintingAllowedAmount, "FiatToken: mint amount exceeds minterAllowance"); - - totalSupply_ = totalSupply_.add(_amount); - _setBalance(_to, _balanceOf(_to).add(_amount)); - minterAllowed[msg.sender] = mintingAllowedAmount.sub(_amount); - emit Mint(msg.sender, _to, _amount); - emit Transfer(address(0), _to, _amount); - return true; - } - - /** - * @dev Throws if called by any account other than the masterMinter - */ - modifier onlyMasterMinter() { - require(msg.sender == masterMinter, "FiatToken: caller is not the masterMinter"); - _; - } - - /** - * @notice Gets the minter allowance for an account. - * @param minter The address to check. - * @return The remaining minter allowance for the account. - */ - function minterAllowance(address minter) external view returns (uint256) { - return minterAllowed[minter]; - } - - /** - * @notice Checks if an account is a minter. - * @param account The address to check. - * @return True if the account is a minter, false if the account is not a minter. - */ - function isMinter(address account) external view returns (bool) { - return minters[account]; - } - - /** - * @notice Gets the remaining amount of fiat tokens a spender is allowed to transfer on - * behalf of the token owner. - * @param owner The token owner's address. - * @param spender The spender's address. - * @return The remaining allowance. - */ - function allowance(address owner, address spender) external view override returns (uint256) { - return allowed[owner][spender]; - } - - /** - * @notice Gets the totalSupply of the fiat token. - * @return The totalSupply of the fiat token. - */ - function totalSupply() external view override returns (uint256) { - return totalSupply_; - } - - /** - * @notice Gets the fiat token balance of an account. - * @param account The address to check. - * @return balance The fiat token balance of the account. - */ - function balanceOf(address account) external view override returns (uint256) { - return _balanceOf(account); - } - - /** - * @notice Sets a fiat token allowance for a spender to spend on behalf of the caller. - * @param spender The spender's address. - * @param value The allowance amount. - * @return True if the operation was successful. - */ - function approve(address spender, uint256 value) - external - virtual - override - whenNotPaused - notBlacklisted(msg.sender) - notBlacklisted(spender) - returns (bool) - { - _approve(msg.sender, spender, value); - return true; - } - - /** - * @dev Internal function to set allowance. - * @param owner Token owner's address. - * @param spender Spender's address. - * @param value Allowance amount. - */ - function _approve(address owner, address spender, uint256 value) internal override { - require(owner != address(0), "ERC20: approve from the zero address"); - require(spender != address(0), "ERC20: approve to the zero address"); - allowed[owner][spender] = value; - emit Approval(owner, spender, value); - } - - /** - * @notice Transfers tokens from an address to another by spending the caller's allowance. - * @dev The caller must have some fiat token allowance on the payer's tokens. - * @param from Payer's address. - * @param to Payee's address. - * @param value Transfer amount. - * @return True if the operation was successful. - */ - function transferFrom(address from, address to, uint256 value) - external - override - whenNotPaused - notBlacklisted(msg.sender) - notBlacklisted(from) - notBlacklisted(to) - returns (bool) - { - require(value <= allowed[from][msg.sender], "ERC20: transfer amount exceeds allowance"); - _transfer(from, to, value); - allowed[from][msg.sender] = allowed[from][msg.sender].sub(value); - return true; - } - - /** - * @notice Transfers tokens from the caller. - * @param to Payee's address. - * @param value Transfer amount. - * @return True if the operation was successful. - */ - function transfer(address to, uint256 value) - external - override - whenNotPaused - notBlacklisted(msg.sender) - notBlacklisted(to) - returns (bool) - { - _transfer(msg.sender, to, value); - return true; - } - - /** - * @dev Internal function to process transfers. - * @param from Payer's address. - * @param to Payee's address. - * @param value Transfer amount. - */ - function _transfer(address from, address to, uint256 value) internal override { - require(from != address(0), "ERC20: transfer from the zero address"); - require(to != address(0), "ERC20: transfer to the zero address"); - require(value <= _balanceOf(from), "ERC20: transfer amount exceeds balance"); - - _setBalance(from, _balanceOf(from).sub(value)); - _setBalance(to, _balanceOf(to).add(value)); - emit Transfer(from, to, value); - } - - /** - * @notice Adds or updates a new minter with a mint allowance. - * @param minter The address of the minter. - * @param minterAllowedAmount The minting amount allowed for the minter. - * @return True if the operation was successful. - */ - function configureMinter(address minter, uint256 minterAllowedAmount) - external - whenNotPaused - onlyMasterMinter - returns (bool) - { - minters[minter] = true; - minterAllowed[minter] = minterAllowedAmount; - emit MinterConfigured(minter, minterAllowedAmount); - return true; - } - - /** - * @notice Removes a minter. - * @param minter The address of the minter to remove. - * @return True if the operation was successful. - */ - function removeMinter(address minter) external onlyMasterMinter returns (bool) { - minters[minter] = false; - minterAllowed[minter] = 0; - emit MinterRemoved(minter); - return true; - } - - /** - * @notice Allows a minter to burn some of its own tokens. - * @dev The caller must be a minter, must not be blacklisted, and the amount to burn - * should be less than or equal to the account's balance. - * @param _amount the amount of tokens to be burned. - */ - function burn(uint256 _amount) public whenNotPaused onlyMinters notBlacklisted(msg.sender) { - uint256 balance = _balanceOf(msg.sender); - require(_amount > 0, "FiatToken: burn amount not greater than 0"); - require(balance >= _amount, "FiatToken: burn amount exceeds balance"); - - totalSupply_ = totalSupply_.sub(_amount); - _setBalance(msg.sender, balance.sub(_amount)); - emit Burn(msg.sender, _amount); - emit Transfer(msg.sender, address(0), _amount); - } - - /** - * @notice Updates the master minter address. - * @param _newMasterMinter The address of the new master minter. - */ - function updateMasterMinter(address _newMasterMinter) external onlyOwner { - require(_newMasterMinter != address(0), "FiatToken: new masterMinter is the zero address"); - masterMinter = _newMasterMinter; - emit MasterMinterChanged(masterMinter); - } - - /** - * - */ - function _blacklist(address _account) internal override { - _setBlacklistState(_account, true); - } - - /** - * - */ - function _unBlacklist(address _account) internal override { - _setBlacklistState(_account, false); - } - - /** - * @dev Helper method that sets the blacklist state of an account. - * @param _account The address of the account. - * @param _shouldBlacklist True if the account should be blacklisted, false if the account should be unblacklisted. - */ - function _setBlacklistState(address _account, bool _shouldBlacklist) internal virtual { - _deprecatedBlacklisted[_account] = _shouldBlacklist; - } - - /** - * @dev Helper method that sets the balance of an account. - * @param _account The address of the account. - * @param _balance The new fiat token balance of the account. - */ - function _setBalance(address _account, uint256 _balance) internal virtual { - balanceAndBlacklistStates[_account] = _balance; - } - - /** - * - */ - function _isBlacklisted(address _account) internal view virtual override returns (bool) { - return _deprecatedBlacklisted[_account]; - } - - /** - * @dev Helper method to obtain the balance of an account. - * @param _account The address of the account. - * @return The fiat token balance of the account. - */ - function _balanceOf(address _account) internal view virtual returns (uint256) { - return balanceAndBlacklistStates[_account]; - } -} - -// contracts/v2/EIP2612.sol -/** - * Copyright 2023 Circle Internet Financial, LTD. All rights reserved. - * - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @title EIP-2612 - * @notice Provide internal implementation for gas-abstracted approvals - */ -abstract contract EIP2612 is AbstractFiatTokenV2, EIP712Domain { - // keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)") - bytes32 public constant PERMIT_TYPEHASH = - 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9; - - mapping(address => uint256) private _permitNonces; - - /** - * @notice Nonces for permit - * @param owner Token owner's address (Authorizer) - * @return Next nonce - */ - function nonces(address owner) external view returns (uint256) { - return _permitNonces[owner]; - } - - /** - * @notice Verify a signed approval permit and execute if valid - * @param owner Token owner's address (Authorizer) - * @param spender Spender's address - * @param value Amount of allowance - * @param deadline The time at which the signature expires (unix time), or max uint256 value to signal no expiration - * @param v v of the signature - * @param r r of the signature - * @param s s of the signature - */ - function _permit( - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) internal { - _permit(owner, spender, value, deadline, abi.encodePacked(r, s, v)); - } - - /** - * @notice Verify a signed approval permit and execute if valid - * @dev EOA wallet signatures should be packed in the order of r, s, v. - * @param owner Token owner's address (Authorizer) - * @param spender Spender's address - * @param value Amount of allowance - * @param deadline The time at which the signature expires (unix time), or max uint256 value to signal no expiration - * @param signature Signature byte array signed by an EOA wallet or a contract wallet - */ - function _permit( - address owner, - address spender, - uint256 value, - uint256 deadline, - bytes memory signature - ) internal { - require( - deadline == type(uint256).max || deadline >= block.timestamp, - "FiatTokenV2: permit is expired" - ); - - bytes32 typedDataHash = MessageHashUtils.toTypedDataHash( - _domainSeparator(), - keccak256( - abi.encode(PERMIT_TYPEHASH, owner, spender, value, _permitNonces[owner]++, deadline) - ) - ); - require( - SignatureChecker.isValidSignatureNow(owner, typedDataHash, signature), - "EIP2612: invalid signature" - ); - - _approve(owner, spender, value); - } -} - -// contracts/v2/EIP3009.sol -/** - * Copyright 2023 Circle Internet Financial, LTD. All rights reserved. - * - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @title EIP-3009 - * @notice Provide internal implementation for gas-abstracted transfers - * @dev Contracts that inherit from this must wrap these with publicly - * accessible functions, optionally adding modifiers where necessary - */ -abstract contract EIP3009 is AbstractFiatTokenV2, EIP712Domain { - // keccak256("TransferWithAuthorization(address from,address to,uint256 value,uint256 validAfter,uint256 validBefore,bytes32 nonce)") - bytes32 public constant TRANSFER_WITH_AUTHORIZATION_TYPEHASH = - 0x7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a2267; - - // keccak256("ReceiveWithAuthorization(address from,address to,uint256 value,uint256 validAfter,uint256 validBefore,bytes32 nonce)") - bytes32 public constant RECEIVE_WITH_AUTHORIZATION_TYPEHASH = - 0xd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de8; - - // keccak256("CancelAuthorization(address authorizer,bytes32 nonce)") - bytes32 public constant CANCEL_AUTHORIZATION_TYPEHASH = - 0x158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a1597429; - - /** - * @dev authorizer address => nonce => bool (true if nonce is used) - */ - mapping(address => mapping(bytes32 => bool)) private _authorizationStates; - - event AuthorizationUsed(address indexed authorizer, bytes32 indexed nonce); - event AuthorizationCanceled(address indexed authorizer, bytes32 indexed nonce); - - /** - * @notice Returns the state of an authorization - * @dev Nonces are randomly generated 32-byte data unique to the - * authorizer's address - * @param authorizer Authorizer's address - * @param nonce Nonce of the authorization - * @return True if the nonce is used - */ - function authorizationState(address authorizer, bytes32 nonce) external view returns (bool) { - return _authorizationStates[authorizer][nonce]; - } - - /** - * @notice Execute a transfer with a signed authorization - * @param from Payer's address (Authorizer) - * @param to Payee's address - * @param value Amount to be transferred - * @param validAfter The time after which this is valid (unix time) - * @param validBefore The time before which this is valid (unix time) - * @param nonce Unique nonce - * @param v v of the signature - * @param r r of the signature - * @param s s of the signature - */ - function _transferWithAuthorization( - address from, - address to, - uint256 value, - uint256 validAfter, - uint256 validBefore, - bytes32 nonce, - uint8 v, - bytes32 r, - bytes32 s - ) internal { - _transferWithAuthorization( - from, to, value, validAfter, validBefore, nonce, abi.encodePacked(r, s, v) - ); - } - - /** - * @notice Execute a transfer with a signed authorization - * @dev EOA wallet signatures should be packed in the order of r, s, v. - * @param from Payer's address (Authorizer) - * @param to Payee's address - * @param value Amount to be transferred - * @param validAfter The time after which this is valid (unix time) - * @param validBefore The time before which this is valid (unix time) - * @param nonce Unique nonce - * @param signature Signature byte array produced by an EOA wallet or a contract wallet - */ - function _transferWithAuthorization( - address from, - address to, - uint256 value, - uint256 validAfter, - uint256 validBefore, - bytes32 nonce, - bytes memory signature - ) internal { - _requireValidAuthorization(from, nonce, validAfter, validBefore); - _requireValidSignature( - from, - keccak256( - abi.encode( - TRANSFER_WITH_AUTHORIZATION_TYPEHASH, - from, - to, - value, - validAfter, - validBefore, - nonce - ) - ), - signature - ); - - _markAuthorizationAsUsed(from, nonce); - _transfer(from, to, value); - } - - /** - * @notice Receive a transfer with a signed authorization from the payer - * @dev This has an additional check to ensure that the payee's address - * matches the caller of this function to prevent front-running attacks. - * @param from Payer's address (Authorizer) - * @param to Payee's address - * @param value Amount to be transferred - * @param validAfter The time after which this is valid (unix time) - * @param validBefore The time before which this is valid (unix time) - * @param nonce Unique nonce - * @param v v of the signature - * @param r r of the signature - * @param s s of the signature - */ - function _receiveWithAuthorization( - address from, - address to, - uint256 value, - uint256 validAfter, - uint256 validBefore, - bytes32 nonce, - uint8 v, - bytes32 r, - bytes32 s - ) internal { - _receiveWithAuthorization( - from, to, value, validAfter, validBefore, nonce, abi.encodePacked(r, s, v) - ); - } - - /** - * @notice Receive a transfer with a signed authorization from the payer - * @dev This has an additional check to ensure that the payee's address - * matches the caller of this function to prevent front-running attacks. - * EOA wallet signatures should be packed in the order of r, s, v. - * @param from Payer's address (Authorizer) - * @param to Payee's address - * @param value Amount to be transferred - * @param validAfter The time after which this is valid (unix time) - * @param validBefore The time before which this is valid (unix time) - * @param nonce Unique nonce - * @param signature Signature byte array produced by an EOA wallet or a contract wallet - */ - function _receiveWithAuthorization( - address from, - address to, - uint256 value, - uint256 validAfter, - uint256 validBefore, - bytes32 nonce, - bytes memory signature - ) internal { - require(to == msg.sender, "FiatTokenV2: caller must be the payee"); - _requireValidAuthorization(from, nonce, validAfter, validBefore); - _requireValidSignature( - from, - keccak256( - abi.encode( - RECEIVE_WITH_AUTHORIZATION_TYPEHASH, - from, - to, - value, - validAfter, - validBefore, - nonce - ) - ), - signature - ); - - _markAuthorizationAsUsed(from, nonce); - _transfer(from, to, value); - } - - /** - * @notice Attempt to cancel an authorization - * @param authorizer Authorizer's address - * @param nonce Nonce of the authorization - * @param v v of the signature - * @param r r of the signature - * @param s s of the signature - */ - function _cancelAuthorization(address authorizer, bytes32 nonce, uint8 v, bytes32 r, bytes32 s) - internal - { - _cancelAuthorization(authorizer, nonce, abi.encodePacked(r, s, v)); - } - - /** - * @notice Attempt to cancel an authorization - * @dev EOA wallet signatures should be packed in the order of r, s, v. - * @param authorizer Authorizer's address - * @param nonce Nonce of the authorization - * @param signature Signature byte array produced by an EOA wallet or a contract wallet - */ - function _cancelAuthorization(address authorizer, bytes32 nonce, bytes memory signature) - internal - { - _requireUnusedAuthorization(authorizer, nonce); - _requireValidSignature( - authorizer, - keccak256(abi.encode(CANCEL_AUTHORIZATION_TYPEHASH, authorizer, nonce)), - signature - ); - - _authorizationStates[authorizer][nonce] = true; - emit AuthorizationCanceled(authorizer, nonce); - } - - /** - * @notice Validates that signature against input data struct - * @param signer Signer's address - * @param dataHash Hash of encoded data struct - * @param signature Signature byte array produced by an EOA wallet or a contract wallet - */ - function _requireValidSignature(address signer, bytes32 dataHash, bytes memory signature) - private - view - { - require( - SignatureChecker.isValidSignatureNow( - signer, MessageHashUtils.toTypedDataHash(_domainSeparator(), dataHash), signature - ), - "FiatTokenV2: invalid signature" - ); - } - - /** - * @notice Check that an authorization is unused - * @param authorizer Authorizer's address - * @param nonce Nonce of the authorization - */ - function _requireUnusedAuthorization(address authorizer, bytes32 nonce) private view { - require( - !_authorizationStates[authorizer][nonce], - "FiatTokenV2: authorization is used or canceled" - ); - } - - /** - * @notice Check that authorization is valid - * @param authorizer Authorizer's address - * @param nonce Nonce of the authorization - * @param validAfter The time after which this is valid (unix time) - * @param validBefore The time before which this is valid (unix time) - */ - function _requireValidAuthorization( - address authorizer, - bytes32 nonce, - uint256 validAfter, - uint256 validBefore - ) private view { - require(block.timestamp > validAfter, "FiatTokenV2: authorization is not yet valid"); - require(block.timestamp < validBefore, "FiatTokenV2: authorization is expired"); - _requireUnusedAuthorization(authorizer, nonce); - } - - /** - * @notice Mark an authorization as used - * @param authorizer Authorizer's address - * @param nonce Nonce of the authorization - */ - function _markAuthorizationAsUsed(address authorizer, bytes32 nonce) private { - _authorizationStates[authorizer][nonce] = true; - emit AuthorizationUsed(authorizer, nonce); - } -} - -// contracts/v1.1/FiatTokenV1_1.sol -/** - * Copyright 2023 Circle Internet Financial, LTD. All rights reserved. - * - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @title FiatTokenV1_1 - * @dev ERC20 Token backed by fiat reserves - */ -contract FiatTokenV1_1 is FiatTokenV1, Rescuable {} - -// contracts/v2/FiatTokenV2.sol -/** - * Copyright 2023 Circle Internet Financial, LTD. All rights reserved. - * - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @title FiatToken V2 - * @notice ERC20 Token backed by fiat reserves, version 2 - */ -contract FiatTokenV2 is FiatTokenV1_1, EIP3009, EIP2612 { - uint8 internal _initializedVersion; - - /** - * @notice Initialize v2 - * @param newName New token name - */ - function initializeV2(string calldata newName) external { - // solhint-disable-next-line reason-string - require(initialized && _initializedVersion == 0); - name = newName; - _DEPRECATED_CACHED_DOMAIN_SEPARATOR = EIP712.makeDomainSeparator(newName, "2"); - _initializedVersion = 1; - } - - /** - * @notice Increase the allowance by a given increment - * @param spender Spender's address - * @param increment Amount of increase in allowance - * @return True if successful - */ - function increaseAllowance(address spender, uint256 increment) - external - virtual - whenNotPaused - notBlacklisted(msg.sender) - notBlacklisted(spender) - returns (bool) - { - _increaseAllowance(msg.sender, spender, increment); - return true; - } - - /** - * @notice Decrease the allowance by a given decrement - * @param spender Spender's address - * @param decrement Amount of decrease in allowance - * @return True if successful - */ - function decreaseAllowance(address spender, uint256 decrement) - external - virtual - whenNotPaused - notBlacklisted(msg.sender) - notBlacklisted(spender) - returns (bool) - { - _decreaseAllowance(msg.sender, spender, decrement); - return true; - } - - /** - * @notice Execute a transfer with a signed authorization - * @param from Payer's address (Authorizer) - * @param to Payee's address - * @param value Amount to be transferred - * @param validAfter The time after which this is valid (unix time) - * @param validBefore The time before which this is valid (unix time) - * @param nonce Unique nonce - * @param v v of the signature - * @param r r of the signature - * @param s s of the signature - */ - function transferWithAuthorization( - address from, - address to, - uint256 value, - uint256 validAfter, - uint256 validBefore, - bytes32 nonce, - uint8 v, - bytes32 r, - bytes32 s - ) external whenNotPaused notBlacklisted(from) notBlacklisted(to) { - _transferWithAuthorization(from, to, value, validAfter, validBefore, nonce, v, r, s); - } - - /** - * @notice Receive a transfer with a signed authorization from the payer - * @dev This has an additional check to ensure that the payee's address - * matches the caller of this function to prevent front-running attacks. - * @param from Payer's address (Authorizer) - * @param to Payee's address - * @param value Amount to be transferred - * @param validAfter The time after which this is valid (unix time) - * @param validBefore The time before which this is valid (unix time) - * @param nonce Unique nonce - * @param v v of the signature - * @param r r of the signature - * @param s s of the signature - */ - function receiveWithAuthorization( - address from, - address to, - uint256 value, - uint256 validAfter, - uint256 validBefore, - bytes32 nonce, - uint8 v, - bytes32 r, - bytes32 s - ) external whenNotPaused notBlacklisted(from) notBlacklisted(to) { - _receiveWithAuthorization(from, to, value, validAfter, validBefore, nonce, v, r, s); - } - - /** - * @notice Attempt to cancel an authorization - * @dev Works only if the authorization is not yet used. - * @param authorizer Authorizer's address - * @param nonce Nonce of the authorization - * @param v v of the signature - * @param r r of the signature - * @param s s of the signature - */ - function cancelAuthorization(address authorizer, bytes32 nonce, uint8 v, bytes32 r, bytes32 s) - external - whenNotPaused - { - _cancelAuthorization(authorizer, nonce, v, r, s); - } - - /** - * @notice Update allowance with a signed permit - * @param owner Token owner's address (Authorizer) - * @param spender Spender's address - * @param value Amount of allowance - * @param deadline The time at which the signature expires (unix time), or max uint256 value to signal no expiration - * @param v v of the signature - * @param r r of the signature - * @param s s of the signature - */ - function permit( - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) external virtual whenNotPaused notBlacklisted(owner) notBlacklisted(spender) { - _permit(owner, spender, value, deadline, v, r, s); - } - - /** - * @dev Internal function to increase the allowance by a given increment - * @param owner Token owner's address - * @param spender Spender's address - * @param increment Amount of increase - */ - function _increaseAllowance(address owner, address spender, uint256 increment) - internal - override - { - _approve(owner, spender, allowed[owner][spender] + increment); - } - - /** - * @dev Internal function to decrease the allowance by a given decrement - * @param owner Token owner's address - * @param spender Spender's address - * @param decrement Amount of decrease - */ - function _decreaseAllowance(address owner, address spender, uint256 decrement) - internal - override - { - _approve(owner, spender, allowed[owner][spender] - decrement); - } -} - -// contracts/v2/FiatTokenV2_1.sol -/** - * Copyright 2023 Circle Internet Financial, LTD. All rights reserved. - * - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// solhint-disable func-name-mixedcase - -/** - * @title FiatToken V2.1 - * @notice ERC20 Token backed by fiat reserves, version 2.1 - */ -contract FiatTokenV2_1 is FiatTokenV2 { - /** - * @notice Initialize v2.1 - * @param lostAndFound The address to which the locked funds are sent - */ - function initializeV2_1(address lostAndFound) external { - // solhint-disable-next-line reason-string - require(_initializedVersion == 1); - - uint256 lockedAmount = _balanceOf(address(this)); - if (lockedAmount > 0) { - _transfer(address(this), lostAndFound, lockedAmount); - } - _blacklist(address(this)); - - _initializedVersion = 2; - } - - /** - * @notice Version string for the EIP712 domain separator - * @return Version string - */ - function version() external pure returns (string memory) { - return "2"; - } -} - -// contracts/v2/FiatTokenV2_2.sol -/** - * Copyright 2023 Circle Internet Financial, LTD. All rights reserved. - * - * - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// solhint-disable-line no-unused-import -// solhint-disable-line no-unused-import -// solhint-disable-line no-unused-import -// solhint-disable-line no-unused-import - -// solhint-disable func-name-mixedcase - -/** - * @title FiatToken V2.2 - * @notice ERC20 Token backed by fiat reserves, version 2.2 - */ -contract FiatTokenV2_2 is FiatTokenV2_1 { - /** - * @notice Initialize v2.2 - * @param accountsToBlacklist A list of accounts to migrate from the old blacklist - * @param newSymbol New token symbol - * data structure to the new blacklist data structure. - */ - function initializeV2_2(address[] calldata accountsToBlacklist, string calldata newSymbol) - external - { - // solhint-disable-next-line reason-string - require(_initializedVersion == 2); - - // Update fiat token symbol - symbol = newSymbol; - - // Add previously blacklisted accounts to the new blacklist data structure - // and remove them from the old blacklist data structure. - for (uint256 i = 0; i < accountsToBlacklist.length; i++) { - require( - _deprecatedBlacklisted[accountsToBlacklist[i]], - "FiatTokenV2_2: Blacklisting previously unblacklisted account!" - ); - _blacklist(accountsToBlacklist[i]); - delete _deprecatedBlacklisted[accountsToBlacklist[i]]; - } - _blacklist(address(this)); - delete _deprecatedBlacklisted[address(this)]; - - _initializedVersion = 3; - } - - /** - * @dev Internal function to get the current chain id. - * @return The current chain id. - */ - function _chainId() internal view virtual returns (uint256) { - uint256 chainId; - assembly { - chainId := chainid() - } - return chainId; - } - - /** - * - */ - function _domainSeparator() internal view override returns (bytes32) { - return EIP712.makeDomainSeparator(name, "2", _chainId()); - } - - /** - * @notice Update allowance with a signed permit - * @dev EOA wallet signatures should be packed in the order of r, s, v. - * @param owner Token owner's address (Authorizer) - * @param spender Spender's address - * @param value Amount of allowance - * @param deadline The time at which the signature expires (unix time), or max uint256 value to signal no expiration - * @param signature Signature bytes signed by an EOA wallet or a contract wallet - */ - function permit( - address owner, - address spender, - uint256 value, - uint256 deadline, - bytes memory signature - ) external whenNotPaused { - _permit(owner, spender, value, deadline, signature); - } - - /** - * @notice Execute a transfer with a signed authorization - * @dev EOA wallet signatures should be packed in the order of r, s, v. - * @param from Payer's address (Authorizer) - * @param to Payee's address - * @param value Amount to be transferred - * @param validAfter The time after which this is valid (unix time) - * @param validBefore The time before which this is valid (unix time) - * @param nonce Unique nonce - * @param signature Signature bytes signed by an EOA wallet or a contract wallet - */ - function transferWithAuthorization( - address from, - address to, - uint256 value, - uint256 validAfter, - uint256 validBefore, - bytes32 nonce, - bytes memory signature - ) external whenNotPaused notBlacklisted(from) notBlacklisted(to) { - _transferWithAuthorization(from, to, value, validAfter, validBefore, nonce, signature); - } - - /** - * @notice Receive a transfer with a signed authorization from the payer - * @dev This has an additional check to ensure that the payee's address - * matches the caller of this function to prevent front-running attacks. - * EOA wallet signatures should be packed in the order of r, s, v. - * @param from Payer's address (Authorizer) - * @param to Payee's address - * @param value Amount to be transferred - * @param validAfter The time after which this is valid (unix time) - * @param validBefore The time before which this is valid (unix time) - * @param nonce Unique nonce - * @param signature Signature bytes signed by an EOA wallet or a contract wallet - */ - function receiveWithAuthorization( - address from, - address to, - uint256 value, - uint256 validAfter, - uint256 validBefore, - bytes32 nonce, - bytes memory signature - ) external whenNotPaused notBlacklisted(from) notBlacklisted(to) { - _receiveWithAuthorization(from, to, value, validAfter, validBefore, nonce, signature); - } - - /** - * @notice Attempt to cancel an authorization - * @dev Works only if the authorization is not yet used. - * EOA wallet signatures should be packed in the order of r, s, v. - * @param authorizer Authorizer's address - * @param nonce Nonce of the authorization - * @param signature Signature bytes signed by an EOA wallet or a contract wallet - */ - function cancelAuthorization(address authorizer, bytes32 nonce, bytes memory signature) - external - whenNotPaused - { - _cancelAuthorization(authorizer, nonce, signature); - } - - /** - * @dev Helper method that sets the blacklist state of an account on balanceAndBlacklistStates. - * If _shouldBlacklist is true, we apply a (1 << 255) bitmask with an OR operation on the - * account's balanceAndBlacklistState. This flips the high bit for the account to 1, - * indicating that the account is blacklisted. - * - * If _shouldBlacklist if false, we reset the account's balanceAndBlacklistStates to their - * balances. This clears the high bit for the account, indicating that the account is unblacklisted. - * @param _account The address of the account. - * @param _shouldBlacklist True if the account should be blacklisted, false if the account should be unblacklisted. - */ - function _setBlacklistState(address _account, bool _shouldBlacklist) internal override { - balanceAndBlacklistStates[_account] = _shouldBlacklist - ? balanceAndBlacklistStates[_account] | (1 << 255) - : _balanceOf(_account); - } - - /** - * @dev Helper method that sets the balance of an account on balanceAndBlacklistStates. - * Since balances are stored in the last 255 bits of the balanceAndBlacklistStates value, - * we need to ensure that the updated balance does not exceed (2^255 - 1). - * Since blacklisted accounts' balances cannot be updated, the method will also - * revert if the account is blacklisted - * @param _account The address of the account. - * @param _balance The new fiat token balance of the account (max: (2^255 - 1)). - */ - function _setBalance(address _account, uint256 _balance) internal override { - require(_balance <= ((1 << 255) - 1), "FiatTokenV2_2: Balance exceeds (2^255 - 1)"); - require(!_isBlacklisted(_account), "FiatTokenV2_2: Account is blacklisted"); - - balanceAndBlacklistStates[_account] = _balance; - } - - /** - * - */ - function _isBlacklisted(address _account) internal view override returns (bool) { - return balanceAndBlacklistStates[_account] >> 255 == 1; - } - - /** - * @dev Helper method to obtain the balance of an account. Since balances - * are stored in the last 255 bits of the balanceAndBlacklistStates value, - * we apply a ((1 << 255) - 1) bit bitmask with an AND operation on the - * balanceAndBlacklistState to obtain the balance. - * @param _account The address of the account. - * @return The fiat token balance of the account. - */ - function _balanceOf(address _account) internal view override returns (uint256) { - return balanceAndBlacklistStates[_account] & ((1 << 255) - 1); - } - - /** - * - */ - function approve(address spender, uint256 value) - external - override(FiatTokenV1, IERC20) - whenNotPaused - returns (bool) - { - _approve(msg.sender, spender, value); - return true; - } - - /** - * - */ - function permit( - address owner, - address spender, - uint256 value, - uint256 deadline, - uint8 v, - bytes32 r, - bytes32 s - ) external override whenNotPaused { - _permit(owner, spender, value, deadline, v, r, s); - } - - /** - * - */ - function increaseAllowance(address spender, uint256 increment) - external - override - whenNotPaused - returns (bool) - { - _increaseAllowance(msg.sender, spender, increment); - return true; - } - - /** - * - */ - function decreaseAllowance(address spender, uint256 decrement) - external - override - whenNotPaused - returns (bool) - { - _decreaseAllowance(msg.sender, spender, decrement); - return true; - } -} - -import {IArbToken} from "../arbitrum/IArbToken.sol"; - -/** - * @title A custom token contract that is based on Circle's FiatToken implementation, - * but also implements IArbToken so it can be used as bridged USDC in Arbitrum token bridge. - * This implementation of bridged USDC can be upgraded to native USDC due to storage compatibility. - * @dev - */ -contract FiatTokenV2_2_ArbCompatible is FiatTokenV2_2, IArbToken { - address public l2Gateway; - address public override l1Address; - - modifier onlyGateway() { - require(msg.sender == l2Gateway, "ONLY_GATEWAY"); - _; - } - - /** - * @notice initialize the token - * @param l2Gateway_ L2 gateway this token communicates with - * @param l1Counterpart_ L1 address of ERC20 - */ - function initialize_ArbCompatible(address l2Gateway_, address l1Counterpart_) external { - // initializeV2_2 of FiatTokenV2_2 sets version to 3 - require(_initializedVersion == 3); - require(l2Gateway_ != address(0), "INVALID_GATEWAY"); - require(l2Gateway == address(0), "ALREADY_INIT"); - l2Gateway = l2Gateway_; - l1Address = l1Counterpart_; - } - - /** - * @notice Mint tokens on L2. Callable path is L1Gateway depositToken (which handles L1 escrow), which triggers L2Gateway, which calls this - * @param account recipient of tokens - * @param amount amount of tokens minted - */ - function bridgeMint(address account, uint256 amount) public virtual override onlyGateway { - mint(account, amount); - } - - /** - * @notice Burn tokens on L2. - * @dev only the token bridge can call this - * @param account owner of tokens - * @param amount amount of tokens burnt - */ - function bridgeBurn(address account, uint256 amount) public virtual override onlyGateway { - _burn(account, amount); - } - - /** - * @notice Allows a minter to burn some of its own tokens. - * @dev The caller must be a minter, must not be blacklisted, and the amount to burn - * should be less than or equal to the account's balance. - * @param _amount the amount of tokens to be burned. - */ - function _burn(address _account, uint256 _amount) - internal - whenNotPaused - onlyMinters - notBlacklisted(_account) - { - uint256 balance = _balanceOf(_account); - require(_amount > 0, "FiatToken: burn amount not greater than 0"); - require(balance >= _amount, "FiatToken: burn amount exceeds balance"); - - totalSupply_ = totalSupply_ - _amount; - _setBalance(_account, balance - _amount); - emit Burn(_account, _amount); - emit Transfer(_account, address(0), _amount); - } -} diff --git a/contracts/tokenbridge/test/IFiatTokenArbitrumOrbitV2_2.sol b/contracts/tokenbridge/test/IFiatTokenArbitrumOrbitV2_2.sol new file mode 100644 index 0000000000..9cf552c0a1 --- /dev/null +++ b/contracts/tokenbridge/test/IFiatTokenArbitrumOrbitV2_2.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.0; + +interface IFiatTokenArbitrumOrbitV2_2 { + function initialize( + string memory tokenName, + string memory tokenSymbol, + string memory tokenCurrency, + uint8 tokenDecimals, + address newMasterMinter, + address newPauser, + address newBlacklister, + address newOwner + ) external; + function initializeV2(string calldata newName) external; + function initializeV2_1(address lostAndFound) external; + function initializeV2_2(address[] calldata accountsToBlacklist, string calldata newSymbol) + external; + function initializeArbitrumOrbit(address _l2Gateway, address _l1Token) external; +} diff --git a/test-foundry/L2USDCCustomGateway.t.sol b/test-foundry/L2USDCCustomGateway.t.sol index 33c698701a..7c2146c1a9 100644 --- a/test-foundry/L2USDCCustomGateway.t.sol +++ b/test-foundry/L2USDCCustomGateway.t.sol @@ -9,6 +9,8 @@ import {L1USDCCustomGateway} from "contracts/tokenbridge/ethereum/gateway/L1USDC import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import {AddressAliasHelper} from "contracts/tokenbridge/libraries/AddressAliasHelper.sol"; import {L2GatewayToken} from "contracts/tokenbridge/libraries/L2GatewayToken.sol"; +import {IFiatTokenArbitrumOrbitV2_2} from + "contracts/tokenbridge/test/IFiatTokenArbitrumOrbitV2_2.sol"; import {TestUtil} from "./util/TestUtil.sol"; contract L2USDCCustomGatewayTest is L2ArbitrumGatewayTest { @@ -24,7 +26,7 @@ contract L2USDCCustomGatewayTest is L2ArbitrumGatewayTest { address bridgedUsdcLogic = TestUtil.deployBridgedUsdcToken(); l2USDC = TestUtil.deployProxy(bridgedUsdcLogic); - FiatTokenArbitrumOrbitV2_2(l2USDC).initialize( + IFiatTokenArbitrumOrbitV2_2(l2USDC).initialize( "USDC token", "USDC.e", "USD", @@ -34,10 +36,10 @@ contract L2USDCCustomGatewayTest is L2ArbitrumGatewayTest { makeAddr("newBlacklister"), owner ); - FiatTokenArbitrumOrbitV2_2(l2USDC).initializeV2("USDC"); - FiatTokenArbitrumOrbitV2_2(l2USDC).initializeV2_1(makeAddr("lostAndFound")); - FiatTokenArbitrumOrbitV2_2(l2USDC).initializeV2_2(new address[](0), "USDC.e"); - FiatTokenArbitrumOrbitV2_2(l2USDC).initializeArbitrumOrbit(address(l2USDCGateway), l1USDC); + IFiatTokenArbitrumOrbitV2_2(l2USDC).initializeV2("USDC"); + IFiatTokenArbitrumOrbitV2_2(l2USDC).initializeV2_1(makeAddr("lostAndFound")); + IFiatTokenArbitrumOrbitV2_2(l2USDC).initializeV2_2(new address[](0), "USDC.e"); + IFiatTokenArbitrumOrbitV2_2(l2USDC).initializeArbitrumOrbit(address(l2USDCGateway), l1USDC); l2USDCGateway.initialize(l1Counterpart, router, l1USDC, l2USDC, owner); } From 0c899aee11fd5e44b15cc132a37fdf71a88db2cf Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Fri, 7 Jun 2024 11:19:10 +0200 Subject: [PATCH 11/20] Remove unused --- remappings.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/remappings.txt b/remappings.txt index 007c4faeda..1c717ff353 100644 --- a/remappings.txt +++ b/remappings.txt @@ -4,4 +4,3 @@ forge-std/=lib/forge-std/src/ @openzeppelin/contracts/=node_modules/@openzeppelin/contracts/ @arbitrum=node_modules/@arbitrum @offchainlabs=node_modules/@offchainlabs -@solady=node_modules/solady From 53dc0d2f80c63e78d8561652e104767a10273d2a Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Fri, 7 Jun 2024 14:38:43 +0200 Subject: [PATCH 12/20] Set minter in separate call --- .../test/IFiatTokenArbitrumOrbitV2_2.sol | 1 + test-foundry/L2USDCCustomGateway.t.sol | 18 ++++++++++++++++-- test-foundry/util/TestUtil.sol | 6 +++--- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/contracts/tokenbridge/test/IFiatTokenArbitrumOrbitV2_2.sol b/contracts/tokenbridge/test/IFiatTokenArbitrumOrbitV2_2.sol index 9cf552c0a1..c4b1cce3b7 100644 --- a/contracts/tokenbridge/test/IFiatTokenArbitrumOrbitV2_2.sol +++ b/contracts/tokenbridge/test/IFiatTokenArbitrumOrbitV2_2.sol @@ -17,4 +17,5 @@ interface IFiatTokenArbitrumOrbitV2_2 { function initializeV2_2(address[] calldata accountsToBlacklist, string calldata newSymbol) external; function initializeArbitrumOrbit(address _l2Gateway, address _l1Token) external; + function configureMinter(address minter, uint256 minterAllowedAmount) external; } diff --git a/test-foundry/L2USDCCustomGateway.t.sol b/test-foundry/L2USDCCustomGateway.t.sol index 7c2146c1a9..53e52f6bf0 100644 --- a/test-foundry/L2USDCCustomGateway.t.sol +++ b/test-foundry/L2USDCCustomGateway.t.sol @@ -8,7 +8,7 @@ import {L2USDCCustomGateway} from "contracts/tokenbridge/arbitrum/gateway/L2USDC import {L1USDCCustomGateway} from "contracts/tokenbridge/ethereum/gateway/L1USDCCustomGateway.sol"; import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import {AddressAliasHelper} from "contracts/tokenbridge/libraries/AddressAliasHelper.sol"; -import {L2GatewayToken} from "contracts/tokenbridge/libraries/L2GatewayToken.sol"; +import {L2GatewayToken, IArbToken} from "contracts/tokenbridge/libraries/L2GatewayToken.sol"; import {IFiatTokenArbitrumOrbitV2_2} from "contracts/tokenbridge/test/IFiatTokenArbitrumOrbitV2_2.sol"; import {TestUtil} from "./util/TestUtil.sol"; @@ -19,6 +19,7 @@ contract L2USDCCustomGatewayTest is L2ArbitrumGatewayTest { address public l2USDC; address public user = makeAddr("usdc_user"); address public owner = makeAddr("l2gw-owner"); + address masterMinter = makeAddr("newMasterMinter"); function setUp() public virtual { l2USDCGateway = new L2USDCCustomGateway(); @@ -31,7 +32,7 @@ contract L2USDCCustomGatewayTest is L2ArbitrumGatewayTest { "USDC.e", "USD", uint8(6), - makeAddr("newMasterMinter"), + masterMinter, makeAddr("newPauser"), makeAddr("newBlacklister"), owner @@ -41,6 +42,11 @@ contract L2USDCCustomGatewayTest is L2ArbitrumGatewayTest { IFiatTokenArbitrumOrbitV2_2(l2USDC).initializeV2_2(new address[](0), "USDC.e"); IFiatTokenArbitrumOrbitV2_2(l2USDC).initializeArbitrumOrbit(address(l2USDCGateway), l1USDC); + vm.prank(masterMinter); + IFiatTokenArbitrumOrbitV2_2(l2USDC).configureMinter( + address(l2USDCGateway), type(uint256).max + ); + l2USDCGateway.initialize(l1Counterpart, router, l1USDC, l2USDC, owner); } @@ -156,6 +162,10 @@ contract L2USDCCustomGatewayTest is L2ArbitrumGatewayTest { uint256 withdrawalAmount = 200_500; bytes memory data = new bytes(0); + // mint some tokens so withdrawal can be successful + vm.prank(address(l2USDCGateway)); + IArbToken(l2USDC).bridgeMint(sender, withdrawalAmount * 2); + // events uint256 expectedId = 0; bytes memory expectedData = @@ -180,6 +190,10 @@ contract L2USDCCustomGatewayTest is L2ArbitrumGatewayTest { uint256 withdrawalAmount = 200_500; bytes memory data = new bytes(0); + // mint some tokens so withdrawal can be successful + vm.prank(address(l2USDCGateway)); + IArbToken(l2USDC).bridgeMint(sender, withdrawalAmount); + // events uint256 expectedId = 0; bytes memory expectedData = diff --git a/test-foundry/util/TestUtil.sol b/test-foundry/util/TestUtil.sol index 348781329a..d1954e469c 100644 --- a/test-foundry/util/TestUtil.sol +++ b/test-foundry/util/TestUtil.sol @@ -26,13 +26,13 @@ library TestUtil { // insert lib address into bytecode bytes memory b1 = - hex"60806040526001805460ff60a01b191690556000600b553480156200002357600080fd5b506200002f3362000035565b62000057565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b615f6480620000676000396000f3fe608060405234801561001057600080fd5b506004361061038e5760003560e01c806388b7ab63116101de578063b2118a8d1161010f578063dd62ed3e116100ad578063ef55bec61161007c578063ef55bec614611044578063f2fde38b146110b0578063f9f92be4146110e3578063fe575a87146111165761038e565b8063dd62ed3e14610f5c578063e3ee160e14610f97578063e5a6b10f14611003578063e94a01021461100b5761038e565b8063c2eeeebd116100e9578063c2eeeebd14610e7e578063d505accf14610e86578063d608ea6414610ee4578063d916948714610f545761038e565b8063b2118a8d14610d6b578063b7b7289914610dae578063bd10243014610e765761038e565b8063a0cc6a681161017c578063a9059cbb11610156578063a9059cbb14610c99578063aa20e1e414610cd2578063aa271e1a14610d05578063ad38bf2214610d385761038e565b8063a0cc6a6814610c1d578063a297ea5e14610c25578063a457c2d714610c605761038e565b80638da5cb5b116101b85780638da5cb5b14610bfd5780638fa74a0e14610c0557806395d89b4114610c0d5780639fd0506d14610c155761038e565b806388b7ab6314610aad5780638a6db9c314610b915780638c2a993e14610bc45761038e565b806339509351116102c3578063554bab3c1161026157806374f4f5471161023057806374f4f54714610a315780637ecebe0014610a6a5780637f2eecc314610a9d5780638456cb5914610aa55761038e565b8063554bab3c146109755780635a049a70146109a85780635c975abb146109f657806370a08231146109fe5761038e565b806342966c681161029d57806342966c6814610855578063430239b4146108725780634e44d9561461093457806354fd4d501461096d5761038e565b806339509351146107db5780633f4ba83a1461081457806340c10f191461081c5761038e565b80633092afd5116103305780633357162b1161030a5780633357162b146105ae57806335d99f351461079a5780633644e515146107cb57806338a63183146107d35761038e565b80633092afd51461055557806330adf81f14610588578063313ce567146105905761038e565b80631a8952661161036c5780631a8952661461047757806323b872dd146104ac5780632ab60045146104ef5780632fc81e09146105225761038e565b806306fdde0314610393578063095ea7b31461041057806318160ddd1461045d575b600080fd5b61039b611149565b6040805160208082528351818301528351919283929083019185019080838360005b838110156103d55781810151838201526020016103bd565b50505050905090810190601f1680156104025780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6104496004803603604081101561042657600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356111f5565b604080519115158252519081900360200190f35b610465611296565b60408051918252519081900360200190f35b6104aa6004803603602081101561048d57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff1661129c565b005b610449600480360360608110156104c257600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060400135611359565b6104aa6004803603602081101561050557600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611614565b6104aa6004803603602081101561053857600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611775565b6104496004803603602081101561056b57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166117dd565b6104656118d6565b6105986118fa565b6040805160ff9092168252519081900360200190f35b6104aa60048036036101008110156105c557600080fd5b8101906020810181356401000000008111156105e057600080fd5b8201836020820111156105f257600080fd5b8035906020019184600183028401116401000000008311171561061457600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929594936020810193503591505064010000000081111561066757600080fd5b82018360208201111561067957600080fd5b8035906020019184600183028401116401000000008311171561069b57600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092959493602081019350359150506401000000008111156106ee57600080fd5b82018360208201111561070057600080fd5b8035906020019184600183028401116401000000008311171561072257600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050813560ff16925050602081013573ffffffffffffffffffffffffffffffffffffffff90811691604081013582169160608201358116916080013516611903565b6107a2611c45565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b610465611c61565b6107a2611c70565b610449600480360360408110156107f157600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135611c8c565b6104aa611d24565b6104496004803603604081101561083257600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135611de7565b6104aa6004803603602081101561086b57600080fd5b50356121b8565b6104aa6004803603604081101561088857600080fd5b8101906020810181356401000000008111156108a357600080fd5b8201836020820111156108b557600080fd5b803590602001918460208302840111640100000000831117156108d757600080fd5b9193909290916020810190356401000000008111156108f557600080fd5b82018360208201111561090757600080fd5b8035906020019184600183028401116401000000008311171561092957600080fd5b50909250905061245a565b6104496004803603604081101561094a57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135612611565b61039b6127a4565b6104aa6004803603602081101561098b57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166127db565b6104aa600480360360a08110156109be57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060208101359060ff6040820135169060608101359060800135612942565b6104496129e0565b61046560048036036020811015610a1457600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612a01565b6104aa60048036036040811015610a4757600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135612a12565b61046560048036036020811015610a8057600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612ac1565b610465612ae9565b6104aa612b0d565b6104aa600480360360e0811015610ac357600080fd5b73ffffffffffffffffffffffffffffffffffffffff823581169260208101359091169160408201359160608101359160808201359160a08101359181019060e0810160c0820135640100000000811115610b1c57600080fd5b820183602082011115610b2e57600080fd5b80359060200191846001830284011164010000000083111715610b5057600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612be7945050505050565b61046560048036036020811015610ba757600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612d4b565b6104aa60048036036040811015610bda57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135612d73565b6107a2612e23565b6107a2612e3f565b61039b612e64565b6107a2612edd565b610465612ef9565b6104aa60048036036040811015610c3b57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020013516612f1d565b61044960048036036040811015610c7657600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813516906020013561308c565b61044960048036036040811015610caf57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135613124565b6104aa60048036036020811015610ce857600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16613287565b61044960048036036020811015610d1b57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166133ee565b6104aa60048036036020811015610d4e57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16613419565b6104aa60048036036060811015610d8157600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060400135613580565b6104aa60048036036060811015610dc457600080fd5b73ffffffffffffffffffffffffffffffffffffffff82351691602081013591810190606081016040820135640100000000811115610e0157600080fd5b820183602082011115610e1357600080fd5b80359060200191846001830284011164010000000083111715610e3557600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550613611945050505050565b6107a26136a6565b6107a26136c2565b6104aa600480360360e0811015610e9c57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c001356136e7565b6104aa60048036036020811015610efa57600080fd5b810190602081018135640100000000811115610f1557600080fd5b820183602082011115610f2757600080fd5b80359060200191846001830284011164010000000083111715610f4957600080fd5b509092509050613789565b610465613872565b61046560048036036040811015610f7257600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020013516613896565b6104aa6004803603610120811015610fae57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060408101359060608101359060808101359060a08101359060ff60c0820135169060e08101359061010001356138ce565b61039b613a36565b6104496004803603604081101561102157600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135613aaf565b6104aa600480360361012081101561105b57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060408101359060608101359060808101359060a08101359060ff60c0820135169060e0810135906101000135613ae7565b6104aa600480360360208110156110c657600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16613c42565b6104aa600480360360208110156110f957600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16613d95565b6104496004803603602081101561112c57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16613e52565b6004805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156111ed5780601f106111c2576101008083540402835291602001916111ed565b820191906000526020600020905b8154815290600101906020018083116111d057829003601f168201915b505050505081565b60015460009074010000000000000000000000000000000000000000900460ff161561128257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b61128d338484613e5d565b50600192915050565b600b5490565b60025473ffffffffffffffffffffffffffffffffffffffff16331461130c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c815260200180615be0602c913960400191505060405180910390fd5b61131581613fa4565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f117e3210bb9aa7d9baff172026820255c6f6c30ba8999d1c2fd88e2848137c4e90600090a250565b60015460009074010000000000000000000000000000000000000000900460ff16156113e657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336113f081613faf565b15611446576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b8461145081613faf565b156114a6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b846114b081613faf565b15611506576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff87166000908152600a6020908152604080832033845290915290205485111561158f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526028815260200180615cd06028913960400191505060405180910390fd5b61159a878787613fdd565b73ffffffffffffffffffffffffffffffffffffffff87166000908152600a602090815260408083203384529091529020546115d590866141a8565b73ffffffffffffffffffffffffffffffffffffffff88166000908152600a60209081526040808320338452909152902055600193505050509392505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461169a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116611706576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180615b19602a913960400191505060405180910390fd5b600e80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517fe475e580d85111348e40d8ca33cfdd74c30fe1655c2d8537a13abc10065ffa5a90600090a250565b60125460ff1660011461178757600080fd5b60006117923061421f565b905080156117a5576117a5308383613fdd565b6117ae30614269565b5050601280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166002179055565b60085460009073ffffffffffffffffffffffffffffffffffffffff163314611850576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615bb76029913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166000818152600c6020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055600d909152808220829055517fe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb666929190a2506001919050565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60065460ff1681565b60085474010000000000000000000000000000000000000000900460ff1615611977576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180615d4b602a913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff84166119e3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f815260200180615c7d602f913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8316611a4f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615af06029913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216611abb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e815260200180615cf8602e913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8116611b27576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526028815260200180615e386028913960400191505060405180910390fd5b8751611b3a9060049060208b0190615889565b508651611b4e9060059060208a0190615889565b508551611b62906007906020890190615889565b50600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff8716179055600880547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff8781169190911790925560018054821686841617905560028054909116918416919091179055611bfc81614274565b5050600880547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055505050505050565b60085473ffffffffffffffffffffffffffffffffffffffff1681565b6000611c6b6142bb565b905090565b600e5473ffffffffffffffffffffffffffffffffffffffff1690565b60015460009074010000000000000000000000000000000000000000900460ff1615611d1957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b61128d3384846143b0565b60015473ffffffffffffffffffffffffffffffffffffffff163314611d94576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180615dec6022913960400191505060405180910390fd5b600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690556040517f7805862f689e2f13df9f062ff482ad3ad112aca9e0847911ed832e158c525b3390600090a1565b60015460009074010000000000000000000000000000000000000000900460ff1615611e7457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff16611edc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180615c5c6021913960400191505060405180910390fd5b33611ee681613faf565b15611f3c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b83611f4681613faf565b15611f9c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8516612008576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180615a856023913960400191505060405180910390fd5b60008411612061576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615b686029913960400191505060405180910390fd5b336000908152600d6020526040902054808511156120ca576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e815260200180615dbe602e913960400191505060405180910390fd5b600b546120d790866143fa565b600b556120f6866120f1876120eb8361421f565b906143fa565b614475565b61210081866141a8565b336000818152600d6020908152604091829020939093558051888152905173ffffffffffffffffffffffffffffffffffffffff8a16937fab8530f87dc9b59234c4623bf917212bb2536d647574c8e7e5da92c2ede0c9f8928290030190a360408051868152905173ffffffffffffffffffffffffffffffffffffffff8816916000917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a350600195945050505050565b60015474010000000000000000000000000000000000000000900460ff161561224257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff166122aa576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180615c5c6021913960400191505060405180910390fd5b336122b481613faf565b1561230a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b60006123153361421f565b905060008311612370576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615a5c6029913960400191505060405180910390fd5b828110156123c9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180615c366026913960400191505060405180910390fd5b600b546123d690846141a8565b600b556123e7336120f183866141a8565b60408051848152905133917fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5919081900360200190a260408051848152905160009133917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a3505050565b60125460ff1660021461246c57600080fd5b61247860058383615907565b5060005b838110156125ba576003600086868481811061249457fe5b6020908102929092013573ffffffffffffffffffffffffffffffffffffffff168352508101919091526040016000205460ff1661251c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603d8152602001806159a9603d913960400191505060405180910390fd5b61254d85858381811061252b57fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff16614269565b6003600086868481811061255d57fe5b6020908102929092013573ffffffffffffffffffffffffffffffffffffffff1683525081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905560010161247c565b506125c430614269565b505030600090815260036020819052604090912080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009081169091556012805490911690911790555050565b60015460009074010000000000000000000000000000000000000000900460ff161561269e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b60085473ffffffffffffffffffffffffffffffffffffffff16331461270e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615bb76029913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff83166000818152600c6020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055600d825291829020859055815185815291517f46980fca912ef9bcdbd36877427b6b90e860769f604e89c0e67720cece530d209281900390910190a250600192915050565b60408051808201909152600181527f3200000000000000000000000000000000000000000000000000000000000000602082015290565b60005473ffffffffffffffffffffffffffffffffffffffff16331461286157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff81166128cd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526028815260200180615a096028913960400191505060405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691909117918290556040519116907fb80482a293ca2e013eda8683c9bd7fc8347cfdaeea5ede58cba46df502c2a60490600090a250565b60015474010000000000000000000000000000000000000000900460ff16156129cc57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6129d98585858585614576565b5050505050565b60015474010000000000000000000000000000000000000000900460ff1681565b6000612a0c8261421f565b92915050565b612a1a612e3f565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612ab357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4f4e4c595f474154455741590000000000000000000000000000000000000000604482015290519081900360640190fd5b612abd82826145b6565b5050565b73ffffffffffffffffffffffffffffffffffffffff1660009081526011602052604090205490565b7fd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de881565b60015473ffffffffffffffffffffffffffffffffffffffff163314612b7d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180615dec6022913960400191505060405180910390fd5b600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790556040517f6985a02210a168e66602d3235cb6db0e70f92b3ba4d376a33c0f3d9434bff62590600090a1565b60015474010000000000000000000000000000000000000000900460ff1615612c7157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b86612c7b81613faf565b15612cd1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b86612cdb81613faf565b15612d31576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b612d408989898989898961487c565b505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff166000908152600d602052604090205490565b612d7b612e3f565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612e1457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4f4e4c595f474154455741590000000000000000000000000000000000000000604482015290519081900360640190fd5b612e1e8282611de7565b505050565b60005473ffffffffffffffffffffffffffffffffffffffff1690565b7fdbf6298cab77bb44ebfd5abb25ed2538c2a55f7404c47e83e6531361fba28c245490565b6005805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156111ed5780601f106111c2576101008083540402835291602001916111ed565b60015473ffffffffffffffffffffffffffffffffffffffff1681565b7f7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a226781565b60125460ff16600314612f2f57600080fd5b73ffffffffffffffffffffffffffffffffffffffff8216612fb157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f494e56414c49445f474154455741590000000000000000000000000000000000604482015290519081900360640190fd5b6000612fbb612e3f565b73ffffffffffffffffffffffffffffffffffffffff161461303d57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f414c52454144595f494e49540000000000000000000000000000000000000000604482015290519081900360640190fd5b817fdbf6298cab77bb44ebfd5abb25ed2538c2a55f7404c47e83e6531361fba28c2455807f54352c0d7cc5793352a36344bfdcdcf68ba6258544ce1aed71f60a74d882c19155612abd8261499d565b60015460009074010000000000000000000000000000000000000000900460ff161561311957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b61128d338484614a52565b60015460009074010000000000000000000000000000000000000000900460ff16156131b157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336131bb81613faf565b15613211576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b8361321b81613faf565b15613271576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b61327c338686613fdd565b506001949350505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461330d57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116613379576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f815260200180615c7d602f913960400191505060405180910390fd5b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691909117918290556040519116907fdb66dfa9c6b8f5226fe9aac7e51897ae8ee94ac31dc70bb6c9900b2574b707e690600090a250565b73ffffffffffffffffffffffffffffffffffffffff166000908152600c602052604090205460ff1690565b60005473ffffffffffffffffffffffffffffffffffffffff16331461349f57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff811661350b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526032815260200180615e8e6032913960400191505060405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691909117918290556040519116907fc67398012c111ce95ecb7429b933096c977380ee6c421175a71a4a4c6c88c06e90600090a250565b600e5473ffffffffffffffffffffffffffffffffffffffff1633146135f0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526024815260200180615cac6024913960400191505060405180910390fd5b612e1e73ffffffffffffffffffffffffffffffffffffffff84168383614aae565b60015474010000000000000000000000000000000000000000900460ff161561369b57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b612e1e838383614b3b565b60025473ffffffffffffffffffffffffffffffffffffffff1681565b7f54352c0d7cc5793352a36344bfdcdcf68ba6258544ce1aed71f60a74d882c1915490565b60015474010000000000000000000000000000000000000000900460ff161561377157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b61378087878787878787614c45565b50505050505050565b60085474010000000000000000000000000000000000000000900460ff1680156137b6575060125460ff16155b6137bf57600080fd5b6137cb60048383615907565b5061384082828080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600181527f320000000000000000000000000000000000000000000000000000000000000060208201529150614c879050565b600f555050601280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b7f158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a159742981565b73ffffffffffffffffffffffffffffffffffffffff9182166000908152600a6020908152604080832093909416825291909152205490565b60015474010000000000000000000000000000000000000000900460ff161561395857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b8861396281613faf565b156139b8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b886139c281613faf565b15613a18576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b613a298b8b8b8b8b8b8b8b8b614c9d565b5050505050505050505050565b6007805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156111ed5780601f106111c2576101008083540402835291602001916111ed565b73ffffffffffffffffffffffffffffffffffffffff919091166000908152601060209081526040808320938352929052205460ff1690565b60015474010000000000000000000000000000000000000000900460ff1615613b7157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b88613b7b81613faf565b15613bd1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b88613bdb81613faf565b15613c31576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b613a298b8b8b8b8b8b8b8b8b614ce1565b60005473ffffffffffffffffffffffffffffffffffffffff163314613cc857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116613d34576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180615aa86026913960400191505060405180910390fd5b6000546040805173ffffffffffffffffffffffffffffffffffffffff9283168152918316602083015280517f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09281900390910190a1613d9281614274565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314613e05576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c815260200180615be0602c913960400191505060405180910390fd5b613e0e81614269565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fffa4e6181777692565cf28528fc88fd1516ea86b56da075235fa575af6a4b85590600090a250565b6000612a0c82613faf565b73ffffffffffffffffffffffffffffffffffffffff8316613ec9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526024815260200180615d9a6024913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216613f35576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180615ace6022913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8084166000818152600a6020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b613d92816000614d25565b73ffffffffffffffffffffffffffffffffffffffff1660009081526009602052604090205460ff1c60011490565b73ffffffffffffffffffffffffffffffffffffffff8316614049576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615d756025913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166140b5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806159e66023913960400191505060405180910390fd5b6140be8361421f565b811115614116576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180615b916026913960400191505060405180910390fd5b61412d836120f1836141278761421f565b906141a8565b61413e826120f1836120eb8661421f565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b60008282111561421957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b73ffffffffffffffffffffffffffffffffffffffff166000908152600960205260409020547f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690565b613d92816001614d25565b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6004805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152600093611c6b93919290918301828280156143685780601f1061433d57610100808354040283529160200191614368565b820191906000526020600020905b81548152906001019060200180831161434b57829003601f168201915b50505050506040518060400160405280600181526020017f32000000000000000000000000000000000000000000000000000000000000008152506143ab614dae565b614db2565b73ffffffffffffffffffffffffffffffffffffffff8084166000908152600a6020908152604080832093861683529290522054612e1e90849084906143f590856143fa565b613e5d565b60008282018381101561446e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8111156144ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180615c0c602a913960400191505060405180910390fd5b6144f782613faf565b1561454d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615b436025913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff909116600090815260096020526040902055565b6129d98585848487604051602001808481526020018381526020018260ff1660f81b81526001019350505050604051602081830303815290604052614b3b565b60015474010000000000000000000000000000000000000000900460ff161561464057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff166146a8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180615c5c6021913960400191505060405180910390fd5b816146b281613faf565b15614708576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b60006147138461421f565b90506000831161476e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615a5c6029913960400191505060405180910390fd5b828110156147c7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180615c366026913960400191505060405180910390fd5b600b805484900390556147dc84848303614475565b60408051848152905173ffffffffffffffffffffffffffffffffffffffff8616917fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5919081900360200190a260408051848152905160009173ffffffffffffffffffffffffffffffffffffffff8716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a350505050565b73ffffffffffffffffffffffffffffffffffffffff861633146148ea576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615d266025913960400191505060405180910390fd5b6148f687838686614e26565b604080517fd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de860208083019190915273ffffffffffffffffffffffffffffffffffffffff808b1683850152891660608301526080820188905260a0820187905260c0820186905260e080830186905283518084039091018152610100909201909252805191012061498890889083614ee6565b6149928783615064565b613780878787613fdd565b73ffffffffffffffffffffffffffffffffffffffff81166000818152600c6020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055600d8252918290207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90819055825181815292519093927f46980fca912ef9bcdbd36877427b6b90e860769f604e89c0e67720cece530d2092908290030190a25050565b612e1e83836143f584604051806060016040528060258152602001615f0a6025913973ffffffffffffffffffffffffffffffffffffffff808a166000908152600a60209081526040808320938c168352929052205491906150e9565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052612e1e90849061519a565b614b458383615272565b614bbf837f158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a159742960001b8585604051602001808481526020018373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200193505050506040516020818303038152906040528051906020012083614ee6565b73ffffffffffffffffffffffffffffffffffffffff8316600081815260106020908152604080832086845290915280822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055518492917f1cdd46ff242716cdaa72d159d339a485b3438398348d68f09d7c8c0a59353d8191a3505050565b61378087878787868689604051602001808481526020018381526020018260ff1660f81b815260010193505050506040516020818303038152906040526152fc565b600046614c95848483614db2565b949350505050565b612d4089898989898988888b604051602001808481526020018381526020018260ff1660f81b815260010193505050506040516020818303038152906040526155c0565b612d4089898989898988888b604051602001808481526020018381526020018260ff1660f81b8152600101935050505060405160208183030381529060405261487c565b80614d3857614d338261421f565b614d81565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600960205260409020547f8000000000000000000000000000000000000000000000000000000000000000175b73ffffffffffffffffffffffffffffffffffffffff90921660009081526009602052604090209190915550565b4690565b8251602093840120825192840192909220604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8187015280820194909452606084019190915260808301919091523060a0808401919091528151808403909101815260c09092019052805191012090565b814211614e7e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b815260200180615a31602b913960400191505060405180910390fd5b804210614ed6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ee56025913960400191505060405180910390fd5b614ee08484615272565b50505050565b73"; + hex"60806040526001805460ff60a01b191690556000600b553480156200002357600080fd5b506200002f3362000035565b62000057565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b61502e80620000676000396000f3fe608060405234801561001057600080fd5b50600436106103a45760003560e01c80638a6db9c3116101e9578063b7b728991161010f578063dd62ed3e116100ad578063ef55bec61161007c578063ef55bec614611069578063f2fde38b146110c8578063f9f92be4146110ee578063fe575a8714611114576103a4565b8063dd62ed3e14610fa8578063e3ee160e14610fd6578063e5a6b10f14611035578063e94a01021461103d576103a4565b8063cf092995116100e9578063cf09299514610e08578063d505accf14610edf578063d608ea6414610f30578063d916948714610fa0576103a4565b8063b7b7289914610d3d578063bd10243014610df8578063c2eeeebd14610e00576103a4565b8063a0cc6a6811610187578063aa20e1e411610156578063aa20e1e414610c95578063aa271e1a14610cbb578063ad38bf2214610ce1578063b2118a8d14610d07576103a4565b8063a0cc6a6814610c07578063a297ea5e14610c0f578063a457c2d714610c3d578063a9059cbb14610c69576103a4565b80638fa74a0e116101c35780638fa74a0e14610b2457806395d89b4114610b2c5780639fd0506d14610b345780639fd5a6cf14610b3c576103a4565b80638a6db9c314610aca5780638c2a993e14610af05780638da5cb5b14610b1c576103a4565b80633f4ba83a116102ce5780635a049a701161026c5780637ecebe001161023b5780637ecebe00146109bd5780637f2eecc3146109e35780638456cb59146109eb57806388b7ab63146109f3576103a4565b80635a049a70146109225780635c975abb1461096357806370a082311461096b57806374f4f54714610991576103a4565b8063430239b4116102a8578063430239b4146108065780634e44d956146108c857806354fd4d50146108f4578063554bab3c146108fc576103a4565b80633f4ba83a146107b557806340c10f19146107bd57806342966c68146107e9576103a4565b80633092afd51161034657806335d99f351161031557806335d99f35146107555780633644e5151461077957806338a63183146107815780633950935114610789576103a4565b80633092afd51461052a57806330adf81f14610550578063313ce567146105585780633357162b14610576576103a4565b80631a895266116103825780631a8952661461048057806323b872dd146104a85780632ab60045146104de5780632fc81e0914610504576103a4565b806306fdde03146103a9578063095ea7b31461042657806318160ddd14610466575b600080fd5b6103b161113a565b6040805160208082528351818301528351919283929083019185019080838360005b838110156103eb5781810151838201526020016103d3565b50505050905090810190601f1680156104185780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6104526004803603604081101561043c57600080fd5b506001600160a01b0381351690602001356111e6565b604080519115158252519081900360200190f35b61046e61125c565b60408051918252519081900360200190f35b6104a66004803603602081101561049657600080fd5b50356001600160a01b0316611262565b005b610452600480360360608110156104be57600080fd5b506001600160a01b038135811691602081013590911690604001356112eb565b6104a6600480360360208110156104f457600080fd5b50356001600160a01b03166114ec565b6104a66004803603602081101561051a57600080fd5b50356001600160a01b03166115f2565b6104526004803603602081101561054057600080fd5b50356001600160a01b031661163c565b61046e6116e3565b610560611707565b6040805160ff9092168252519081900360200190f35b6104a6600480360361010081101561058d57600080fd5b8101906020810181356401000000008111156105a857600080fd5b8201836020820111156105ba57600080fd5b803590602001918460018302840111640100000000831117156105dc57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929594936020810193503591505064010000000081111561062f57600080fd5b82018360208201111561064157600080fd5b8035906020019184600183028401116401000000008311171561066357600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092959493602081019350359150506401000000008111156106b657600080fd5b8201836020820111156106c857600080fd5b803590602001918460018302840111640100000000831117156106ea57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050813560ff1692505060208101356001600160a01b0390811691604081013582169160608201358116916080013516611710565b61075d61194f565b604080516001600160a01b039092168252519081900360200190f35b61046e61195e565b61075d61196d565b6104526004803603604081101561079f57600080fd5b506001600160a01b03813516906020013561197c565b6104a66119e9565b610452600480360360408110156107d357600080fd5b506001600160a01b038135169060200135611a85565b6104a6600480360360208110156107ff57600080fd5b5035611d68565b6104a66004803603604081101561081c57600080fd5b81019060208101813564010000000081111561083757600080fd5b82018360208201111561084957600080fd5b8035906020019184602083028401116401000000008311171561086b57600080fd5b91939092909160208101903564010000000081111561088957600080fd5b82018360208201111561089b57600080fd5b803590602001918460018302840111640100000000831117156108bd57600080fd5b509092509050611f77565b610452600480360360408110156108de57600080fd5b506001600160a01b0381351690602001356120b1565b6103b16121c7565b6104a66004803603602081101561091257600080fd5b50356001600160a01b03166121fe565b6104a6600480360360a081101561093857600080fd5b506001600160a01b038135169060208101359060ff604082013516906060810135906080013561230a565b61045261237d565b61046e6004803603602081101561098157600080fd5b50356001600160a01b031661238d565b6104a6600480360360408110156109a757600080fd5b506001600160a01b03813516906020013561239e565b61046e600480360360208110156109d357600080fd5b50356001600160a01b0316612419565b61046e612434565b6104a6612458565b6104a6600480360360e0811015610a0957600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359160808201359160a08101359181019060e0810160c0820135640100000000811115610a5557600080fd5b820183602082011115610a6757600080fd5b80359060200191846001830284011164010000000083111715610a8957600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506124fa945050505050565b61046e60048036036020811015610ae057600080fd5b50356001600160a01b03166125ff565b6104a660048036036040811015610b0657600080fd5b506001600160a01b03813516906020013561261a565b61075d612696565b61075d6126a5565b6103b16126ca565b61075d612743565b6104a6600480360360a0811015610b5257600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359181019060a081016080820135640100000000811115610b9257600080fd5b820183602082011115610ba457600080fd5b80359060200191846001830284011164010000000083111715610bc657600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612752945050505050565b61046e6127be565b6104a660048036036040811015610c2557600080fd5b506001600160a01b03813581169160200135166127e2565b61045260048036036040811015610c5357600080fd5b506001600160a01b0381351690602001356128fd565b61045260048036036040811015610c7f57600080fd5b506001600160a01b03813516906020013561296a565b6104a660048036036020811015610cab57600080fd5b50356001600160a01b0316612a6e565b61045260048036036020811015610cd157600080fd5b50356001600160a01b0316612b7a565b6104a660048036036020811015610cf757600080fd5b50356001600160a01b0316612b98565b6104a660048036036060811015610d1d57600080fd5b506001600160a01b03813581169160208101359091169060400135612ca4565b6104a660048036036060811015610d5357600080fd5b6001600160a01b0382351691602081013591810190606081016040820135640100000000811115610d8357600080fd5b820183602082011115610d9557600080fd5b80359060200191846001830284011164010000000083111715610db757600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612d01945050505050565b61075d612d6b565b61075d612d7a565b6104a6600480360360e0811015610e1e57600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359160808201359160a08101359181019060e0810160c0820135640100000000811115610e6a57600080fd5b820183602082011115610e7c57600080fd5b80359060200191846001830284011164010000000083111715610e9e57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612d9f945050505050565b6104a6600480360360e0811015610ef557600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c00135612e99565b6104a660048036036020811015610f4657600080fd5b810190602081018135640100000000811115610f6157600080fd5b820183602082011115610f7357600080fd5b80359060200191846001830284011164010000000083111715610f9557600080fd5b509092509050612f10565b61046e612fca565b61046e60048036036040811015610fbe57600080fd5b506001600160a01b0381358116916020013516612fee565b6104a66004803603610120811015610fed57600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060808101359060a08101359060ff60c0820135169060e0810135906101000135613019565b6103b1613122565b6104526004803603604081101561105357600080fd5b506001600160a01b03813516906020013561319b565b6104a6600480360361012081101561108057600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060808101359060a08101359060ff60c0820135169060e08101359061010001356131c6565b6104a6600480360360208110156110de57600080fd5b50356001600160a01b03166132c2565b6104a66004803603602081101561110457600080fd5b50356001600160a01b03166133ba565b6104526004803603602081101561112a57600080fd5b50356001600160a01b0316613443565b6004805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156111de5780601f106111b3576101008083540402835291602001916111de565b820191906000526020600020905b8154815290600101906020018083116111c157829003601f168201915b505050505081565b600154600090600160a01b900460ff1615611248576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b61125333848461344e565b50600192915050565b600b5490565b6002546001600160a01b031633146112ab5760405162461bcd60e51b815260040180806020018281038252602c815260200180614caa602c913960400191505060405180910390fd5b6112b48161353a565b6040516001600160a01b038216907f117e3210bb9aa7d9baff172026820255c6f6c30ba8999d1c2fd88e2848137c4e90600090a250565b600154600090600160a01b900460ff161561134d576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b3361135781613545565b156113935760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b8461139d81613545565b156113d95760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b846113e381613545565b1561141f5760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b6001600160a01b0387166000908152600a602090815260408083203384529091529020548511156114815760405162461bcd60e51b8152600401808060200182810382526028815260200180614d9a6028913960400191505060405180910390fd5b61148c878787613566565b6001600160a01b0387166000908152600a602090815260408083203384529091529020546114ba90866136af565b6001600160a01b0388166000908152600a60209081526040808320338452909152902055600193505050509392505050565b6000546001600160a01b0316331461154b576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166115905760405162461bcd60e51b815260040180806020018281038252602a815260200180614be3602a913960400191505060405180910390fd5b600e80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040517fe475e580d85111348e40d8ca33cfdd74c30fe1655c2d8537a13abc10065ffa5a90600090a250565b60125460ff1660011461160457600080fd5b600061160f3061370c565b9050801561162257611622308383613566565b61162b30613749565b50506012805460ff19166002179055565b6008546000906001600160a01b031633146116885760405162461bcd60e51b8152600401808060200182810382526029815260200180614c816029913960400191505060405180910390fd5b6001600160a01b0382166000818152600c60209081526040808320805460ff19169055600d909152808220829055517fe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb666929190a2506001919050565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60065460ff1681565b600854600160a01b900460ff16156117595760405162461bcd60e51b815260040180806020018281038252602a815260200180614e15602a913960400191505060405180910390fd5b6001600160a01b03841661179e5760405162461bcd60e51b815260040180806020018281038252602f815260200180614d47602f913960400191505060405180910390fd5b6001600160a01b0383166117e35760405162461bcd60e51b8152600401808060200182810382526029815260200180614bba6029913960400191505060405180910390fd5b6001600160a01b0382166118285760405162461bcd60e51b815260040180806020018281038252602e815260200180614dc2602e913960400191505060405180910390fd5b6001600160a01b03811661186d5760405162461bcd60e51b8152600401808060200182810382526028815260200180614f026028913960400191505060405180910390fd5b87516118809060049060208b0190614971565b5086516118949060059060208a0190614971565b5085516118a8906007906020890190614971565b506006805460ff191660ff8716179055600880547fffffffffffffffffffffffff00000000000000000000000000000000000000009081166001600160a01b03878116919091179092556001805482168684161790556002805490911691841691909117905561191781613754565b5050600880547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16600160a01b179055505050505050565b6008546001600160a01b031681565b600061196861378e565b905090565b600e546001600160a01b031690565b600154600090600160a01b900460ff16156119de576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b611253338484613883565b6001546001600160a01b03163314611a325760405162461bcd60e51b8152600401808060200182810382526022815260200180614eb66022913960400191505060405180910390fd5b600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690556040517f7805862f689e2f13df9f062ff482ad3ad112aca9e0847911ed832e158c525b3390600090a1565b600154600090600160a01b900460ff1615611ae7576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff16611b355760405162461bcd60e51b8152600401808060200182810382526021815260200180614d266021913960400191505060405180910390fd5b33611b3f81613545565b15611b7b5760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b83611b8581613545565b15611bc15760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b6001600160a01b038516611c065760405162461bcd60e51b8152600401808060200182810382526023815260200180614b4f6023913960400191505060405180910390fd5b60008411611c455760405162461bcd60e51b8152600401808060200182810382526029815260200180614c326029913960400191505060405180910390fd5b336000908152600d602052604090205480851115611c945760405162461bcd60e51b815260040180806020018281038252602e815260200180614e88602e913960400191505060405180910390fd5b600b54611ca190866138c0565b600b55611cc086611cbb87611cb58361370c565b906138c0565b613921565b611cca81866136af565b336000818152600d602090815260409182902093909355805188815290516001600160a01b038a16937fab8530f87dc9b59234c4623bf917212bb2536d647574c8e7e5da92c2ede0c9f8928290030190a36040805186815290516001600160a01b038816916000917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a350600195945050505050565b600154600160a01b900460ff1615611dc7576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff16611e155760405162461bcd60e51b8152600401808060200182810382526021815260200180614d266021913960400191505060405180910390fd5b33611e1f81613545565b15611e5b5760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b6000611e663361370c565b905060008311611ea75760405162461bcd60e51b8152600401808060200182810382526029815260200180614b266029913960400191505060405180910390fd5b82811015611ee65760405162461bcd60e51b8152600401808060200182810382526026815260200180614d006026913960400191505060405180910390fd5b600b54611ef390846136af565b600b55611f0433611cbb83866136af565b60408051848152905133917fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5919081900360200190a260408051848152905160009133917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a3505050565b60125460ff16600214611f8957600080fd5b611f95600583836149ef565b5060005b838110156120785760036000868684818110611fb157fe5b602090810292909201356001600160a01b03168352508101919091526040016000205460ff166120125760405162461bcd60e51b815260040180806020018281038252603d815260200180614a73603d913960400191505060405180910390fd5b61203685858381811061202157fe5b905060200201356001600160a01b0316613749565b6003600086868481811061204657fe5b602090810292909201356001600160a01b0316835250810191909152604001600020805460ff19169055600101611f99565b5061208230613749565b5050306000908152600360208190526040909120805460ff199081169091556012805490911690911790555050565b600154600090600160a01b900460ff1615612113576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6008546001600160a01b0316331461215c5760405162461bcd60e51b8152600401808060200182810382526029815260200180614c816029913960400191505060405180910390fd5b6001600160a01b0383166000818152600c60209081526040808320805460ff19166001179055600d825291829020859055815185815291517f46980fca912ef9bcdbd36877427b6b90e860769f604e89c0e67720cece530d209281900390910190a250600192915050565b60408051808201909152600181527f3200000000000000000000000000000000000000000000000000000000000000602082015290565b6000546001600160a01b0316331461225d576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166122a25760405162461bcd60e51b8152600401808060200182810382526028815260200180614ad36028913960400191505060405180910390fd5b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691909117918290556040519116907fb80482a293ca2e013eda8683c9bd7fc8347cfdaeea5ede58cba46df502c2a60490600090a250565b600154600160a01b900460ff1615612369576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b61237685858585856139e1565b5050505050565b600154600160a01b900460ff1681565b60006123988261370c565b92915050565b6123a66126a5565b6001600160a01b0316336001600160a01b03161461240b576040805162461bcd60e51b815260206004820152600c60248201527f4f4e4c595f474154455741590000000000000000000000000000000000000000604482015290519081900360640190fd5b6124158282613a21565b5050565b6001600160a01b031660009081526011602052604090205490565b7fd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de881565b6001546001600160a01b031633146124a15760405162461bcd60e51b8152600401808060200182810382526022815260200180614eb66022913960400191505060405180910390fd5b600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16600160a01b1790556040517f6985a02210a168e66602d3235cb6db0e70f92b3ba4d376a33c0f3d9434bff62590600090a1565b600154600160a01b900460ff1615612559576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b8661256381613545565b1561259f5760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b866125a981613545565b156125e55760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b6125f489898989898989613c43565b505050505050505050565b6001600160a01b03166000908152600d602052604090205490565b6126226126a5565b6001600160a01b0316336001600160a01b031614612687576040805162461bcd60e51b815260206004820152600c60248201527f4f4e4c595f474154455741590000000000000000000000000000000000000000604482015290519081900360640190fd5b6126918282611a85565b505050565b6000546001600160a01b031690565b7fdbf6298cab77bb44ebfd5abb25ed2538c2a55f7404c47e83e6531361fba28c245490565b6005805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156111de5780601f106111b3576101008083540402835291602001916111de565b6001546001600160a01b031681565b600154600160a01b900460ff16156127b1576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6123768585858585613d30565b7f7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a226781565b60125460ff166003146127f457600080fd5b6001600160a01b03821661284f576040805162461bcd60e51b815260206004820152600f60248201527f494e56414c49445f474154455741590000000000000000000000000000000000604482015290519081900360640190fd5b60006128596126a5565b6001600160a01b0316146128b4576040805162461bcd60e51b815260206004820152600c60248201527f414c52454144595f494e49540000000000000000000000000000000000000000604482015290519081900360640190fd5b7fdbf6298cab77bb44ebfd5abb25ed2538c2a55f7404c47e83e6531361fba28c24919091557f54352c0d7cc5793352a36344bfdcdcf68ba6258544ce1aed71f60a74d882c19155565b600154600090600160a01b900460ff161561295f576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b611253338484613fa6565b600154600090600160a01b900460ff16156129cc576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336129d681613545565b15612a125760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b83612a1c81613545565b15612a585760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b612a63338686613566565b506001949350505050565b6000546001600160a01b03163314612acd576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b038116612b125760405162461bcd60e51b815260040180806020018281038252602f815260200180614d47602f913960400191505060405180910390fd5b600880547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691909117918290556040519116907fdb66dfa9c6b8f5226fe9aac7e51897ae8ee94ac31dc70bb6c9900b2574b707e690600090a250565b6001600160a01b03166000908152600c602052604090205460ff1690565b6000546001600160a01b03163314612bf7576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b038116612c3c5760405162461bcd60e51b8152600401808060200182810382526032815260200180614f586032913960400191505060405180910390fd5b600280547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691909117918290556040519116907fc67398012c111ce95ecb7429b933096c977380ee6c421175a71a4a4c6c88c06e90600090a250565b600e546001600160a01b03163314612ced5760405162461bcd60e51b8152600401808060200182810382526024815260200180614d766024913960400191505060405180910390fd5b6126916001600160a01b0384168383613ff5565b600154600160a01b900460ff1615612d60576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b612691838383614075565b6002546001600160a01b031681565b7f54352c0d7cc5793352a36344bfdcdcf68ba6258544ce1aed71f60a74d882c1915490565b600154600160a01b900460ff1615612dfe576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b86612e0881613545565b15612e445760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b86612e4e81613545565b15612e8a5760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b6125f489898989898989614147565b600154600160a01b900460ff1615612ef8576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b612f07878787878787876141d8565b50505050505050565b600854600160a01b900460ff168015612f2c575060125460ff16155b612f3557600080fd5b612f41600483836149ef565b50612fb682828080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600181527f32000000000000000000000000000000000000000000000000000000000000006020820152915061421a9050565b600f5550506012805460ff19166001179055565b7f158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a159742981565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205490565b600154600160a01b900460ff1615613078576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b8861308281613545565b156130be5760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b886130c881613545565b156131045760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b6131158b8b8b8b8b8b8b8b8b614230565b5050505050505050505050565b6007805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156111de5780601f106111b3576101008083540402835291602001916111de565b6001600160a01b03919091166000908152601060209081526040808320938352929052205460ff1690565b600154600160a01b900460ff1615613225576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b8861322f81613545565b1561326b5760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b8861327581613545565b156132b15760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b6131158b8b8b8b8b8b8b8b8b614274565b6000546001600160a01b03163314613321576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166133665760405162461bcd60e51b8152600401808060200182810382526026815260200180614b726026913960400191505060405180910390fd5b600054604080516001600160a01b039283168152918316602083015280517f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09281900390910190a16133b781613754565b50565b6002546001600160a01b031633146134035760405162461bcd60e51b815260040180806020018281038252602c815260200180614caa602c913960400191505060405180910390fd5b61340c81613749565b6040516001600160a01b038216907fffa4e6181777692565cf28528fc88fd1516ea86b56da075235fa575af6a4b85590600090a250565b600061239882613545565b6001600160a01b0383166134935760405162461bcd60e51b8152600401808060200182810382526024815260200180614e646024913960400191505060405180910390fd5b6001600160a01b0382166134d85760405162461bcd60e51b8152600401808060200182810382526022815260200180614b986022913960400191505060405180910390fd5b6001600160a01b038084166000818152600a6020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6133b78160006142b8565b6001600160a01b031660009081526009602052604090205460ff1c60011490565b6001600160a01b0383166135ab5760405162461bcd60e51b8152600401808060200182810382526025815260200180614e3f6025913960400191505060405180910390fd5b6001600160a01b0382166135f05760405162461bcd60e51b8152600401808060200182810382526023815260200180614ab06023913960400191505060405180910390fd5b6135f98361370c565b8111156136375760405162461bcd60e51b8152600401808060200182810382526026815260200180614c5b6026913960400191505060405180910390fd5b61364e83611cbb836136488761370c565b906136af565b61365f82611cbb83611cb58661370c565b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b600082821115613706576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6001600160a01b03166000908152600960205260409020547f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690565b6133b78160016142b8565b600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6004805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152600093611968939192909183018282801561383b5780601f106138105761010080835404028352916020019161383b565b820191906000526020600020905b81548152906001019060200180831161381e57829003601f168201915b50505050506040518060400160405280600181526020017f320000000000000000000000000000000000000000000000000000000000000081525061387e614327565b61432b565b6001600160a01b038084166000908152600a602090815260408083209386168352929052205461269190849084906138bb90856138c0565b61344e565b60008282018381101561391a576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8111156139805760405162461bcd60e51b815260040180806020018281038252602a815260200180614cd6602a913960400191505060405180910390fd5b61398982613545565b156139c55760405162461bcd60e51b8152600401808060200182810382526025815260200180614c0d6025913960400191505060405180910390fd5b6001600160a01b03909116600090815260096020526040902055565b6123768585848487604051602001808481526020018381526020018260ff1660f81b81526001019350505050604051602081830303815290604052614075565b600154600160a01b900460ff1615613a80576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff16613ace5760405162461bcd60e51b8152600401808060200182810382526021815260200180614d266021913960400191505060405180910390fd5b81613ad881613545565b15613b145760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b6000613b1f8461370c565b905060008311613b605760405162461bcd60e51b8152600401808060200182810382526029815260200180614b266029913960400191505060405180910390fd5b82811015613b9f5760405162461bcd60e51b8152600401808060200182810382526026815260200180614d006026913960400191505060405180910390fd5b600b54613bac90846136af565b600b55613bbd84611cbb83866136af565b6040805184815290516001600160a01b038616917fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5919081900360200190a26040805184815290516000916001600160a01b038716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a350505050565b6001600160a01b0386163314613c8a5760405162461bcd60e51b8152600401808060200182810382526025815260200180614df06025913960400191505060405180910390fd5b613c968783868661439f565b604080517fd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de86020808301919091526001600160a01b03808b1683850152891660608301526080820188905260a0820187905260c0820186905260e0808301869052835180840390910181526101009092019092528051910120613d1b9088908361442b565b613d258783614582565b612f07878787613566565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821480613d5e5750428210155b613daf576040805162461bcd60e51b815260206004820152601e60248201527f46696174546f6b656e56323a207065726d697420697320657870697265640000604482015290519081900360640190fd5b6000613e4a613dbc61378e565b6001600160a01b0380891660008181526011602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98184015280840194909452938b166060840152608083018a905260a083019390935260c08083018990528151808403909101815260e0909201905280519101206145dc565b905073"; bytes memory b2 = - hex"636ccea65284614f12614f0c6142bb565b8661565e565b846040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff16815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015614f81578181015183820152602001614f69565b50505050905090810190601f168015614fae5780820380516001836020036101000a031916815260200191505b5094505050505060206040518083038186803b158015614fcd57600080fd5b505af4158015614fe1573d6000803e3d6000fd5b505050506040513d6020811015614ff757600080fd5b5051612e1e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f46696174546f6b656e56323a20696e76616c6964207369676e61747572650000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8216600081815260106020908152604080832085845290915280822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055518392917f98de503528ee59b575ef0c0a2576a82497bfc029a5685b209e9ec333479b10a591a35050565b60008184841115615192576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561515757818101518382015260200161513f565b50505050905090810190601f1680156151845780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b60606151fc826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166156989092919063ffffffff16565b805190915015612e1e5780806020019051602081101561521b57600080fd5b5051612e1e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180615e0e602a913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216600090815260106020908152604080832084845290915290205460ff1615612abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e815260200180615e60602e913960400191505060405180910390fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82148061532a5750428210155b61539557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f46696174546f6b656e56323a207065726d697420697320657870697265640000604482015290519081900360640190fd5b600061543d6153a26142bb565b73ffffffffffffffffffffffffffffffffffffffff80891660008181526011602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98184015280840194909452938b166060840152608083018a905260a083019390935260c08083018990528151808403909101815260e09092019052805191012061565e565b905073"; + hex"636ccea6528783856040518463ffffffff1660e01b815260040180846001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015613eca578181015183820152602001613eb2565b50505050905090810190601f168015613ef75780820380516001836020036101000a031916815260200191505b5094505050505060206040518083038186803b158015613f1657600080fd5b505af4158015613f2a573d6000803e3d6000fd5b505050506040513d6020811015613f4057600080fd5b5051613f93576040805162461bcd60e51b815260206004820152601a60248201527f454950323631323a20696e76616c6964207369676e6174757265000000000000604482015290519081900360640190fd5b613f9e86868661344e565b505050505050565b61269183836138bb84604051806060016040528060258152602001614fd4602591396001600160a01b03808a166000908152600a60209081526040808320938c16835292905220549190614616565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790526126919084906146ad565b61407f838361475e565b6140ec837f158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a159742960001b858560405160200180848152602001836001600160a01b031681526020018281526020019350505050604051602081830303815290604052805190602001208361442b565b6001600160a01b0383166000818152601060209081526040808320868452909152808220805460ff19166001179055518492917f1cdd46ff242716cdaa72d159d339a485b3438398348d68f09d7c8c0a59353d8191a3505050565b6141538783868661439f565b604080517f7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a22676020808301919091526001600160a01b03808b1683850152891660608301526080820188905260a0820187905260c0820186905260e0808301869052835180840390910181526101009092019092528051910120613d1b9088908361442b565b612f0787878787868689604051602001808481526020018381526020018260ff1660f81b81526001019350505050604051602081830303815290604052613d30565b60004661422884848361432b565b949350505050565b6125f489898989898988888b604051602001808481526020018381526020018260ff1660f81b81526001019350505050604051602081830303815290604052614147565b6125f489898989898988888b604051602001808481526020018381526020018260ff1660f81b81526001019350505050604051602081830303815290604052613c43565b806142cb576142c68261370c565b614307565b6001600160a01b0382166000908152600960205260409020547f8000000000000000000000000000000000000000000000000000000000000000175b6001600160a01b0390921660009081526009602052604090209190915550565b4690565b8251602093840120825192840192909220604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8187015280820194909452606084019190915260808301919091523060a0808401919091528151808403909101815260c09092019052805191012090565b8142116143dd5760405162461bcd60e51b815260040180806020018281038252602b815260200180614afb602b913960400191505060405180910390fd5b80421061441b5760405162461bcd60e51b8152600401808060200182810382526025815260200180614faf6025913960400191505060405180910390fd5b614425848461475e565b50505050565b73"; bytes memory b3 = - hex"636ccea6528783856040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff16815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b838110156154ca5781810151838201526020016154b2565b50505050905090810190601f1680156154f75780820380516001836020036101000a031916815260200191505b5094505050505060206040518083038186803b15801561551657600080fd5b505af415801561552a573d6000803e3d6000fd5b505050506040513d602081101561554057600080fd5b50516155ad57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f454950323631323a20696e76616c6964207369676e6174757265000000000000604482015290519081900360640190fd5b6155b8868686613e5d565b505050505050565b6155cc87838686614e26565b604080517f7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a226760208083019190915273ffffffffffffffffffffffffffffffffffffffff808b1683850152891660608301526080820188905260a0820187905260c0820186905260e080830186905283518084039091018152610100909201909252805191012061498890889083614ee6565b6040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b6060614c958484600085856156ac85615803565b61571757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b6020831061578157805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101615744565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d80600081146157e3576040519150601f19603f3d011682016040523d82523d6000602084013e6157e8565b606091505b50915091506157f8828286615809565b979650505050505050565b3b151590565b6060831561581857508161446e565b8251156158285782518084602001fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181815284516024840152845185939192839260440191908501908083836000831561515757818101518382015260200161513f565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106158ca57805160ff19168380011785556158f7565b828001600101855582156158f7579182015b828111156158f75782518255916020019190600101906158dc565b50615903929150615993565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10615966578280017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008235161785556158f7565b828001600101855582156158f7579182015b828111156158f7578235825591602001919060010190615978565b5b80821115615903576000815560010161599456fe46696174546f6b656e56325f323a20426c61636b6c697374696e672070726576696f75736c7920756e626c61636b6c6973746564206163636f756e742145524332303a207472616e7366657220746f20746865207a65726f20616464726573735061757361626c653a206e65772070617573657220697320746865207a65726f206164647265737346696174546f6b656e56323a20617574686f72697a6174696f6e206973206e6f74207965742076616c696446696174546f6b656e3a206275726e20616d6f756e74206e6f742067726561746572207468616e203046696174546f6b656e3a206d696e7420746f20746865207a65726f20616464726573734f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737346696174546f6b656e3a206e65772070617573657220697320746865207a65726f2061646472657373526573637561626c653a206e6577207265736375657220697320746865207a65726f206164647265737346696174546f6b656e56325f323a204163636f756e7420697320626c61636b6c697374656446696174546f6b656e3a206d696e7420616d6f756e74206e6f742067726561746572207468616e203045524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636546696174546f6b656e3a2063616c6c6572206973206e6f7420746865206d61737465724d696e746572426c61636b6c69737461626c653a2063616c6c6572206973206e6f742074686520626c61636b6c697374657246696174546f6b656e56325f323a2042616c616e636520657863656564732028325e323535202d20312946696174546f6b656e3a206275726e20616d6f756e7420657863656564732062616c616e636546696174546f6b656e3a2063616c6c6572206973206e6f742061206d696e74657246696174546f6b656e3a206e6577206d61737465724d696e74657220697320746865207a65726f2061646472657373526573637561626c653a2063616c6c6572206973206e6f7420746865207265736375657245524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636546696174546f6b656e3a206e657720626c61636b6c697374657220697320746865207a65726f206164647265737346696174546f6b656e56323a2063616c6c6572206d7573742062652074686520706179656546696174546f6b656e3a20636f6e747261637420697320616c726561647920696e697469616c697a656445524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737346696174546f6b656e3a206d696e7420616d6f756e742065786365656473206d696e746572416c6c6f77616e63655061757361626c653a2063616c6c6572206973206e6f7420746865207061757365725361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656446696174546f6b656e3a206e6577206f776e657220697320746865207a65726f206164647265737346696174546f6b656e56323a20617574686f72697a6174696f6e2069732075736564206f722063616e63656c6564426c61636b6c69737461626c653a206e657720626c61636b6c697374657220697320746865207a65726f2061646472657373426c61636b6c69737461626c653a206163636f756e7420697320626c61636b6c697374656446696174546f6b656e56323a20617574686f72697a6174696f6e206973206578706972656445524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122038d731178b4dd0e027fef834bc8ab43420dd9ff02d6c94216b764f26362e531d64736f6c634300060c0033"; + hex"636ccea6528461445761445161378e565b866145dc565b846040518463ffffffff1660e01b815260040180846001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b838110156144b95781810151838201526020016144a1565b50505050905090810190601f1680156144e65780820380516001836020036101000a031916815260200191505b5094505050505060206040518083038186803b15801561450557600080fd5b505af4158015614519573d6000803e3d6000fd5b505050506040513d602081101561452f57600080fd5b5051612691576040805162461bcd60e51b815260206004820152601e60248201527f46696174546f6b656e56323a20696e76616c6964207369676e61747572650000604482015290519081900360640190fd5b6001600160a01b0382166000818152601060209081526040808320858452909152808220805460ff19166001179055518392917f98de503528ee59b575ef0c0a2576a82497bfc029a5685b209e9ec333479b10a591a35050565b6040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b600081848411156146a55760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561466a578181015183820152602001614652565b50505050905090810190601f1680156146975780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6060614702826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166147c19092919063ffffffff16565b8051909150156126915780806020019051602081101561472157600080fd5b50516126915760405162461bcd60e51b815260040180806020018281038252602a815260200180614ed8602a913960400191505060405180910390fd5b6001600160a01b038216600090815260106020908152604080832084845290915290205460ff16156124155760405162461bcd60e51b815260040180806020018281038252602e815260200180614f2a602e913960400191505060405180910390fd5b60606142288484600085856147d585614905565b614826576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b6020831061488357805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101614846565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d80600081146148e5576040519150601f19603f3d011682016040523d82523d6000602084013e6148ea565b606091505b50915091506148fa82828661490b565b979650505050505050565b3b151590565b6060831561491a57508161391a565b82511561492a5782518084602001fd5b60405162461bcd60e51b815260206004820181815284516024840152845185939192839260440191908501908083836000831561466a578181015183820152602001614652565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106149b257805160ff19168380011785556149df565b828001600101855582156149df579182015b828111156149df5782518255916020019190600101906149c4565b506149eb929150614a5d565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10614a305782800160ff198235161785556149df565b828001600101855582156149df579182015b828111156149df578235825591602001919060010190614a42565b5b808211156149eb5760008155600101614a5e56fe46696174546f6b656e56325f323a20426c61636b6c697374696e672070726576696f75736c7920756e626c61636b6c6973746564206163636f756e742145524332303a207472616e7366657220746f20746865207a65726f20616464726573735061757361626c653a206e65772070617573657220697320746865207a65726f206164647265737346696174546f6b656e56323a20617574686f72697a6174696f6e206973206e6f74207965742076616c696446696174546f6b656e3a206275726e20616d6f756e74206e6f742067726561746572207468616e203046696174546f6b656e3a206d696e7420746f20746865207a65726f20616464726573734f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737346696174546f6b656e3a206e65772070617573657220697320746865207a65726f2061646472657373526573637561626c653a206e6577207265736375657220697320746865207a65726f206164647265737346696174546f6b656e56325f323a204163636f756e7420697320626c61636b6c697374656446696174546f6b656e3a206d696e7420616d6f756e74206e6f742067726561746572207468616e203045524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636546696174546f6b656e3a2063616c6c6572206973206e6f7420746865206d61737465724d696e746572426c61636b6c69737461626c653a2063616c6c6572206973206e6f742074686520626c61636b6c697374657246696174546f6b656e56325f323a2042616c616e636520657863656564732028325e323535202d20312946696174546f6b656e3a206275726e20616d6f756e7420657863656564732062616c616e636546696174546f6b656e3a2063616c6c6572206973206e6f742061206d696e74657246696174546f6b656e3a206e6577206d61737465724d696e74657220697320746865207a65726f2061646472657373526573637561626c653a2063616c6c6572206973206e6f7420746865207265736375657245524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636546696174546f6b656e3a206e657720626c61636b6c697374657220697320746865207a65726f206164647265737346696174546f6b656e56323a2063616c6c6572206d7573742062652074686520706179656546696174546f6b656e3a20636f6e747261637420697320616c726561647920696e697469616c697a656445524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737346696174546f6b656e3a206d696e7420616d6f756e742065786365656473206d696e746572416c6c6f77616e63655061757361626c653a2063616c6c6572206973206e6f7420746865207061757365725361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656446696174546f6b656e3a206e6577206f776e657220697320746865207a65726f206164647265737346696174546f6b656e56323a20617574686f72697a6174696f6e2069732075736564206f722063616e63656c6564426c61636b6c69737461626c653a206e657720626c61636b6c697374657220697320746865207a65726f2061646472657373426c61636b6c69737461626c653a206163636f756e7420697320626c61636b6c697374656446696174546f6b656e56323a20617574686f72697a6174696f6e206973206578706972656445524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220615e051a229e77d8da0781c2c1926a3017e6914f059e90a4aa05450168f36bdc64736f6c634300060c0033"; bytes memory libAddress = abi.encodePacked(sigCheckerAddress); From 46550ee2cf810b1e82acd5724fdb55abf5697207 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Fri, 7 Jun 2024 15:02:41 +0200 Subject: [PATCH 13/20] Set minter in separate call in e2e tests --- test-e2e/orbitTokenBridge.ts | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/test-e2e/orbitTokenBridge.ts b/test-e2e/orbitTokenBridge.ts index 59a95e00f9..7a096cc7f6 100644 --- a/test-e2e/orbitTokenBridge.ts +++ b/test-e2e/orbitTokenBridge.ts @@ -716,13 +716,14 @@ describe('orbitTokenBridge', () => { tupL2Usdc.address, deployerL2Wallet ) + const masterMinter = deployerL2Wallet await ( await l2UsdcInit.initialize( 'USDC token', 'USDC.e', 'USD', 6, - ethers.Wallet.createRandom().address, + masterMinter.address, ethers.Wallet.createRandom().address, ethers.Wallet.createRandom().address, deployerL2Wallet.address @@ -739,6 +740,15 @@ describe('orbitTokenBridge', () => { l1Usdc.address ) ).wait() + + await ( + await l2UsdcInit + .connect(masterMinter) + .configureMinter( + l2USDCCustomGateway.address, + ethers.constants.MaxUint256 + ) + ).wait() const l2Usdc = IERC20__factory.connect(l2UsdcInit.address, deployerL2Wallet) console.log('L2 USDC address: ', l2Usdc.address) @@ -951,13 +961,14 @@ describe('orbitTokenBridge', () => { tupL2Usdc.address, deployerL2Wallet ) + const masterMinter = deployerL2Wallet await ( await l2UsdcInit.initialize( 'USDC token', 'USDC.e', 'USD', 6, - ethers.Wallet.createRandom().address, + masterMinter.address, ethers.Wallet.createRandom().address, ethers.Wallet.createRandom().address, deployerL2Wallet.address @@ -974,6 +985,14 @@ describe('orbitTokenBridge', () => { l1Usdc.address ) ).wait() + await ( + await l2UsdcInit + .connect(masterMinter) + .configureMinter( + l2USDCCustomGateway.address, + ethers.constants.MaxUint256 + ) + ).wait() const l2Usdc = IERC20__factory.connect(l2UsdcInit.address, deployerL2Wallet) console.log('L2 USDC address: ', l2Usdc.address) @@ -1224,7 +1243,7 @@ async function _deployBridgedUsdcToken(deployer: Wallet) { // prepare bridged usdc bytecode const bytecodeWithPlaceholder: string = - '0x60806040526001805460ff60a01b191690556000600b553480156200002357600080fd5b506200002f3362000035565b62000057565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b615f6480620000676000396000f3fe608060405234801561001057600080fd5b506004361061038e5760003560e01c806388b7ab63116101de578063b2118a8d1161010f578063dd62ed3e116100ad578063ef55bec61161007c578063ef55bec614611044578063f2fde38b146110b0578063f9f92be4146110e3578063fe575a87146111165761038e565b8063dd62ed3e14610f5c578063e3ee160e14610f97578063e5a6b10f14611003578063e94a01021461100b5761038e565b8063c2eeeebd116100e9578063c2eeeebd14610e7e578063d505accf14610e86578063d608ea6414610ee4578063d916948714610f545761038e565b8063b2118a8d14610d6b578063b7b7289914610dae578063bd10243014610e765761038e565b8063a0cc6a681161017c578063a9059cbb11610156578063a9059cbb14610c99578063aa20e1e414610cd2578063aa271e1a14610d05578063ad38bf2214610d385761038e565b8063a0cc6a6814610c1d578063a297ea5e14610c25578063a457c2d714610c605761038e565b80638da5cb5b116101b85780638da5cb5b14610bfd5780638fa74a0e14610c0557806395d89b4114610c0d5780639fd0506d14610c155761038e565b806388b7ab6314610aad5780638a6db9c314610b915780638c2a993e14610bc45761038e565b806339509351116102c3578063554bab3c1161026157806374f4f5471161023057806374f4f54714610a315780637ecebe0014610a6a5780637f2eecc314610a9d5780638456cb5914610aa55761038e565b8063554bab3c146109755780635a049a70146109a85780635c975abb146109f657806370a08231146109fe5761038e565b806342966c681161029d57806342966c6814610855578063430239b4146108725780634e44d9561461093457806354fd4d501461096d5761038e565b806339509351146107db5780633f4ba83a1461081457806340c10f191461081c5761038e565b80633092afd5116103305780633357162b1161030a5780633357162b146105ae57806335d99f351461079a5780633644e515146107cb57806338a63183146107d35761038e565b80633092afd51461055557806330adf81f14610588578063313ce567146105905761038e565b80631a8952661161036c5780631a8952661461047757806323b872dd146104ac5780632ab60045146104ef5780632fc81e09146105225761038e565b806306fdde0314610393578063095ea7b31461041057806318160ddd1461045d575b600080fd5b61039b611149565b6040805160208082528351818301528351919283929083019185019080838360005b838110156103d55781810151838201526020016103bd565b50505050905090810190601f1680156104025780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6104496004803603604081101561042657600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356111f5565b604080519115158252519081900360200190f35b610465611296565b60408051918252519081900360200190f35b6104aa6004803603602081101561048d57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff1661129c565b005b610449600480360360608110156104c257600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060400135611359565b6104aa6004803603602081101561050557600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611614565b6104aa6004803603602081101561053857600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611775565b6104496004803603602081101561056b57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166117dd565b6104656118d6565b6105986118fa565b6040805160ff9092168252519081900360200190f35b6104aa60048036036101008110156105c557600080fd5b8101906020810181356401000000008111156105e057600080fd5b8201836020820111156105f257600080fd5b8035906020019184600183028401116401000000008311171561061457600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929594936020810193503591505064010000000081111561066757600080fd5b82018360208201111561067957600080fd5b8035906020019184600183028401116401000000008311171561069b57600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092959493602081019350359150506401000000008111156106ee57600080fd5b82018360208201111561070057600080fd5b8035906020019184600183028401116401000000008311171561072257600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050813560ff16925050602081013573ffffffffffffffffffffffffffffffffffffffff90811691604081013582169160608201358116916080013516611903565b6107a2611c45565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b610465611c61565b6107a2611c70565b610449600480360360408110156107f157600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135611c8c565b6104aa611d24565b6104496004803603604081101561083257600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135611de7565b6104aa6004803603602081101561086b57600080fd5b50356121b8565b6104aa6004803603604081101561088857600080fd5b8101906020810181356401000000008111156108a357600080fd5b8201836020820111156108b557600080fd5b803590602001918460208302840111640100000000831117156108d757600080fd5b9193909290916020810190356401000000008111156108f557600080fd5b82018360208201111561090757600080fd5b8035906020019184600183028401116401000000008311171561092957600080fd5b50909250905061245a565b6104496004803603604081101561094a57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135612611565b61039b6127a4565b6104aa6004803603602081101561098b57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166127db565b6104aa600480360360a08110156109be57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060208101359060ff6040820135169060608101359060800135612942565b6104496129e0565b61046560048036036020811015610a1457600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612a01565b6104aa60048036036040811015610a4757600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135612a12565b61046560048036036020811015610a8057600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612ac1565b610465612ae9565b6104aa612b0d565b6104aa600480360360e0811015610ac357600080fd5b73ffffffffffffffffffffffffffffffffffffffff823581169260208101359091169160408201359160608101359160808201359160a08101359181019060e0810160c0820135640100000000811115610b1c57600080fd5b820183602082011115610b2e57600080fd5b80359060200191846001830284011164010000000083111715610b5057600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612be7945050505050565b61046560048036036020811015610ba757600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612d4b565b6104aa60048036036040811015610bda57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135612d73565b6107a2612e23565b6107a2612e3f565b61039b612e64565b6107a2612edd565b610465612ef9565b6104aa60048036036040811015610c3b57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020013516612f1d565b61044960048036036040811015610c7657600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813516906020013561308c565b61044960048036036040811015610caf57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135613124565b6104aa60048036036020811015610ce857600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16613287565b61044960048036036020811015610d1b57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166133ee565b6104aa60048036036020811015610d4e57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16613419565b6104aa60048036036060811015610d8157600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060400135613580565b6104aa60048036036060811015610dc457600080fd5b73ffffffffffffffffffffffffffffffffffffffff82351691602081013591810190606081016040820135640100000000811115610e0157600080fd5b820183602082011115610e1357600080fd5b80359060200191846001830284011164010000000083111715610e3557600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550613611945050505050565b6107a26136a6565b6107a26136c2565b6104aa600480360360e0811015610e9c57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c001356136e7565b6104aa60048036036020811015610efa57600080fd5b810190602081018135640100000000811115610f1557600080fd5b820183602082011115610f2757600080fd5b80359060200191846001830284011164010000000083111715610f4957600080fd5b509092509050613789565b610465613872565b61046560048036036040811015610f7257600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020013516613896565b6104aa6004803603610120811015610fae57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060408101359060608101359060808101359060a08101359060ff60c0820135169060e08101359061010001356138ce565b61039b613a36565b6104496004803603604081101561102157600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135613aaf565b6104aa600480360361012081101561105b57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060408101359060608101359060808101359060a08101359060ff60c0820135169060e0810135906101000135613ae7565b6104aa600480360360208110156110c657600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16613c42565b6104aa600480360360208110156110f957600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16613d95565b6104496004803603602081101561112c57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16613e52565b6004805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156111ed5780601f106111c2576101008083540402835291602001916111ed565b820191906000526020600020905b8154815290600101906020018083116111d057829003601f168201915b505050505081565b60015460009074010000000000000000000000000000000000000000900460ff161561128257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b61128d338484613e5d565b50600192915050565b600b5490565b60025473ffffffffffffffffffffffffffffffffffffffff16331461130c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c815260200180615be0602c913960400191505060405180910390fd5b61131581613fa4565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f117e3210bb9aa7d9baff172026820255c6f6c30ba8999d1c2fd88e2848137c4e90600090a250565b60015460009074010000000000000000000000000000000000000000900460ff16156113e657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336113f081613faf565b15611446576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b8461145081613faf565b156114a6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b846114b081613faf565b15611506576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff87166000908152600a6020908152604080832033845290915290205485111561158f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526028815260200180615cd06028913960400191505060405180910390fd5b61159a878787613fdd565b73ffffffffffffffffffffffffffffffffffffffff87166000908152600a602090815260408083203384529091529020546115d590866141a8565b73ffffffffffffffffffffffffffffffffffffffff88166000908152600a60209081526040808320338452909152902055600193505050509392505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461169a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116611706576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180615b19602a913960400191505060405180910390fd5b600e80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517fe475e580d85111348e40d8ca33cfdd74c30fe1655c2d8537a13abc10065ffa5a90600090a250565b60125460ff1660011461178757600080fd5b60006117923061421f565b905080156117a5576117a5308383613fdd565b6117ae30614269565b5050601280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166002179055565b60085460009073ffffffffffffffffffffffffffffffffffffffff163314611850576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615bb76029913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166000818152600c6020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055600d909152808220829055517fe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb666929190a2506001919050565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60065460ff1681565b60085474010000000000000000000000000000000000000000900460ff1615611977576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180615d4b602a913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff84166119e3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f815260200180615c7d602f913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8316611a4f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615af06029913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216611abb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e815260200180615cf8602e913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8116611b27576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526028815260200180615e386028913960400191505060405180910390fd5b8751611b3a9060049060208b0190615889565b508651611b4e9060059060208a0190615889565b508551611b62906007906020890190615889565b50600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff8716179055600880547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff8781169190911790925560018054821686841617905560028054909116918416919091179055611bfc81614274565b5050600880547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055505050505050565b60085473ffffffffffffffffffffffffffffffffffffffff1681565b6000611c6b6142bb565b905090565b600e5473ffffffffffffffffffffffffffffffffffffffff1690565b60015460009074010000000000000000000000000000000000000000900460ff1615611d1957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b61128d3384846143b0565b60015473ffffffffffffffffffffffffffffffffffffffff163314611d94576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180615dec6022913960400191505060405180910390fd5b600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690556040517f7805862f689e2f13df9f062ff482ad3ad112aca9e0847911ed832e158c525b3390600090a1565b60015460009074010000000000000000000000000000000000000000900460ff1615611e7457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff16611edc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180615c5c6021913960400191505060405180910390fd5b33611ee681613faf565b15611f3c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b83611f4681613faf565b15611f9c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8516612008576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180615a856023913960400191505060405180910390fd5b60008411612061576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615b686029913960400191505060405180910390fd5b336000908152600d6020526040902054808511156120ca576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e815260200180615dbe602e913960400191505060405180910390fd5b600b546120d790866143fa565b600b556120f6866120f1876120eb8361421f565b906143fa565b614475565b61210081866141a8565b336000818152600d6020908152604091829020939093558051888152905173ffffffffffffffffffffffffffffffffffffffff8a16937fab8530f87dc9b59234c4623bf917212bb2536d647574c8e7e5da92c2ede0c9f8928290030190a360408051868152905173ffffffffffffffffffffffffffffffffffffffff8816916000917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a350600195945050505050565b60015474010000000000000000000000000000000000000000900460ff161561224257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff166122aa576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180615c5c6021913960400191505060405180910390fd5b336122b481613faf565b1561230a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b60006123153361421f565b905060008311612370576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615a5c6029913960400191505060405180910390fd5b828110156123c9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180615c366026913960400191505060405180910390fd5b600b546123d690846141a8565b600b556123e7336120f183866141a8565b60408051848152905133917fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5919081900360200190a260408051848152905160009133917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a3505050565b60125460ff1660021461246c57600080fd5b61247860058383615907565b5060005b838110156125ba576003600086868481811061249457fe5b6020908102929092013573ffffffffffffffffffffffffffffffffffffffff168352508101919091526040016000205460ff1661251c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603d8152602001806159a9603d913960400191505060405180910390fd5b61254d85858381811061252b57fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff16614269565b6003600086868481811061255d57fe5b6020908102929092013573ffffffffffffffffffffffffffffffffffffffff1683525081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905560010161247c565b506125c430614269565b505030600090815260036020819052604090912080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009081169091556012805490911690911790555050565b60015460009074010000000000000000000000000000000000000000900460ff161561269e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b60085473ffffffffffffffffffffffffffffffffffffffff16331461270e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615bb76029913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff83166000818152600c6020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055600d825291829020859055815185815291517f46980fca912ef9bcdbd36877427b6b90e860769f604e89c0e67720cece530d209281900390910190a250600192915050565b60408051808201909152600181527f3200000000000000000000000000000000000000000000000000000000000000602082015290565b60005473ffffffffffffffffffffffffffffffffffffffff16331461286157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff81166128cd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526028815260200180615a096028913960400191505060405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691909117918290556040519116907fb80482a293ca2e013eda8683c9bd7fc8347cfdaeea5ede58cba46df502c2a60490600090a250565b60015474010000000000000000000000000000000000000000900460ff16156129cc57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6129d98585858585614576565b5050505050565b60015474010000000000000000000000000000000000000000900460ff1681565b6000612a0c8261421f565b92915050565b612a1a612e3f565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612ab357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4f4e4c595f474154455741590000000000000000000000000000000000000000604482015290519081900360640190fd5b612abd82826145b6565b5050565b73ffffffffffffffffffffffffffffffffffffffff1660009081526011602052604090205490565b7fd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de881565b60015473ffffffffffffffffffffffffffffffffffffffff163314612b7d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180615dec6022913960400191505060405180910390fd5b600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790556040517f6985a02210a168e66602d3235cb6db0e70f92b3ba4d376a33c0f3d9434bff62590600090a1565b60015474010000000000000000000000000000000000000000900460ff1615612c7157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b86612c7b81613faf565b15612cd1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b86612cdb81613faf565b15612d31576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b612d408989898989898961487c565b505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff166000908152600d602052604090205490565b612d7b612e3f565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612e1457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4f4e4c595f474154455741590000000000000000000000000000000000000000604482015290519081900360640190fd5b612e1e8282611de7565b505050565b60005473ffffffffffffffffffffffffffffffffffffffff1690565b7fdbf6298cab77bb44ebfd5abb25ed2538c2a55f7404c47e83e6531361fba28c245490565b6005805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156111ed5780601f106111c2576101008083540402835291602001916111ed565b60015473ffffffffffffffffffffffffffffffffffffffff1681565b7f7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a226781565b60125460ff16600314612f2f57600080fd5b73ffffffffffffffffffffffffffffffffffffffff8216612fb157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f494e56414c49445f474154455741590000000000000000000000000000000000604482015290519081900360640190fd5b6000612fbb612e3f565b73ffffffffffffffffffffffffffffffffffffffff161461303d57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f414c52454144595f494e49540000000000000000000000000000000000000000604482015290519081900360640190fd5b817fdbf6298cab77bb44ebfd5abb25ed2538c2a55f7404c47e83e6531361fba28c2455807f54352c0d7cc5793352a36344bfdcdcf68ba6258544ce1aed71f60a74d882c19155612abd8261499d565b60015460009074010000000000000000000000000000000000000000900460ff161561311957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b61128d338484614a52565b60015460009074010000000000000000000000000000000000000000900460ff16156131b157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336131bb81613faf565b15613211576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b8361321b81613faf565b15613271576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b61327c338686613fdd565b506001949350505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461330d57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116613379576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f815260200180615c7d602f913960400191505060405180910390fd5b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691909117918290556040519116907fdb66dfa9c6b8f5226fe9aac7e51897ae8ee94ac31dc70bb6c9900b2574b707e690600090a250565b73ffffffffffffffffffffffffffffffffffffffff166000908152600c602052604090205460ff1690565b60005473ffffffffffffffffffffffffffffffffffffffff16331461349f57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff811661350b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526032815260200180615e8e6032913960400191505060405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691909117918290556040519116907fc67398012c111ce95ecb7429b933096c977380ee6c421175a71a4a4c6c88c06e90600090a250565b600e5473ffffffffffffffffffffffffffffffffffffffff1633146135f0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526024815260200180615cac6024913960400191505060405180910390fd5b612e1e73ffffffffffffffffffffffffffffffffffffffff84168383614aae565b60015474010000000000000000000000000000000000000000900460ff161561369b57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b612e1e838383614b3b565b60025473ffffffffffffffffffffffffffffffffffffffff1681565b7f54352c0d7cc5793352a36344bfdcdcf68ba6258544ce1aed71f60a74d882c1915490565b60015474010000000000000000000000000000000000000000900460ff161561377157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b61378087878787878787614c45565b50505050505050565b60085474010000000000000000000000000000000000000000900460ff1680156137b6575060125460ff16155b6137bf57600080fd5b6137cb60048383615907565b5061384082828080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600181527f320000000000000000000000000000000000000000000000000000000000000060208201529150614c879050565b600f555050601280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b7f158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a159742981565b73ffffffffffffffffffffffffffffffffffffffff9182166000908152600a6020908152604080832093909416825291909152205490565b60015474010000000000000000000000000000000000000000900460ff161561395857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b8861396281613faf565b156139b8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b886139c281613faf565b15613a18576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b613a298b8b8b8b8b8b8b8b8b614c9d565b5050505050505050505050565b6007805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156111ed5780601f106111c2576101008083540402835291602001916111ed565b73ffffffffffffffffffffffffffffffffffffffff919091166000908152601060209081526040808320938352929052205460ff1690565b60015474010000000000000000000000000000000000000000900460ff1615613b7157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b88613b7b81613faf565b15613bd1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b88613bdb81613faf565b15613c31576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b613a298b8b8b8b8b8b8b8b8b614ce1565b60005473ffffffffffffffffffffffffffffffffffffffff163314613cc857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116613d34576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180615aa86026913960400191505060405180910390fd5b6000546040805173ffffffffffffffffffffffffffffffffffffffff9283168152918316602083015280517f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09281900390910190a1613d9281614274565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314613e05576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c815260200180615be0602c913960400191505060405180910390fd5b613e0e81614269565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fffa4e6181777692565cf28528fc88fd1516ea86b56da075235fa575af6a4b85590600090a250565b6000612a0c82613faf565b73ffffffffffffffffffffffffffffffffffffffff8316613ec9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526024815260200180615d9a6024913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216613f35576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180615ace6022913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8084166000818152600a6020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b613d92816000614d25565b73ffffffffffffffffffffffffffffffffffffffff1660009081526009602052604090205460ff1c60011490565b73ffffffffffffffffffffffffffffffffffffffff8316614049576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615d756025913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166140b5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806159e66023913960400191505060405180910390fd5b6140be8361421f565b811115614116576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180615b916026913960400191505060405180910390fd5b61412d836120f1836141278761421f565b906141a8565b61413e826120f1836120eb8661421f565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b60008282111561421957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b73ffffffffffffffffffffffffffffffffffffffff166000908152600960205260409020547f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690565b613d92816001614d25565b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6004805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152600093611c6b93919290918301828280156143685780601f1061433d57610100808354040283529160200191614368565b820191906000526020600020905b81548152906001019060200180831161434b57829003601f168201915b50505050506040518060400160405280600181526020017f32000000000000000000000000000000000000000000000000000000000000008152506143ab614dae565b614db2565b73ffffffffffffffffffffffffffffffffffffffff8084166000908152600a6020908152604080832093861683529290522054612e1e90849084906143f590856143fa565b613e5d565b60008282018381101561446e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8111156144ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180615c0c602a913960400191505060405180910390fd5b6144f782613faf565b1561454d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615b436025913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff909116600090815260096020526040902055565b6129d98585848487604051602001808481526020018381526020018260ff1660f81b81526001019350505050604051602081830303815290604052614b3b565b60015474010000000000000000000000000000000000000000900460ff161561464057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff166146a8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180615c5c6021913960400191505060405180910390fd5b816146b281613faf565b15614708576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ec06025913960400191505060405180910390fd5b60006147138461421f565b90506000831161476e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615a5c6029913960400191505060405180910390fd5b828110156147c7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180615c366026913960400191505060405180910390fd5b600b805484900390556147dc84848303614475565b60408051848152905173ffffffffffffffffffffffffffffffffffffffff8616917fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5919081900360200190a260408051848152905160009173ffffffffffffffffffffffffffffffffffffffff8716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a350505050565b73ffffffffffffffffffffffffffffffffffffffff861633146148ea576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615d266025913960400191505060405180910390fd5b6148f687838686614e26565b604080517fd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de860208083019190915273ffffffffffffffffffffffffffffffffffffffff808b1683850152891660608301526080820188905260a0820187905260c0820186905260e080830186905283518084039091018152610100909201909252805191012061498890889083614ee6565b6149928783615064565b613780878787613fdd565b73ffffffffffffffffffffffffffffffffffffffff81166000818152600c6020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055600d8252918290207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90819055825181815292519093927f46980fca912ef9bcdbd36877427b6b90e860769f604e89c0e67720cece530d2092908290030190a25050565b612e1e83836143f584604051806060016040528060258152602001615f0a6025913973ffffffffffffffffffffffffffffffffffffffff808a166000908152600a60209081526040808320938c168352929052205491906150e9565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052612e1e90849061519a565b614b458383615272565b614bbf837f158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a159742960001b8585604051602001808481526020018373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200193505050506040516020818303038152906040528051906020012083614ee6565b73ffffffffffffffffffffffffffffffffffffffff8316600081815260106020908152604080832086845290915280822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055518492917f1cdd46ff242716cdaa72d159d339a485b3438398348d68f09d7c8c0a59353d8191a3505050565b61378087878787868689604051602001808481526020018381526020018260ff1660f81b815260010193505050506040516020818303038152906040526152fc565b600046614c95848483614db2565b949350505050565b612d4089898989898988888b604051602001808481526020018381526020018260ff1660f81b815260010193505050506040516020818303038152906040526155c0565b612d4089898989898988888b604051602001808481526020018381526020018260ff1660f81b8152600101935050505060405160208183030381529060405261487c565b80614d3857614d338261421f565b614d81565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600960205260409020547f8000000000000000000000000000000000000000000000000000000000000000175b73ffffffffffffffffffffffffffffffffffffffff90921660009081526009602052604090209190915550565b4690565b8251602093840120825192840192909220604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8187015280820194909452606084019190915260808301919091523060a0808401919091528151808403909101815260c09092019052805191012090565b814211614e7e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b815260200180615a31602b913960400191505060405180910390fd5b804210614ed6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180615ee56025913960400191505060405180910390fd5b614ee08484615272565b50505050565b73__$715109b5d747ea58b675c6ea3f0dba8c60$__636ccea65284614f12614f0c6142bb565b8661565e565b846040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff16815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015614f81578181015183820152602001614f69565b50505050905090810190601f168015614fae5780820380516001836020036101000a031916815260200191505b5094505050505060206040518083038186803b158015614fcd57600080fd5b505af4158015614fe1573d6000803e3d6000fd5b505050506040513d6020811015614ff757600080fd5b5051612e1e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f46696174546f6b656e56323a20696e76616c6964207369676e61747572650000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8216600081815260106020908152604080832085845290915280822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055518392917f98de503528ee59b575ef0c0a2576a82497bfc029a5685b209e9ec333479b10a591a35050565b60008184841115615192576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561515757818101518382015260200161513f565b50505050905090810190601f1680156151845780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b60606151fc826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166156989092919063ffffffff16565b805190915015612e1e5780806020019051602081101561521b57600080fd5b5051612e1e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180615e0e602a913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216600090815260106020908152604080832084845290915290205460ff1615612abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e815260200180615e60602e913960400191505060405180910390fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82148061532a5750428210155b61539557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f46696174546f6b656e56323a207065726d697420697320657870697265640000604482015290519081900360640190fd5b600061543d6153a26142bb565b73ffffffffffffffffffffffffffffffffffffffff80891660008181526011602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98184015280840194909452938b166060840152608083018a905260a083019390935260c08083018990528151808403909101815260e09092019052805191012061565e565b905073__$715109b5d747ea58b675c6ea3f0dba8c60$__636ccea6528783856040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff16815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b838110156154ca5781810151838201526020016154b2565b50505050905090810190601f1680156154f75780820380516001836020036101000a031916815260200191505b5094505050505060206040518083038186803b15801561551657600080fd5b505af415801561552a573d6000803e3d6000fd5b505050506040513d602081101561554057600080fd5b50516155ad57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f454950323631323a20696e76616c6964207369676e6174757265000000000000604482015290519081900360640190fd5b6155b8868686613e5d565b505050505050565b6155cc87838686614e26565b604080517f7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a226760208083019190915273ffffffffffffffffffffffffffffffffffffffff808b1683850152891660608301526080820188905260a0820187905260c0820186905260e080830186905283518084039091018152610100909201909252805191012061498890889083614ee6565b6040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b6060614c958484600085856156ac85615803565b61571757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b6020831061578157805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101615744565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d80600081146157e3576040519150601f19603f3d011682016040523d82523d6000602084013e6157e8565b606091505b50915091506157f8828286615809565b979650505050505050565b3b151590565b6060831561581857508161446e565b8251156158285782518084602001fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181815284516024840152845185939192839260440191908501908083836000831561515757818101518382015260200161513f565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106158ca57805160ff19168380011785556158f7565b828001600101855582156158f7579182015b828111156158f75782518255916020019190600101906158dc565b50615903929150615993565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10615966578280017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008235161785556158f7565b828001600101855582156158f7579182015b828111156158f7578235825591602001919060010190615978565b5b80821115615903576000815560010161599456fe46696174546f6b656e56325f323a20426c61636b6c697374696e672070726576696f75736c7920756e626c61636b6c6973746564206163636f756e742145524332303a207472616e7366657220746f20746865207a65726f20616464726573735061757361626c653a206e65772070617573657220697320746865207a65726f206164647265737346696174546f6b656e56323a20617574686f72697a6174696f6e206973206e6f74207965742076616c696446696174546f6b656e3a206275726e20616d6f756e74206e6f742067726561746572207468616e203046696174546f6b656e3a206d696e7420746f20746865207a65726f20616464726573734f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737346696174546f6b656e3a206e65772070617573657220697320746865207a65726f2061646472657373526573637561626c653a206e6577207265736375657220697320746865207a65726f206164647265737346696174546f6b656e56325f323a204163636f756e7420697320626c61636b6c697374656446696174546f6b656e3a206d696e7420616d6f756e74206e6f742067726561746572207468616e203045524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636546696174546f6b656e3a2063616c6c6572206973206e6f7420746865206d61737465724d696e746572426c61636b6c69737461626c653a2063616c6c6572206973206e6f742074686520626c61636b6c697374657246696174546f6b656e56325f323a2042616c616e636520657863656564732028325e323535202d20312946696174546f6b656e3a206275726e20616d6f756e7420657863656564732062616c616e636546696174546f6b656e3a2063616c6c6572206973206e6f742061206d696e74657246696174546f6b656e3a206e6577206d61737465724d696e74657220697320746865207a65726f2061646472657373526573637561626c653a2063616c6c6572206973206e6f7420746865207265736375657245524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636546696174546f6b656e3a206e657720626c61636b6c697374657220697320746865207a65726f206164647265737346696174546f6b656e56323a2063616c6c6572206d7573742062652074686520706179656546696174546f6b656e3a20636f6e747261637420697320616c726561647920696e697469616c697a656445524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737346696174546f6b656e3a206d696e7420616d6f756e742065786365656473206d696e746572416c6c6f77616e63655061757361626c653a2063616c6c6572206973206e6f7420746865207061757365725361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656446696174546f6b656e3a206e6577206f776e657220697320746865207a65726f206164647265737346696174546f6b656e56323a20617574686f72697a6174696f6e2069732075736564206f722063616e63656c6564426c61636b6c69737461626c653a206e657720626c61636b6c697374657220697320746865207a65726f2061646472657373426c61636b6c69737461626c653a206163636f756e7420697320626c61636b6c697374656446696174546f6b656e56323a20617574686f72697a6174696f6e206973206578706972656445524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122038d731178b4dd0e027fef834bc8ab43420dd9ff02d6c94216b764f26362e531d64736f6c634300060c0033' + '0x60806040526001805460ff60a01b191690556000600b553480156200002357600080fd5b506200002f3362000035565b62000057565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b61502e80620000676000396000f3fe608060405234801561001057600080fd5b50600436106103a45760003560e01c80638a6db9c3116101e9578063b7b728991161010f578063dd62ed3e116100ad578063ef55bec61161007c578063ef55bec614611069578063f2fde38b146110c8578063f9f92be4146110ee578063fe575a8714611114576103a4565b8063dd62ed3e14610fa8578063e3ee160e14610fd6578063e5a6b10f14611035578063e94a01021461103d576103a4565b8063cf092995116100e9578063cf09299514610e08578063d505accf14610edf578063d608ea6414610f30578063d916948714610fa0576103a4565b8063b7b7289914610d3d578063bd10243014610df8578063c2eeeebd14610e00576103a4565b8063a0cc6a6811610187578063aa20e1e411610156578063aa20e1e414610c95578063aa271e1a14610cbb578063ad38bf2214610ce1578063b2118a8d14610d07576103a4565b8063a0cc6a6814610c07578063a297ea5e14610c0f578063a457c2d714610c3d578063a9059cbb14610c69576103a4565b80638fa74a0e116101c35780638fa74a0e14610b2457806395d89b4114610b2c5780639fd0506d14610b345780639fd5a6cf14610b3c576103a4565b80638a6db9c314610aca5780638c2a993e14610af05780638da5cb5b14610b1c576103a4565b80633f4ba83a116102ce5780635a049a701161026c5780637ecebe001161023b5780637ecebe00146109bd5780637f2eecc3146109e35780638456cb59146109eb57806388b7ab63146109f3576103a4565b80635a049a70146109225780635c975abb1461096357806370a082311461096b57806374f4f54714610991576103a4565b8063430239b4116102a8578063430239b4146108065780634e44d956146108c857806354fd4d50146108f4578063554bab3c146108fc576103a4565b80633f4ba83a146107b557806340c10f19146107bd57806342966c68146107e9576103a4565b80633092afd51161034657806335d99f351161031557806335d99f35146107555780633644e5151461077957806338a63183146107815780633950935114610789576103a4565b80633092afd51461052a57806330adf81f14610550578063313ce567146105585780633357162b14610576576103a4565b80631a895266116103825780631a8952661461048057806323b872dd146104a85780632ab60045146104de5780632fc81e0914610504576103a4565b806306fdde03146103a9578063095ea7b31461042657806318160ddd14610466575b600080fd5b6103b161113a565b6040805160208082528351818301528351919283929083019185019080838360005b838110156103eb5781810151838201526020016103d3565b50505050905090810190601f1680156104185780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6104526004803603604081101561043c57600080fd5b506001600160a01b0381351690602001356111e6565b604080519115158252519081900360200190f35b61046e61125c565b60408051918252519081900360200190f35b6104a66004803603602081101561049657600080fd5b50356001600160a01b0316611262565b005b610452600480360360608110156104be57600080fd5b506001600160a01b038135811691602081013590911690604001356112eb565b6104a6600480360360208110156104f457600080fd5b50356001600160a01b03166114ec565b6104a66004803603602081101561051a57600080fd5b50356001600160a01b03166115f2565b6104526004803603602081101561054057600080fd5b50356001600160a01b031661163c565b61046e6116e3565b610560611707565b6040805160ff9092168252519081900360200190f35b6104a6600480360361010081101561058d57600080fd5b8101906020810181356401000000008111156105a857600080fd5b8201836020820111156105ba57600080fd5b803590602001918460018302840111640100000000831117156105dc57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929594936020810193503591505064010000000081111561062f57600080fd5b82018360208201111561064157600080fd5b8035906020019184600183028401116401000000008311171561066357600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092959493602081019350359150506401000000008111156106b657600080fd5b8201836020820111156106c857600080fd5b803590602001918460018302840111640100000000831117156106ea57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050813560ff1692505060208101356001600160a01b0390811691604081013582169160608201358116916080013516611710565b61075d61194f565b604080516001600160a01b039092168252519081900360200190f35b61046e61195e565b61075d61196d565b6104526004803603604081101561079f57600080fd5b506001600160a01b03813516906020013561197c565b6104a66119e9565b610452600480360360408110156107d357600080fd5b506001600160a01b038135169060200135611a85565b6104a6600480360360208110156107ff57600080fd5b5035611d68565b6104a66004803603604081101561081c57600080fd5b81019060208101813564010000000081111561083757600080fd5b82018360208201111561084957600080fd5b8035906020019184602083028401116401000000008311171561086b57600080fd5b91939092909160208101903564010000000081111561088957600080fd5b82018360208201111561089b57600080fd5b803590602001918460018302840111640100000000831117156108bd57600080fd5b509092509050611f77565b610452600480360360408110156108de57600080fd5b506001600160a01b0381351690602001356120b1565b6103b16121c7565b6104a66004803603602081101561091257600080fd5b50356001600160a01b03166121fe565b6104a6600480360360a081101561093857600080fd5b506001600160a01b038135169060208101359060ff604082013516906060810135906080013561230a565b61045261237d565b61046e6004803603602081101561098157600080fd5b50356001600160a01b031661238d565b6104a6600480360360408110156109a757600080fd5b506001600160a01b03813516906020013561239e565b61046e600480360360208110156109d357600080fd5b50356001600160a01b0316612419565b61046e612434565b6104a6612458565b6104a6600480360360e0811015610a0957600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359160808201359160a08101359181019060e0810160c0820135640100000000811115610a5557600080fd5b820183602082011115610a6757600080fd5b80359060200191846001830284011164010000000083111715610a8957600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506124fa945050505050565b61046e60048036036020811015610ae057600080fd5b50356001600160a01b03166125ff565b6104a660048036036040811015610b0657600080fd5b506001600160a01b03813516906020013561261a565b61075d612696565b61075d6126a5565b6103b16126ca565b61075d612743565b6104a6600480360360a0811015610b5257600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359181019060a081016080820135640100000000811115610b9257600080fd5b820183602082011115610ba457600080fd5b80359060200191846001830284011164010000000083111715610bc657600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612752945050505050565b61046e6127be565b6104a660048036036040811015610c2557600080fd5b506001600160a01b03813581169160200135166127e2565b61045260048036036040811015610c5357600080fd5b506001600160a01b0381351690602001356128fd565b61045260048036036040811015610c7f57600080fd5b506001600160a01b03813516906020013561296a565b6104a660048036036020811015610cab57600080fd5b50356001600160a01b0316612a6e565b61045260048036036020811015610cd157600080fd5b50356001600160a01b0316612b7a565b6104a660048036036020811015610cf757600080fd5b50356001600160a01b0316612b98565b6104a660048036036060811015610d1d57600080fd5b506001600160a01b03813581169160208101359091169060400135612ca4565b6104a660048036036060811015610d5357600080fd5b6001600160a01b0382351691602081013591810190606081016040820135640100000000811115610d8357600080fd5b820183602082011115610d9557600080fd5b80359060200191846001830284011164010000000083111715610db757600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612d01945050505050565b61075d612d6b565b61075d612d7a565b6104a6600480360360e0811015610e1e57600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359160808201359160a08101359181019060e0810160c0820135640100000000811115610e6a57600080fd5b820183602082011115610e7c57600080fd5b80359060200191846001830284011164010000000083111715610e9e57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612d9f945050505050565b6104a6600480360360e0811015610ef557600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c00135612e99565b6104a660048036036020811015610f4657600080fd5b810190602081018135640100000000811115610f6157600080fd5b820183602082011115610f7357600080fd5b80359060200191846001830284011164010000000083111715610f9557600080fd5b509092509050612f10565b61046e612fca565b61046e60048036036040811015610fbe57600080fd5b506001600160a01b0381358116916020013516612fee565b6104a66004803603610120811015610fed57600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060808101359060a08101359060ff60c0820135169060e0810135906101000135613019565b6103b1613122565b6104526004803603604081101561105357600080fd5b506001600160a01b03813516906020013561319b565b6104a6600480360361012081101561108057600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060808101359060a08101359060ff60c0820135169060e08101359061010001356131c6565b6104a6600480360360208110156110de57600080fd5b50356001600160a01b03166132c2565b6104a66004803603602081101561110457600080fd5b50356001600160a01b03166133ba565b6104526004803603602081101561112a57600080fd5b50356001600160a01b0316613443565b6004805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156111de5780601f106111b3576101008083540402835291602001916111de565b820191906000526020600020905b8154815290600101906020018083116111c157829003601f168201915b505050505081565b600154600090600160a01b900460ff1615611248576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b61125333848461344e565b50600192915050565b600b5490565b6002546001600160a01b031633146112ab5760405162461bcd60e51b815260040180806020018281038252602c815260200180614caa602c913960400191505060405180910390fd5b6112b48161353a565b6040516001600160a01b038216907f117e3210bb9aa7d9baff172026820255c6f6c30ba8999d1c2fd88e2848137c4e90600090a250565b600154600090600160a01b900460ff161561134d576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b3361135781613545565b156113935760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b8461139d81613545565b156113d95760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b846113e381613545565b1561141f5760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b6001600160a01b0387166000908152600a602090815260408083203384529091529020548511156114815760405162461bcd60e51b8152600401808060200182810382526028815260200180614d9a6028913960400191505060405180910390fd5b61148c878787613566565b6001600160a01b0387166000908152600a602090815260408083203384529091529020546114ba90866136af565b6001600160a01b0388166000908152600a60209081526040808320338452909152902055600193505050509392505050565b6000546001600160a01b0316331461154b576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166115905760405162461bcd60e51b815260040180806020018281038252602a815260200180614be3602a913960400191505060405180910390fd5b600e80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040517fe475e580d85111348e40d8ca33cfdd74c30fe1655c2d8537a13abc10065ffa5a90600090a250565b60125460ff1660011461160457600080fd5b600061160f3061370c565b9050801561162257611622308383613566565b61162b30613749565b50506012805460ff19166002179055565b6008546000906001600160a01b031633146116885760405162461bcd60e51b8152600401808060200182810382526029815260200180614c816029913960400191505060405180910390fd5b6001600160a01b0382166000818152600c60209081526040808320805460ff19169055600d909152808220829055517fe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb666929190a2506001919050565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60065460ff1681565b600854600160a01b900460ff16156117595760405162461bcd60e51b815260040180806020018281038252602a815260200180614e15602a913960400191505060405180910390fd5b6001600160a01b03841661179e5760405162461bcd60e51b815260040180806020018281038252602f815260200180614d47602f913960400191505060405180910390fd5b6001600160a01b0383166117e35760405162461bcd60e51b8152600401808060200182810382526029815260200180614bba6029913960400191505060405180910390fd5b6001600160a01b0382166118285760405162461bcd60e51b815260040180806020018281038252602e815260200180614dc2602e913960400191505060405180910390fd5b6001600160a01b03811661186d5760405162461bcd60e51b8152600401808060200182810382526028815260200180614f026028913960400191505060405180910390fd5b87516118809060049060208b0190614971565b5086516118949060059060208a0190614971565b5085516118a8906007906020890190614971565b506006805460ff191660ff8716179055600880547fffffffffffffffffffffffff00000000000000000000000000000000000000009081166001600160a01b03878116919091179092556001805482168684161790556002805490911691841691909117905561191781613754565b5050600880547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16600160a01b179055505050505050565b6008546001600160a01b031681565b600061196861378e565b905090565b600e546001600160a01b031690565b600154600090600160a01b900460ff16156119de576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b611253338484613883565b6001546001600160a01b03163314611a325760405162461bcd60e51b8152600401808060200182810382526022815260200180614eb66022913960400191505060405180910390fd5b600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690556040517f7805862f689e2f13df9f062ff482ad3ad112aca9e0847911ed832e158c525b3390600090a1565b600154600090600160a01b900460ff1615611ae7576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff16611b355760405162461bcd60e51b8152600401808060200182810382526021815260200180614d266021913960400191505060405180910390fd5b33611b3f81613545565b15611b7b5760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b83611b8581613545565b15611bc15760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b6001600160a01b038516611c065760405162461bcd60e51b8152600401808060200182810382526023815260200180614b4f6023913960400191505060405180910390fd5b60008411611c455760405162461bcd60e51b8152600401808060200182810382526029815260200180614c326029913960400191505060405180910390fd5b336000908152600d602052604090205480851115611c945760405162461bcd60e51b815260040180806020018281038252602e815260200180614e88602e913960400191505060405180910390fd5b600b54611ca190866138c0565b600b55611cc086611cbb87611cb58361370c565b906138c0565b613921565b611cca81866136af565b336000818152600d602090815260409182902093909355805188815290516001600160a01b038a16937fab8530f87dc9b59234c4623bf917212bb2536d647574c8e7e5da92c2ede0c9f8928290030190a36040805186815290516001600160a01b038816916000917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a350600195945050505050565b600154600160a01b900460ff1615611dc7576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff16611e155760405162461bcd60e51b8152600401808060200182810382526021815260200180614d266021913960400191505060405180910390fd5b33611e1f81613545565b15611e5b5760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b6000611e663361370c565b905060008311611ea75760405162461bcd60e51b8152600401808060200182810382526029815260200180614b266029913960400191505060405180910390fd5b82811015611ee65760405162461bcd60e51b8152600401808060200182810382526026815260200180614d006026913960400191505060405180910390fd5b600b54611ef390846136af565b600b55611f0433611cbb83866136af565b60408051848152905133917fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5919081900360200190a260408051848152905160009133917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a3505050565b60125460ff16600214611f8957600080fd5b611f95600583836149ef565b5060005b838110156120785760036000868684818110611fb157fe5b602090810292909201356001600160a01b03168352508101919091526040016000205460ff166120125760405162461bcd60e51b815260040180806020018281038252603d815260200180614a73603d913960400191505060405180910390fd5b61203685858381811061202157fe5b905060200201356001600160a01b0316613749565b6003600086868481811061204657fe5b602090810292909201356001600160a01b0316835250810191909152604001600020805460ff19169055600101611f99565b5061208230613749565b5050306000908152600360208190526040909120805460ff199081169091556012805490911690911790555050565b600154600090600160a01b900460ff1615612113576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6008546001600160a01b0316331461215c5760405162461bcd60e51b8152600401808060200182810382526029815260200180614c816029913960400191505060405180910390fd5b6001600160a01b0383166000818152600c60209081526040808320805460ff19166001179055600d825291829020859055815185815291517f46980fca912ef9bcdbd36877427b6b90e860769f604e89c0e67720cece530d209281900390910190a250600192915050565b60408051808201909152600181527f3200000000000000000000000000000000000000000000000000000000000000602082015290565b6000546001600160a01b0316331461225d576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166122a25760405162461bcd60e51b8152600401808060200182810382526028815260200180614ad36028913960400191505060405180910390fd5b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691909117918290556040519116907fb80482a293ca2e013eda8683c9bd7fc8347cfdaeea5ede58cba46df502c2a60490600090a250565b600154600160a01b900460ff1615612369576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b61237685858585856139e1565b5050505050565b600154600160a01b900460ff1681565b60006123988261370c565b92915050565b6123a66126a5565b6001600160a01b0316336001600160a01b03161461240b576040805162461bcd60e51b815260206004820152600c60248201527f4f4e4c595f474154455741590000000000000000000000000000000000000000604482015290519081900360640190fd5b6124158282613a21565b5050565b6001600160a01b031660009081526011602052604090205490565b7fd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de881565b6001546001600160a01b031633146124a15760405162461bcd60e51b8152600401808060200182810382526022815260200180614eb66022913960400191505060405180910390fd5b600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16600160a01b1790556040517f6985a02210a168e66602d3235cb6db0e70f92b3ba4d376a33c0f3d9434bff62590600090a1565b600154600160a01b900460ff1615612559576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b8661256381613545565b1561259f5760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b866125a981613545565b156125e55760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b6125f489898989898989613c43565b505050505050505050565b6001600160a01b03166000908152600d602052604090205490565b6126226126a5565b6001600160a01b0316336001600160a01b031614612687576040805162461bcd60e51b815260206004820152600c60248201527f4f4e4c595f474154455741590000000000000000000000000000000000000000604482015290519081900360640190fd5b6126918282611a85565b505050565b6000546001600160a01b031690565b7fdbf6298cab77bb44ebfd5abb25ed2538c2a55f7404c47e83e6531361fba28c245490565b6005805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156111de5780601f106111b3576101008083540402835291602001916111de565b6001546001600160a01b031681565b600154600160a01b900460ff16156127b1576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6123768585858585613d30565b7f7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a226781565b60125460ff166003146127f457600080fd5b6001600160a01b03821661284f576040805162461bcd60e51b815260206004820152600f60248201527f494e56414c49445f474154455741590000000000000000000000000000000000604482015290519081900360640190fd5b60006128596126a5565b6001600160a01b0316146128b4576040805162461bcd60e51b815260206004820152600c60248201527f414c52454144595f494e49540000000000000000000000000000000000000000604482015290519081900360640190fd5b7fdbf6298cab77bb44ebfd5abb25ed2538c2a55f7404c47e83e6531361fba28c24919091557f54352c0d7cc5793352a36344bfdcdcf68ba6258544ce1aed71f60a74d882c19155565b600154600090600160a01b900460ff161561295f576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b611253338484613fa6565b600154600090600160a01b900460ff16156129cc576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336129d681613545565b15612a125760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b83612a1c81613545565b15612a585760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b612a63338686613566565b506001949350505050565b6000546001600160a01b03163314612acd576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b038116612b125760405162461bcd60e51b815260040180806020018281038252602f815260200180614d47602f913960400191505060405180910390fd5b600880547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691909117918290556040519116907fdb66dfa9c6b8f5226fe9aac7e51897ae8ee94ac31dc70bb6c9900b2574b707e690600090a250565b6001600160a01b03166000908152600c602052604090205460ff1690565b6000546001600160a01b03163314612bf7576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b038116612c3c5760405162461bcd60e51b8152600401808060200182810382526032815260200180614f586032913960400191505060405180910390fd5b600280547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691909117918290556040519116907fc67398012c111ce95ecb7429b933096c977380ee6c421175a71a4a4c6c88c06e90600090a250565b600e546001600160a01b03163314612ced5760405162461bcd60e51b8152600401808060200182810382526024815260200180614d766024913960400191505060405180910390fd5b6126916001600160a01b0384168383613ff5565b600154600160a01b900460ff1615612d60576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b612691838383614075565b6002546001600160a01b031681565b7f54352c0d7cc5793352a36344bfdcdcf68ba6258544ce1aed71f60a74d882c1915490565b600154600160a01b900460ff1615612dfe576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b86612e0881613545565b15612e445760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b86612e4e81613545565b15612e8a5760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b6125f489898989898989614147565b600154600160a01b900460ff1615612ef8576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b612f07878787878787876141d8565b50505050505050565b600854600160a01b900460ff168015612f2c575060125460ff16155b612f3557600080fd5b612f41600483836149ef565b50612fb682828080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600181527f32000000000000000000000000000000000000000000000000000000000000006020820152915061421a9050565b600f5550506012805460ff19166001179055565b7f158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a159742981565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205490565b600154600160a01b900460ff1615613078576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b8861308281613545565b156130be5760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b886130c881613545565b156131045760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b6131158b8b8b8b8b8b8b8b8b614230565b5050505050505050505050565b6007805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156111de5780601f106111b3576101008083540402835291602001916111de565b6001600160a01b03919091166000908152601060209081526040808320938352929052205460ff1690565b600154600160a01b900460ff1615613225576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b8861322f81613545565b1561326b5760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b8861327581613545565b156132b15760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b6131158b8b8b8b8b8b8b8b8b614274565b6000546001600160a01b03163314613321576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166133665760405162461bcd60e51b8152600401808060200182810382526026815260200180614b726026913960400191505060405180910390fd5b600054604080516001600160a01b039283168152918316602083015280517f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09281900390910190a16133b781613754565b50565b6002546001600160a01b031633146134035760405162461bcd60e51b815260040180806020018281038252602c815260200180614caa602c913960400191505060405180910390fd5b61340c81613749565b6040516001600160a01b038216907fffa4e6181777692565cf28528fc88fd1516ea86b56da075235fa575af6a4b85590600090a250565b600061239882613545565b6001600160a01b0383166134935760405162461bcd60e51b8152600401808060200182810382526024815260200180614e646024913960400191505060405180910390fd5b6001600160a01b0382166134d85760405162461bcd60e51b8152600401808060200182810382526022815260200180614b986022913960400191505060405180910390fd5b6001600160a01b038084166000818152600a6020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6133b78160006142b8565b6001600160a01b031660009081526009602052604090205460ff1c60011490565b6001600160a01b0383166135ab5760405162461bcd60e51b8152600401808060200182810382526025815260200180614e3f6025913960400191505060405180910390fd5b6001600160a01b0382166135f05760405162461bcd60e51b8152600401808060200182810382526023815260200180614ab06023913960400191505060405180910390fd5b6135f98361370c565b8111156136375760405162461bcd60e51b8152600401808060200182810382526026815260200180614c5b6026913960400191505060405180910390fd5b61364e83611cbb836136488761370c565b906136af565b61365f82611cbb83611cb58661370c565b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b600082821115613706576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6001600160a01b03166000908152600960205260409020547f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690565b6133b78160016142b8565b600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6004805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152600093611968939192909183018282801561383b5780601f106138105761010080835404028352916020019161383b565b820191906000526020600020905b81548152906001019060200180831161381e57829003601f168201915b50505050506040518060400160405280600181526020017f320000000000000000000000000000000000000000000000000000000000000081525061387e614327565b61432b565b6001600160a01b038084166000908152600a602090815260408083209386168352929052205461269190849084906138bb90856138c0565b61344e565b60008282018381101561391a576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8111156139805760405162461bcd60e51b815260040180806020018281038252602a815260200180614cd6602a913960400191505060405180910390fd5b61398982613545565b156139c55760405162461bcd60e51b8152600401808060200182810382526025815260200180614c0d6025913960400191505060405180910390fd5b6001600160a01b03909116600090815260096020526040902055565b6123768585848487604051602001808481526020018381526020018260ff1660f81b81526001019350505050604051602081830303815290604052614075565b600154600160a01b900460ff1615613a80576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff16613ace5760405162461bcd60e51b8152600401808060200182810382526021815260200180614d266021913960400191505060405180910390fd5b81613ad881613545565b15613b145760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b6000613b1f8461370c565b905060008311613b605760405162461bcd60e51b8152600401808060200182810382526029815260200180614b266029913960400191505060405180910390fd5b82811015613b9f5760405162461bcd60e51b8152600401808060200182810382526026815260200180614d006026913960400191505060405180910390fd5b600b54613bac90846136af565b600b55613bbd84611cbb83866136af565b6040805184815290516001600160a01b038616917fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5919081900360200190a26040805184815290516000916001600160a01b038716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a350505050565b6001600160a01b0386163314613c8a5760405162461bcd60e51b8152600401808060200182810382526025815260200180614df06025913960400191505060405180910390fd5b613c968783868661439f565b604080517fd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de86020808301919091526001600160a01b03808b1683850152891660608301526080820188905260a0820187905260c0820186905260e0808301869052835180840390910181526101009092019092528051910120613d1b9088908361442b565b613d258783614582565b612f07878787613566565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821480613d5e5750428210155b613daf576040805162461bcd60e51b815260206004820152601e60248201527f46696174546f6b656e56323a207065726d697420697320657870697265640000604482015290519081900360640190fd5b6000613e4a613dbc61378e565b6001600160a01b0380891660008181526011602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98184015280840194909452938b166060840152608083018a905260a083019390935260c08083018990528151808403909101815260e0909201905280519101206145dc565b905073__$715109b5d747ea58b675c6ea3f0dba8c60$__636ccea6528783856040518463ffffffff1660e01b815260040180846001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015613eca578181015183820152602001613eb2565b50505050905090810190601f168015613ef75780820380516001836020036101000a031916815260200191505b5094505050505060206040518083038186803b158015613f1657600080fd5b505af4158015613f2a573d6000803e3d6000fd5b505050506040513d6020811015613f4057600080fd5b5051613f93576040805162461bcd60e51b815260206004820152601a60248201527f454950323631323a20696e76616c6964207369676e6174757265000000000000604482015290519081900360640190fd5b613f9e86868661344e565b505050505050565b61269183836138bb84604051806060016040528060258152602001614fd4602591396001600160a01b03808a166000908152600a60209081526040808320938c16835292905220549190614616565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790526126919084906146ad565b61407f838361475e565b6140ec837f158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a159742960001b858560405160200180848152602001836001600160a01b031681526020018281526020019350505050604051602081830303815290604052805190602001208361442b565b6001600160a01b0383166000818152601060209081526040808320868452909152808220805460ff19166001179055518492917f1cdd46ff242716cdaa72d159d339a485b3438398348d68f09d7c8c0a59353d8191a3505050565b6141538783868661439f565b604080517f7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a22676020808301919091526001600160a01b03808b1683850152891660608301526080820188905260a0820187905260c0820186905260e0808301869052835180840390910181526101009092019092528051910120613d1b9088908361442b565b612f0787878787868689604051602001808481526020018381526020018260ff1660f81b81526001019350505050604051602081830303815290604052613d30565b60004661422884848361432b565b949350505050565b6125f489898989898988888b604051602001808481526020018381526020018260ff1660f81b81526001019350505050604051602081830303815290604052614147565b6125f489898989898988888b604051602001808481526020018381526020018260ff1660f81b81526001019350505050604051602081830303815290604052613c43565b806142cb576142c68261370c565b614307565b6001600160a01b0382166000908152600960205260409020547f8000000000000000000000000000000000000000000000000000000000000000175b6001600160a01b0390921660009081526009602052604090209190915550565b4690565b8251602093840120825192840192909220604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8187015280820194909452606084019190915260808301919091523060a0808401919091528151808403909101815260c09092019052805191012090565b8142116143dd5760405162461bcd60e51b815260040180806020018281038252602b815260200180614afb602b913960400191505060405180910390fd5b80421061441b5760405162461bcd60e51b8152600401808060200182810382526025815260200180614faf6025913960400191505060405180910390fd5b614425848461475e565b50505050565b73__$715109b5d747ea58b675c6ea3f0dba8c60$__636ccea6528461445761445161378e565b866145dc565b846040518463ffffffff1660e01b815260040180846001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b838110156144b95781810151838201526020016144a1565b50505050905090810190601f1680156144e65780820380516001836020036101000a031916815260200191505b5094505050505060206040518083038186803b15801561450557600080fd5b505af4158015614519573d6000803e3d6000fd5b505050506040513d602081101561452f57600080fd5b5051612691576040805162461bcd60e51b815260206004820152601e60248201527f46696174546f6b656e56323a20696e76616c6964207369676e61747572650000604482015290519081900360640190fd5b6001600160a01b0382166000818152601060209081526040808320858452909152808220805460ff19166001179055518392917f98de503528ee59b575ef0c0a2576a82497bfc029a5685b209e9ec333479b10a591a35050565b6040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b600081848411156146a55760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561466a578181015183820152602001614652565b50505050905090810190601f1680156146975780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6060614702826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166147c19092919063ffffffff16565b8051909150156126915780806020019051602081101561472157600080fd5b50516126915760405162461bcd60e51b815260040180806020018281038252602a815260200180614ed8602a913960400191505060405180910390fd5b6001600160a01b038216600090815260106020908152604080832084845290915290205460ff16156124155760405162461bcd60e51b815260040180806020018281038252602e815260200180614f2a602e913960400191505060405180910390fd5b60606142288484600085856147d585614905565b614826576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b6020831061488357805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101614846565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d80600081146148e5576040519150601f19603f3d011682016040523d82523d6000602084013e6148ea565b606091505b50915091506148fa82828661490b565b979650505050505050565b3b151590565b6060831561491a57508161391a565b82511561492a5782518084602001fd5b60405162461bcd60e51b815260206004820181815284516024840152845185939192839260440191908501908083836000831561466a578181015183820152602001614652565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106149b257805160ff19168380011785556149df565b828001600101855582156149df579182015b828111156149df5782518255916020019190600101906149c4565b506149eb929150614a5d565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10614a305782800160ff198235161785556149df565b828001600101855582156149df579182015b828111156149df578235825591602001919060010190614a42565b5b808211156149eb5760008155600101614a5e56fe46696174546f6b656e56325f323a20426c61636b6c697374696e672070726576696f75736c7920756e626c61636b6c6973746564206163636f756e742145524332303a207472616e7366657220746f20746865207a65726f20616464726573735061757361626c653a206e65772070617573657220697320746865207a65726f206164647265737346696174546f6b656e56323a20617574686f72697a6174696f6e206973206e6f74207965742076616c696446696174546f6b656e3a206275726e20616d6f756e74206e6f742067726561746572207468616e203046696174546f6b656e3a206d696e7420746f20746865207a65726f20616464726573734f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737346696174546f6b656e3a206e65772070617573657220697320746865207a65726f2061646472657373526573637561626c653a206e6577207265736375657220697320746865207a65726f206164647265737346696174546f6b656e56325f323a204163636f756e7420697320626c61636b6c697374656446696174546f6b656e3a206d696e7420616d6f756e74206e6f742067726561746572207468616e203045524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636546696174546f6b656e3a2063616c6c6572206973206e6f7420746865206d61737465724d696e746572426c61636b6c69737461626c653a2063616c6c6572206973206e6f742074686520626c61636b6c697374657246696174546f6b656e56325f323a2042616c616e636520657863656564732028325e323535202d20312946696174546f6b656e3a206275726e20616d6f756e7420657863656564732062616c616e636546696174546f6b656e3a2063616c6c6572206973206e6f742061206d696e74657246696174546f6b656e3a206e6577206d61737465724d696e74657220697320746865207a65726f2061646472657373526573637561626c653a2063616c6c6572206973206e6f7420746865207265736375657245524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636546696174546f6b656e3a206e657720626c61636b6c697374657220697320746865207a65726f206164647265737346696174546f6b656e56323a2063616c6c6572206d7573742062652074686520706179656546696174546f6b656e3a20636f6e747261637420697320616c726561647920696e697469616c697a656445524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737346696174546f6b656e3a206d696e7420616d6f756e742065786365656473206d696e746572416c6c6f77616e63655061757361626c653a2063616c6c6572206973206e6f7420746865207061757365725361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656446696174546f6b656e3a206e6577206f776e657220697320746865207a65726f206164647265737346696174546f6b656e56323a20617574686f72697a6174696f6e2069732075736564206f722063616e63656c6564426c61636b6c69737461626c653a206e657720626c61636b6c697374657220697320746865207a65726f2061646472657373426c61636b6c69737461626c653a206163636f756e7420697320626c61636b6c697374656446696174546f6b656e56323a20617574686f72697a6174696f6e206973206578706972656445524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220615e051a229e77d8da0781c2c1926a3017e6914f059e90a4aa05450168f36bdc64736f6c634300060c0033' const placeholder = '__$715109b5d747ea58b675c6ea3f0dba8c60$__' const libAddressStripped = sigCheckerLib.address.replace(/^0x/, '') From 16f5e8c3a0ec023a7f2ae953a145910a06689ca3 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Fri, 7 Jun 2024 18:00:49 +0200 Subject: [PATCH 14/20] FOrmatting --- test-foundry/L1OrbitUSDCGateway.t.sol | 3 +- test-foundry/L1USDCGateway.t.sol | 46 +++++++-------------------- test-foundry/L2USDCGateway.t.sol | 35 ++++++-------------- 3 files changed, 23 insertions(+), 61 deletions(-) diff --git a/test-foundry/L1OrbitUSDCGateway.t.sol b/test-foundry/L1OrbitUSDCGateway.t.sol index f711bef44b..06932b8fdf 100644 --- a/test-foundry/L1OrbitUSDCGateway.t.sol +++ b/test-foundry/L1OrbitUSDCGateway.t.sol @@ -3,8 +3,7 @@ pragma solidity ^0.8.0; import "./L1USDCGateway.t.sol"; -import {L1OrbitUSDCGateway} from - "contracts/tokenbridge/ethereum/gateway/L1OrbitUSDCGateway.sol"; +import {L1OrbitUSDCGateway} from "contracts/tokenbridge/ethereum/gateway/L1OrbitUSDCGateway.sol"; import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import {ERC20InboxMock} from "contracts/tokenbridge/test/InboxMock.sol"; import {ERC20PresetMinterPauser} from diff --git a/test-foundry/L1USDCGateway.t.sol b/test-foundry/L1USDCGateway.t.sol index cd3d681531..31bf1d376a 100644 --- a/test-foundry/L1USDCGateway.t.sol +++ b/test-foundry/L1USDCGateway.t.sol @@ -50,18 +50,14 @@ contract L1USDCGatewayTest is L1ArbitrumExtendedGatewayTest { } function test_burnLockedUSDC_revert_NotOwner() public { - vm.expectRevert( - abi.encodeWithSelector(L1USDCGateway.L1USDCGateway_NotOwner.selector) - ); + vm.expectRevert(abi.encodeWithSelector(L1USDCGateway.L1USDCGateway_NotOwner.selector)); usdcGateway.burnLockedUSDC(); } function test_burnLockedUSDC_revert_NotPaused() public { vm.prank(owner); vm.expectRevert( - abi.encodeWithSelector( - L1USDCGateway.L1USDCGateway_DepositsNotPaused.selector - ) + abi.encodeWithSelector(L1USDCGateway.L1USDCGateway_DepositsNotPaused.selector) ); usdcGateway.burnLockedUSDC(); } @@ -90,25 +86,19 @@ contract L1USDCGatewayTest is L1ArbitrumExtendedGatewayTest { function test_initialize_revert_InvalidL1USDC() public { L1USDCGateway gateway = new L1USDCGateway(); - vm.expectRevert( - abi.encodeWithSelector(L1USDCGateway.L1USDCGateway_InvalidL1USDC.selector) - ); + vm.expectRevert(abi.encodeWithSelector(L1USDCGateway.L1USDCGateway_InvalidL1USDC.selector)); gateway.initialize(l2Gateway, router, inbox, address(0), L2_USDC, owner); } function test_initialize_revert_InvalidL2USDC() public { L1USDCGateway gateway = new L1USDCGateway(); - vm.expectRevert( - abi.encodeWithSelector(L1USDCGateway.L1USDCGateway_InvalidL2USDC.selector) - ); + vm.expectRevert(abi.encodeWithSelector(L1USDCGateway.L1USDCGateway_InvalidL2USDC.selector)); gateway.initialize(l2Gateway, router, inbox, L1_USDC, address(0), owner); } function test_initialize_revert_InvalidOwner() public { L1USDCGateway gateway = new L1USDCGateway(); - vm.expectRevert( - abi.encodeWithSelector(L1USDCGateway.L1USDCGateway_InvalidOwner.selector) - ); + vm.expectRevert(abi.encodeWithSelector(L1USDCGateway.L1USDCGateway_InvalidOwner.selector)); gateway.initialize(l2Gateway, router, inbox, L1_USDC, L2_USDC, address(0)); } @@ -201,7 +191,7 @@ contract L1USDCGatewayTest is L1ArbitrumExtendedGatewayTest { assertEq(seqNum0, abi.encode(0), "Invalid seqNum0"); } - function test_outboundTransferCustomRefund() public virtual { + function test_outboundTransferCustomRefund() public virtual { // fund user uint256 depositAmount = 5_500_000_555; deal(L1_USDC, user, depositAmount); @@ -264,9 +254,7 @@ contract L1USDCGatewayTest is L1ArbitrumExtendedGatewayTest { vm.prank(owner); usdcGateway.pauseDeposits(); - vm.expectRevert( - abi.encodeWithSelector(L1USDCGateway.L1USDCGateway_DepositsPaused.selector) - ); + vm.expectRevert(abi.encodeWithSelector(L1USDCGateway.L1USDCGateway_DepositsPaused.selector)); vm.prank(router); l1Gateway.outboundTransferCustomRefund{value: retryableCost}( @@ -280,9 +268,7 @@ contract L1USDCGatewayTest is L1ArbitrumExtendedGatewayTest { vm.prank(owner); usdcGateway.pauseDeposits(); - vm.expectRevert( - abi.encodeWithSelector(L1USDCGateway.L1USDCGateway_DepositsPaused.selector) - ); + vm.expectRevert(abi.encodeWithSelector(L1USDCGateway.L1USDCGateway_DepositsPaused.selector)); vm.prank(router); l1Gateway.outboundTransferCustomRefund{value: retryableCost}( @@ -306,9 +292,7 @@ contract L1USDCGatewayTest is L1ArbitrumExtendedGatewayTest { } function test_pauseDeposits_revert_NotOwner() public { - vm.expectRevert( - abi.encodeWithSelector(L1USDCGateway.L1USDCGateway_NotOwner.selector) - ); + vm.expectRevert(abi.encodeWithSelector(L1USDCGateway.L1USDCGateway_NotOwner.selector)); usdcGateway.pauseDeposits(); } @@ -318,9 +302,7 @@ contract L1USDCGatewayTest is L1ArbitrumExtendedGatewayTest { vm.prank(owner); vm.expectRevert( - abi.encodeWithSelector( - L1USDCGateway.L1USDCGateway_DepositsAlreadyPaused.selector - ) + abi.encodeWithSelector(L1USDCGateway.L1USDCGateway_DepositsAlreadyPaused.selector) ); usdcGateway.pauseDeposits(); } @@ -334,17 +316,13 @@ contract L1USDCGatewayTest is L1ArbitrumExtendedGatewayTest { } function test_setOwner_revert_InvalidOwner() public { - vm.expectRevert( - abi.encodeWithSelector(L1USDCGateway.L1USDCGateway_InvalidOwner.selector) - ); + vm.expectRevert(abi.encodeWithSelector(L1USDCGateway.L1USDCGateway_InvalidOwner.selector)); vm.prank(owner); usdcGateway.setOwner(address(0)); } function test_setOwner_revert_NotOwner() public { - vm.expectRevert( - abi.encodeWithSelector(L1USDCGateway.L1USDCGateway_NotOwner.selector) - ); + vm.expectRevert(abi.encodeWithSelector(L1USDCGateway.L1USDCGateway_NotOwner.selector)); usdcGateway.setOwner(owner); } diff --git a/test-foundry/L2USDCGateway.t.sol b/test-foundry/L2USDCGateway.t.sol index c6e434ec9f..a5a5c1c00e 100644 --- a/test-foundry/L2USDCGateway.t.sol +++ b/test-foundry/L2USDCGateway.t.sol @@ -42,10 +42,11 @@ contract L2USDCGatewayTest is L2ArbitrumGatewayTest { IFiatTokenArbitrumOrbitV2_2(l2USDC).initializeV2_2(new address[](0), "USDC.e"); IFiatTokenArbitrumOrbitV2_2(l2USDC).initializeArbitrumOrbit(address(l2USDCGateway), l1USDC); - vm.prank(masterMinter); + vm.startPrank(masterMinter); IFiatTokenArbitrumOrbitV2_2(l2USDC).configureMinter( address(l2USDCGateway), type(uint256).max ); + vm.stopPrank(); l2USDCGateway.initialize(l1Counterpart, router, l1USDC, l2USDC, owner); } @@ -125,17 +126,13 @@ contract L2USDCGatewayTest is L2ArbitrumGatewayTest { function test_initialize_revert_InvalidL1USDC() public { L2USDCGateway gateway = new L2USDCGateway(); - vm.expectRevert( - abi.encodeWithSelector(L2USDCGateway.L2USDCGateway_InvalidL1USDC.selector) - ); + vm.expectRevert(abi.encodeWithSelector(L2USDCGateway.L2USDCGateway_InvalidL1USDC.selector)); L2USDCGateway(gateway).initialize(l1Counterpart, router, address(0), l2USDC, owner); } function test_initialize_revert_InvalidL2USDC() public { L2USDCGateway gateway = new L2USDCGateway(); - vm.expectRevert( - abi.encodeWithSelector(L2USDCGateway.L2USDCGateway_InvalidL2USDC.selector) - ); + vm.expectRevert(abi.encodeWithSelector(L2USDCGateway.L2USDCGateway_InvalidL2USDC.selector)); L2USDCGateway(gateway).initialize(l1Counterpart, router, l1USDC, address(0), owner); } @@ -148,9 +145,7 @@ contract L2USDCGatewayTest is L2ArbitrumGatewayTest { function test_initialize_revert_InvalidOwner() public { L2USDCGateway gateway = new L2USDCGateway(); - vm.expectRevert( - abi.encodeWithSelector(L2USDCGateway.L2USDCGateway_InvalidOwner.selector) - ); + vm.expectRevert(abi.encodeWithSelector(L2USDCGateway.L2USDCGateway_InvalidOwner.selector)); gateway.initialize(l1Counterpart, router, l1USDC, l2USDC, address(0)); } @@ -225,9 +220,7 @@ contract L2USDCGatewayTest is L2ArbitrumGatewayTest { l2USDCGateway.pauseWithdrawals(); vm.expectRevert( - abi.encodeWithSelector( - L2USDCGateway.L2USDCGateway_WithdrawalsPaused.selector - ) + abi.encodeWithSelector(L2USDCGateway.L2USDCGateway_WithdrawalsPaused.selector) ); l2USDCGateway.outboundTransfer(l1USDC, receiver, 200, 0, 0, new bytes(0)); } @@ -252,17 +245,13 @@ contract L2USDCGatewayTest is L2ArbitrumGatewayTest { l2USDCGateway.pauseWithdrawals(); vm.expectRevert( - abi.encodeWithSelector( - L2USDCGateway.L2USDCGateway_WithdrawalsAlreadyPaused.selector - ) + abi.encodeWithSelector(L2USDCGateway.L2USDCGateway_WithdrawalsAlreadyPaused.selector) ); l2USDCGateway.pauseWithdrawals(); } function test_pauseWithdrawals_revert_NotOwner() public { - vm.expectRevert( - abi.encodeWithSelector(L2USDCGateway.L2USDCGateway_NotOwner.selector) - ); + vm.expectRevert(abi.encodeWithSelector(L2USDCGateway.L2USDCGateway_NotOwner.selector)); l2USDCGateway.pauseWithdrawals(); } @@ -275,17 +264,13 @@ contract L2USDCGatewayTest is L2ArbitrumGatewayTest { } function test_setOwner_revert_InvalidOwner() public { - vm.expectRevert( - abi.encodeWithSelector(L2USDCGateway.L2USDCGateway_InvalidOwner.selector) - ); + vm.expectRevert(abi.encodeWithSelector(L2USDCGateway.L2USDCGateway_InvalidOwner.selector)); vm.prank(owner); l2USDCGateway.setOwner(address(0)); } function test_setOwner_revert_NotOwner() public { - vm.expectRevert( - abi.encodeWithSelector(L2USDCGateway.L2USDCGateway_NotOwner.selector) - ); + vm.expectRevert(abi.encodeWithSelector(L2USDCGateway.L2USDCGateway_NotOwner.selector)); l2USDCGateway.setOwner(owner); } From 766d5e11913ce4d6964318e9e7e5f5e5a4cbe7c9 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Fri, 7 Jun 2024 18:01:13 +0200 Subject: [PATCH 15/20] Use latest token implementation --- test-e2e/orbitTokenBridge.ts | 7 ++++--- test-foundry/util/TestUtil.sol | 6 +++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/test-e2e/orbitTokenBridge.ts b/test-e2e/orbitTokenBridge.ts index 56a91d3529..a3bdd00ac5 100644 --- a/test-e2e/orbitTokenBridge.ts +++ b/test-e2e/orbitTokenBridge.ts @@ -903,8 +903,9 @@ describe('orbitTokenBridge', () => { deployerL1Wallet ).deploy() const proxyAdmin = await proxyAdminFac.deployed() - const l1USDCCustomGatewayFactory = - await new L1OrbitUSDCGateway__factory(deployerL1Wallet).deploy() + const l1USDCCustomGatewayFactory = await new L1OrbitUSDCGateway__factory( + deployerL1Wallet + ).deploy() const l1USDCCustomGatewayLogic = await l1USDCCustomGatewayFactory.deployed() const tupFactory = await new TransparentUpgradeableProxy__factory( deployerL1Wallet @@ -1243,7 +1244,7 @@ async function _deployBridgedUsdcToken(deployer: Wallet) { // prepare bridged usdc bytecode const bytecodeWithPlaceholder: string = - '0x60806040526001805460ff60a01b191690556000600b553480156200002357600080fd5b506200002f3362000035565b62000057565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b61502e80620000676000396000f3fe608060405234801561001057600080fd5b50600436106103a45760003560e01c80638a6db9c3116101e9578063b7b728991161010f578063dd62ed3e116100ad578063ef55bec61161007c578063ef55bec614611069578063f2fde38b146110c8578063f9f92be4146110ee578063fe575a8714611114576103a4565b8063dd62ed3e14610fa8578063e3ee160e14610fd6578063e5a6b10f14611035578063e94a01021461103d576103a4565b8063cf092995116100e9578063cf09299514610e08578063d505accf14610edf578063d608ea6414610f30578063d916948714610fa0576103a4565b8063b7b7289914610d3d578063bd10243014610df8578063c2eeeebd14610e00576103a4565b8063a0cc6a6811610187578063aa20e1e411610156578063aa20e1e414610c95578063aa271e1a14610cbb578063ad38bf2214610ce1578063b2118a8d14610d07576103a4565b8063a0cc6a6814610c07578063a297ea5e14610c0f578063a457c2d714610c3d578063a9059cbb14610c69576103a4565b80638fa74a0e116101c35780638fa74a0e14610b2457806395d89b4114610b2c5780639fd0506d14610b345780639fd5a6cf14610b3c576103a4565b80638a6db9c314610aca5780638c2a993e14610af05780638da5cb5b14610b1c576103a4565b80633f4ba83a116102ce5780635a049a701161026c5780637ecebe001161023b5780637ecebe00146109bd5780637f2eecc3146109e35780638456cb59146109eb57806388b7ab63146109f3576103a4565b80635a049a70146109225780635c975abb1461096357806370a082311461096b57806374f4f54714610991576103a4565b8063430239b4116102a8578063430239b4146108065780634e44d956146108c857806354fd4d50146108f4578063554bab3c146108fc576103a4565b80633f4ba83a146107b557806340c10f19146107bd57806342966c68146107e9576103a4565b80633092afd51161034657806335d99f351161031557806335d99f35146107555780633644e5151461077957806338a63183146107815780633950935114610789576103a4565b80633092afd51461052a57806330adf81f14610550578063313ce567146105585780633357162b14610576576103a4565b80631a895266116103825780631a8952661461048057806323b872dd146104a85780632ab60045146104de5780632fc81e0914610504576103a4565b806306fdde03146103a9578063095ea7b31461042657806318160ddd14610466575b600080fd5b6103b161113a565b6040805160208082528351818301528351919283929083019185019080838360005b838110156103eb5781810151838201526020016103d3565b50505050905090810190601f1680156104185780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6104526004803603604081101561043c57600080fd5b506001600160a01b0381351690602001356111e6565b604080519115158252519081900360200190f35b61046e61125c565b60408051918252519081900360200190f35b6104a66004803603602081101561049657600080fd5b50356001600160a01b0316611262565b005b610452600480360360608110156104be57600080fd5b506001600160a01b038135811691602081013590911690604001356112eb565b6104a6600480360360208110156104f457600080fd5b50356001600160a01b03166114ec565b6104a66004803603602081101561051a57600080fd5b50356001600160a01b03166115f2565b6104526004803603602081101561054057600080fd5b50356001600160a01b031661163c565b61046e6116e3565b610560611707565b6040805160ff9092168252519081900360200190f35b6104a6600480360361010081101561058d57600080fd5b8101906020810181356401000000008111156105a857600080fd5b8201836020820111156105ba57600080fd5b803590602001918460018302840111640100000000831117156105dc57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929594936020810193503591505064010000000081111561062f57600080fd5b82018360208201111561064157600080fd5b8035906020019184600183028401116401000000008311171561066357600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092959493602081019350359150506401000000008111156106b657600080fd5b8201836020820111156106c857600080fd5b803590602001918460018302840111640100000000831117156106ea57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050813560ff1692505060208101356001600160a01b0390811691604081013582169160608201358116916080013516611710565b61075d61194f565b604080516001600160a01b039092168252519081900360200190f35b61046e61195e565b61075d61196d565b6104526004803603604081101561079f57600080fd5b506001600160a01b03813516906020013561197c565b6104a66119e9565b610452600480360360408110156107d357600080fd5b506001600160a01b038135169060200135611a85565b6104a6600480360360208110156107ff57600080fd5b5035611d68565b6104a66004803603604081101561081c57600080fd5b81019060208101813564010000000081111561083757600080fd5b82018360208201111561084957600080fd5b8035906020019184602083028401116401000000008311171561086b57600080fd5b91939092909160208101903564010000000081111561088957600080fd5b82018360208201111561089b57600080fd5b803590602001918460018302840111640100000000831117156108bd57600080fd5b509092509050611f77565b610452600480360360408110156108de57600080fd5b506001600160a01b0381351690602001356120b1565b6103b16121c7565b6104a66004803603602081101561091257600080fd5b50356001600160a01b03166121fe565b6104a6600480360360a081101561093857600080fd5b506001600160a01b038135169060208101359060ff604082013516906060810135906080013561230a565b61045261237d565b61046e6004803603602081101561098157600080fd5b50356001600160a01b031661238d565b6104a6600480360360408110156109a757600080fd5b506001600160a01b03813516906020013561239e565b61046e600480360360208110156109d357600080fd5b50356001600160a01b0316612419565b61046e612434565b6104a6612458565b6104a6600480360360e0811015610a0957600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359160808201359160a08101359181019060e0810160c0820135640100000000811115610a5557600080fd5b820183602082011115610a6757600080fd5b80359060200191846001830284011164010000000083111715610a8957600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506124fa945050505050565b61046e60048036036020811015610ae057600080fd5b50356001600160a01b03166125ff565b6104a660048036036040811015610b0657600080fd5b506001600160a01b03813516906020013561261a565b61075d612696565b61075d6126a5565b6103b16126ca565b61075d612743565b6104a6600480360360a0811015610b5257600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359181019060a081016080820135640100000000811115610b9257600080fd5b820183602082011115610ba457600080fd5b80359060200191846001830284011164010000000083111715610bc657600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612752945050505050565b61046e6127be565b6104a660048036036040811015610c2557600080fd5b506001600160a01b03813581169160200135166127e2565b61045260048036036040811015610c5357600080fd5b506001600160a01b0381351690602001356128fd565b61045260048036036040811015610c7f57600080fd5b506001600160a01b03813516906020013561296a565b6104a660048036036020811015610cab57600080fd5b50356001600160a01b0316612a6e565b61045260048036036020811015610cd157600080fd5b50356001600160a01b0316612b7a565b6104a660048036036020811015610cf757600080fd5b50356001600160a01b0316612b98565b6104a660048036036060811015610d1d57600080fd5b506001600160a01b03813581169160208101359091169060400135612ca4565b6104a660048036036060811015610d5357600080fd5b6001600160a01b0382351691602081013591810190606081016040820135640100000000811115610d8357600080fd5b820183602082011115610d9557600080fd5b80359060200191846001830284011164010000000083111715610db757600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612d01945050505050565b61075d612d6b565b61075d612d7a565b6104a6600480360360e0811015610e1e57600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359160808201359160a08101359181019060e0810160c0820135640100000000811115610e6a57600080fd5b820183602082011115610e7c57600080fd5b80359060200191846001830284011164010000000083111715610e9e57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612d9f945050505050565b6104a6600480360360e0811015610ef557600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c00135612e99565b6104a660048036036020811015610f4657600080fd5b810190602081018135640100000000811115610f6157600080fd5b820183602082011115610f7357600080fd5b80359060200191846001830284011164010000000083111715610f9557600080fd5b509092509050612f10565b61046e612fca565b61046e60048036036040811015610fbe57600080fd5b506001600160a01b0381358116916020013516612fee565b6104a66004803603610120811015610fed57600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060808101359060a08101359060ff60c0820135169060e0810135906101000135613019565b6103b1613122565b6104526004803603604081101561105357600080fd5b506001600160a01b03813516906020013561319b565b6104a6600480360361012081101561108057600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060808101359060a08101359060ff60c0820135169060e08101359061010001356131c6565b6104a6600480360360208110156110de57600080fd5b50356001600160a01b03166132c2565b6104a66004803603602081101561110457600080fd5b50356001600160a01b03166133ba565b6104526004803603602081101561112a57600080fd5b50356001600160a01b0316613443565b6004805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156111de5780601f106111b3576101008083540402835291602001916111de565b820191906000526020600020905b8154815290600101906020018083116111c157829003601f168201915b505050505081565b600154600090600160a01b900460ff1615611248576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b61125333848461344e565b50600192915050565b600b5490565b6002546001600160a01b031633146112ab5760405162461bcd60e51b815260040180806020018281038252602c815260200180614caa602c913960400191505060405180910390fd5b6112b48161353a565b6040516001600160a01b038216907f117e3210bb9aa7d9baff172026820255c6f6c30ba8999d1c2fd88e2848137c4e90600090a250565b600154600090600160a01b900460ff161561134d576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b3361135781613545565b156113935760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b8461139d81613545565b156113d95760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b846113e381613545565b1561141f5760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b6001600160a01b0387166000908152600a602090815260408083203384529091529020548511156114815760405162461bcd60e51b8152600401808060200182810382526028815260200180614d9a6028913960400191505060405180910390fd5b61148c878787613566565b6001600160a01b0387166000908152600a602090815260408083203384529091529020546114ba90866136af565b6001600160a01b0388166000908152600a60209081526040808320338452909152902055600193505050509392505050565b6000546001600160a01b0316331461154b576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166115905760405162461bcd60e51b815260040180806020018281038252602a815260200180614be3602a913960400191505060405180910390fd5b600e80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040517fe475e580d85111348e40d8ca33cfdd74c30fe1655c2d8537a13abc10065ffa5a90600090a250565b60125460ff1660011461160457600080fd5b600061160f3061370c565b9050801561162257611622308383613566565b61162b30613749565b50506012805460ff19166002179055565b6008546000906001600160a01b031633146116885760405162461bcd60e51b8152600401808060200182810382526029815260200180614c816029913960400191505060405180910390fd5b6001600160a01b0382166000818152600c60209081526040808320805460ff19169055600d909152808220829055517fe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb666929190a2506001919050565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60065460ff1681565b600854600160a01b900460ff16156117595760405162461bcd60e51b815260040180806020018281038252602a815260200180614e15602a913960400191505060405180910390fd5b6001600160a01b03841661179e5760405162461bcd60e51b815260040180806020018281038252602f815260200180614d47602f913960400191505060405180910390fd5b6001600160a01b0383166117e35760405162461bcd60e51b8152600401808060200182810382526029815260200180614bba6029913960400191505060405180910390fd5b6001600160a01b0382166118285760405162461bcd60e51b815260040180806020018281038252602e815260200180614dc2602e913960400191505060405180910390fd5b6001600160a01b03811661186d5760405162461bcd60e51b8152600401808060200182810382526028815260200180614f026028913960400191505060405180910390fd5b87516118809060049060208b0190614971565b5086516118949060059060208a0190614971565b5085516118a8906007906020890190614971565b506006805460ff191660ff8716179055600880547fffffffffffffffffffffffff00000000000000000000000000000000000000009081166001600160a01b03878116919091179092556001805482168684161790556002805490911691841691909117905561191781613754565b5050600880547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16600160a01b179055505050505050565b6008546001600160a01b031681565b600061196861378e565b905090565b600e546001600160a01b031690565b600154600090600160a01b900460ff16156119de576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b611253338484613883565b6001546001600160a01b03163314611a325760405162461bcd60e51b8152600401808060200182810382526022815260200180614eb66022913960400191505060405180910390fd5b600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690556040517f7805862f689e2f13df9f062ff482ad3ad112aca9e0847911ed832e158c525b3390600090a1565b600154600090600160a01b900460ff1615611ae7576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff16611b355760405162461bcd60e51b8152600401808060200182810382526021815260200180614d266021913960400191505060405180910390fd5b33611b3f81613545565b15611b7b5760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b83611b8581613545565b15611bc15760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b6001600160a01b038516611c065760405162461bcd60e51b8152600401808060200182810382526023815260200180614b4f6023913960400191505060405180910390fd5b60008411611c455760405162461bcd60e51b8152600401808060200182810382526029815260200180614c326029913960400191505060405180910390fd5b336000908152600d602052604090205480851115611c945760405162461bcd60e51b815260040180806020018281038252602e815260200180614e88602e913960400191505060405180910390fd5b600b54611ca190866138c0565b600b55611cc086611cbb87611cb58361370c565b906138c0565b613921565b611cca81866136af565b336000818152600d602090815260409182902093909355805188815290516001600160a01b038a16937fab8530f87dc9b59234c4623bf917212bb2536d647574c8e7e5da92c2ede0c9f8928290030190a36040805186815290516001600160a01b038816916000917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a350600195945050505050565b600154600160a01b900460ff1615611dc7576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff16611e155760405162461bcd60e51b8152600401808060200182810382526021815260200180614d266021913960400191505060405180910390fd5b33611e1f81613545565b15611e5b5760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b6000611e663361370c565b905060008311611ea75760405162461bcd60e51b8152600401808060200182810382526029815260200180614b266029913960400191505060405180910390fd5b82811015611ee65760405162461bcd60e51b8152600401808060200182810382526026815260200180614d006026913960400191505060405180910390fd5b600b54611ef390846136af565b600b55611f0433611cbb83866136af565b60408051848152905133917fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5919081900360200190a260408051848152905160009133917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a3505050565b60125460ff16600214611f8957600080fd5b611f95600583836149ef565b5060005b838110156120785760036000868684818110611fb157fe5b602090810292909201356001600160a01b03168352508101919091526040016000205460ff166120125760405162461bcd60e51b815260040180806020018281038252603d815260200180614a73603d913960400191505060405180910390fd5b61203685858381811061202157fe5b905060200201356001600160a01b0316613749565b6003600086868481811061204657fe5b602090810292909201356001600160a01b0316835250810191909152604001600020805460ff19169055600101611f99565b5061208230613749565b5050306000908152600360208190526040909120805460ff199081169091556012805490911690911790555050565b600154600090600160a01b900460ff1615612113576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6008546001600160a01b0316331461215c5760405162461bcd60e51b8152600401808060200182810382526029815260200180614c816029913960400191505060405180910390fd5b6001600160a01b0383166000818152600c60209081526040808320805460ff19166001179055600d825291829020859055815185815291517f46980fca912ef9bcdbd36877427b6b90e860769f604e89c0e67720cece530d209281900390910190a250600192915050565b60408051808201909152600181527f3200000000000000000000000000000000000000000000000000000000000000602082015290565b6000546001600160a01b0316331461225d576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166122a25760405162461bcd60e51b8152600401808060200182810382526028815260200180614ad36028913960400191505060405180910390fd5b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691909117918290556040519116907fb80482a293ca2e013eda8683c9bd7fc8347cfdaeea5ede58cba46df502c2a60490600090a250565b600154600160a01b900460ff1615612369576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b61237685858585856139e1565b5050505050565b600154600160a01b900460ff1681565b60006123988261370c565b92915050565b6123a66126a5565b6001600160a01b0316336001600160a01b03161461240b576040805162461bcd60e51b815260206004820152600c60248201527f4f4e4c595f474154455741590000000000000000000000000000000000000000604482015290519081900360640190fd5b6124158282613a21565b5050565b6001600160a01b031660009081526011602052604090205490565b7fd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de881565b6001546001600160a01b031633146124a15760405162461bcd60e51b8152600401808060200182810382526022815260200180614eb66022913960400191505060405180910390fd5b600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16600160a01b1790556040517f6985a02210a168e66602d3235cb6db0e70f92b3ba4d376a33c0f3d9434bff62590600090a1565b600154600160a01b900460ff1615612559576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b8661256381613545565b1561259f5760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b866125a981613545565b156125e55760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b6125f489898989898989613c43565b505050505050505050565b6001600160a01b03166000908152600d602052604090205490565b6126226126a5565b6001600160a01b0316336001600160a01b031614612687576040805162461bcd60e51b815260206004820152600c60248201527f4f4e4c595f474154455741590000000000000000000000000000000000000000604482015290519081900360640190fd5b6126918282611a85565b505050565b6000546001600160a01b031690565b7fdbf6298cab77bb44ebfd5abb25ed2538c2a55f7404c47e83e6531361fba28c245490565b6005805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156111de5780601f106111b3576101008083540402835291602001916111de565b6001546001600160a01b031681565b600154600160a01b900460ff16156127b1576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6123768585858585613d30565b7f7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a226781565b60125460ff166003146127f457600080fd5b6001600160a01b03821661284f576040805162461bcd60e51b815260206004820152600f60248201527f494e56414c49445f474154455741590000000000000000000000000000000000604482015290519081900360640190fd5b60006128596126a5565b6001600160a01b0316146128b4576040805162461bcd60e51b815260206004820152600c60248201527f414c52454144595f494e49540000000000000000000000000000000000000000604482015290519081900360640190fd5b7fdbf6298cab77bb44ebfd5abb25ed2538c2a55f7404c47e83e6531361fba28c24919091557f54352c0d7cc5793352a36344bfdcdcf68ba6258544ce1aed71f60a74d882c19155565b600154600090600160a01b900460ff161561295f576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b611253338484613fa6565b600154600090600160a01b900460ff16156129cc576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336129d681613545565b15612a125760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b83612a1c81613545565b15612a585760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b612a63338686613566565b506001949350505050565b6000546001600160a01b03163314612acd576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b038116612b125760405162461bcd60e51b815260040180806020018281038252602f815260200180614d47602f913960400191505060405180910390fd5b600880547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691909117918290556040519116907fdb66dfa9c6b8f5226fe9aac7e51897ae8ee94ac31dc70bb6c9900b2574b707e690600090a250565b6001600160a01b03166000908152600c602052604090205460ff1690565b6000546001600160a01b03163314612bf7576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b038116612c3c5760405162461bcd60e51b8152600401808060200182810382526032815260200180614f586032913960400191505060405180910390fd5b600280547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691909117918290556040519116907fc67398012c111ce95ecb7429b933096c977380ee6c421175a71a4a4c6c88c06e90600090a250565b600e546001600160a01b03163314612ced5760405162461bcd60e51b8152600401808060200182810382526024815260200180614d766024913960400191505060405180910390fd5b6126916001600160a01b0384168383613ff5565b600154600160a01b900460ff1615612d60576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b612691838383614075565b6002546001600160a01b031681565b7f54352c0d7cc5793352a36344bfdcdcf68ba6258544ce1aed71f60a74d882c1915490565b600154600160a01b900460ff1615612dfe576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b86612e0881613545565b15612e445760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b86612e4e81613545565b15612e8a5760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b6125f489898989898989614147565b600154600160a01b900460ff1615612ef8576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b612f07878787878787876141d8565b50505050505050565b600854600160a01b900460ff168015612f2c575060125460ff16155b612f3557600080fd5b612f41600483836149ef565b50612fb682828080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600181527f32000000000000000000000000000000000000000000000000000000000000006020820152915061421a9050565b600f5550506012805460ff19166001179055565b7f158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a159742981565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205490565b600154600160a01b900460ff1615613078576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b8861308281613545565b156130be5760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b886130c881613545565b156131045760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b6131158b8b8b8b8b8b8b8b8b614230565b5050505050505050505050565b6007805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156111de5780601f106111b3576101008083540402835291602001916111de565b6001600160a01b03919091166000908152601060209081526040808320938352929052205460ff1690565b600154600160a01b900460ff1615613225576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b8861322f81613545565b1561326b5760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b8861327581613545565b156132b15760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b6131158b8b8b8b8b8b8b8b8b614274565b6000546001600160a01b03163314613321576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166133665760405162461bcd60e51b8152600401808060200182810382526026815260200180614b726026913960400191505060405180910390fd5b600054604080516001600160a01b039283168152918316602083015280517f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09281900390910190a16133b781613754565b50565b6002546001600160a01b031633146134035760405162461bcd60e51b815260040180806020018281038252602c815260200180614caa602c913960400191505060405180910390fd5b61340c81613749565b6040516001600160a01b038216907fffa4e6181777692565cf28528fc88fd1516ea86b56da075235fa575af6a4b85590600090a250565b600061239882613545565b6001600160a01b0383166134935760405162461bcd60e51b8152600401808060200182810382526024815260200180614e646024913960400191505060405180910390fd5b6001600160a01b0382166134d85760405162461bcd60e51b8152600401808060200182810382526022815260200180614b986022913960400191505060405180910390fd5b6001600160a01b038084166000818152600a6020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6133b78160006142b8565b6001600160a01b031660009081526009602052604090205460ff1c60011490565b6001600160a01b0383166135ab5760405162461bcd60e51b8152600401808060200182810382526025815260200180614e3f6025913960400191505060405180910390fd5b6001600160a01b0382166135f05760405162461bcd60e51b8152600401808060200182810382526023815260200180614ab06023913960400191505060405180910390fd5b6135f98361370c565b8111156136375760405162461bcd60e51b8152600401808060200182810382526026815260200180614c5b6026913960400191505060405180910390fd5b61364e83611cbb836136488761370c565b906136af565b61365f82611cbb83611cb58661370c565b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b600082821115613706576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6001600160a01b03166000908152600960205260409020547f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690565b6133b78160016142b8565b600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6004805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152600093611968939192909183018282801561383b5780601f106138105761010080835404028352916020019161383b565b820191906000526020600020905b81548152906001019060200180831161381e57829003601f168201915b50505050506040518060400160405280600181526020017f320000000000000000000000000000000000000000000000000000000000000081525061387e614327565b61432b565b6001600160a01b038084166000908152600a602090815260408083209386168352929052205461269190849084906138bb90856138c0565b61344e565b60008282018381101561391a576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8111156139805760405162461bcd60e51b815260040180806020018281038252602a815260200180614cd6602a913960400191505060405180910390fd5b61398982613545565b156139c55760405162461bcd60e51b8152600401808060200182810382526025815260200180614c0d6025913960400191505060405180910390fd5b6001600160a01b03909116600090815260096020526040902055565b6123768585848487604051602001808481526020018381526020018260ff1660f81b81526001019350505050604051602081830303815290604052614075565b600154600160a01b900460ff1615613a80576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff16613ace5760405162461bcd60e51b8152600401808060200182810382526021815260200180614d266021913960400191505060405180910390fd5b81613ad881613545565b15613b145760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b6000613b1f8461370c565b905060008311613b605760405162461bcd60e51b8152600401808060200182810382526029815260200180614b266029913960400191505060405180910390fd5b82811015613b9f5760405162461bcd60e51b8152600401808060200182810382526026815260200180614d006026913960400191505060405180910390fd5b600b54613bac90846136af565b600b55613bbd84611cbb83866136af565b6040805184815290516001600160a01b038616917fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5919081900360200190a26040805184815290516000916001600160a01b038716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a350505050565b6001600160a01b0386163314613c8a5760405162461bcd60e51b8152600401808060200182810382526025815260200180614df06025913960400191505060405180910390fd5b613c968783868661439f565b604080517fd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de86020808301919091526001600160a01b03808b1683850152891660608301526080820188905260a0820187905260c0820186905260e0808301869052835180840390910181526101009092019092528051910120613d1b9088908361442b565b613d258783614582565b612f07878787613566565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821480613d5e5750428210155b613daf576040805162461bcd60e51b815260206004820152601e60248201527f46696174546f6b656e56323a207065726d697420697320657870697265640000604482015290519081900360640190fd5b6000613e4a613dbc61378e565b6001600160a01b0380891660008181526011602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98184015280840194909452938b166060840152608083018a905260a083019390935260c08083018990528151808403909101815260e0909201905280519101206145dc565b905073__$715109b5d747ea58b675c6ea3f0dba8c60$__636ccea6528783856040518463ffffffff1660e01b815260040180846001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015613eca578181015183820152602001613eb2565b50505050905090810190601f168015613ef75780820380516001836020036101000a031916815260200191505b5094505050505060206040518083038186803b158015613f1657600080fd5b505af4158015613f2a573d6000803e3d6000fd5b505050506040513d6020811015613f4057600080fd5b5051613f93576040805162461bcd60e51b815260206004820152601a60248201527f454950323631323a20696e76616c6964207369676e6174757265000000000000604482015290519081900360640190fd5b613f9e86868661344e565b505050505050565b61269183836138bb84604051806060016040528060258152602001614fd4602591396001600160a01b03808a166000908152600a60209081526040808320938c16835292905220549190614616565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790526126919084906146ad565b61407f838361475e565b6140ec837f158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a159742960001b858560405160200180848152602001836001600160a01b031681526020018281526020019350505050604051602081830303815290604052805190602001208361442b565b6001600160a01b0383166000818152601060209081526040808320868452909152808220805460ff19166001179055518492917f1cdd46ff242716cdaa72d159d339a485b3438398348d68f09d7c8c0a59353d8191a3505050565b6141538783868661439f565b604080517f7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a22676020808301919091526001600160a01b03808b1683850152891660608301526080820188905260a0820187905260c0820186905260e0808301869052835180840390910181526101009092019092528051910120613d1b9088908361442b565b612f0787878787868689604051602001808481526020018381526020018260ff1660f81b81526001019350505050604051602081830303815290604052613d30565b60004661422884848361432b565b949350505050565b6125f489898989898988888b604051602001808481526020018381526020018260ff1660f81b81526001019350505050604051602081830303815290604052614147565b6125f489898989898988888b604051602001808481526020018381526020018260ff1660f81b81526001019350505050604051602081830303815290604052613c43565b806142cb576142c68261370c565b614307565b6001600160a01b0382166000908152600960205260409020547f8000000000000000000000000000000000000000000000000000000000000000175b6001600160a01b0390921660009081526009602052604090209190915550565b4690565b8251602093840120825192840192909220604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8187015280820194909452606084019190915260808301919091523060a0808401919091528151808403909101815260c09092019052805191012090565b8142116143dd5760405162461bcd60e51b815260040180806020018281038252602b815260200180614afb602b913960400191505060405180910390fd5b80421061441b5760405162461bcd60e51b8152600401808060200182810382526025815260200180614faf6025913960400191505060405180910390fd5b614425848461475e565b50505050565b73__$715109b5d747ea58b675c6ea3f0dba8c60$__636ccea6528461445761445161378e565b866145dc565b846040518463ffffffff1660e01b815260040180846001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b838110156144b95781810151838201526020016144a1565b50505050905090810190601f1680156144e65780820380516001836020036101000a031916815260200191505b5094505050505060206040518083038186803b15801561450557600080fd5b505af4158015614519573d6000803e3d6000fd5b505050506040513d602081101561452f57600080fd5b5051612691576040805162461bcd60e51b815260206004820152601e60248201527f46696174546f6b656e56323a20696e76616c6964207369676e61747572650000604482015290519081900360640190fd5b6001600160a01b0382166000818152601060209081526040808320858452909152808220805460ff19166001179055518392917f98de503528ee59b575ef0c0a2576a82497bfc029a5685b209e9ec333479b10a591a35050565b6040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b600081848411156146a55760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561466a578181015183820152602001614652565b50505050905090810190601f1680156146975780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6060614702826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166147c19092919063ffffffff16565b8051909150156126915780806020019051602081101561472157600080fd5b50516126915760405162461bcd60e51b815260040180806020018281038252602a815260200180614ed8602a913960400191505060405180910390fd5b6001600160a01b038216600090815260106020908152604080832084845290915290205460ff16156124155760405162461bcd60e51b815260040180806020018281038252602e815260200180614f2a602e913960400191505060405180910390fd5b60606142288484600085856147d585614905565b614826576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b6020831061488357805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101614846565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d80600081146148e5576040519150601f19603f3d011682016040523d82523d6000602084013e6148ea565b606091505b50915091506148fa82828661490b565b979650505050505050565b3b151590565b6060831561491a57508161391a565b82511561492a5782518084602001fd5b60405162461bcd60e51b815260206004820181815284516024840152845185939192839260440191908501908083836000831561466a578181015183820152602001614652565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106149b257805160ff19168380011785556149df565b828001600101855582156149df579182015b828111156149df5782518255916020019190600101906149c4565b506149eb929150614a5d565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10614a305782800160ff198235161785556149df565b828001600101855582156149df579182015b828111156149df578235825591602001919060010190614a42565b5b808211156149eb5760008155600101614a5e56fe46696174546f6b656e56325f323a20426c61636b6c697374696e672070726576696f75736c7920756e626c61636b6c6973746564206163636f756e742145524332303a207472616e7366657220746f20746865207a65726f20616464726573735061757361626c653a206e65772070617573657220697320746865207a65726f206164647265737346696174546f6b656e56323a20617574686f72697a6174696f6e206973206e6f74207965742076616c696446696174546f6b656e3a206275726e20616d6f756e74206e6f742067726561746572207468616e203046696174546f6b656e3a206d696e7420746f20746865207a65726f20616464726573734f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737346696174546f6b656e3a206e65772070617573657220697320746865207a65726f2061646472657373526573637561626c653a206e6577207265736375657220697320746865207a65726f206164647265737346696174546f6b656e56325f323a204163636f756e7420697320626c61636b6c697374656446696174546f6b656e3a206d696e7420616d6f756e74206e6f742067726561746572207468616e203045524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636546696174546f6b656e3a2063616c6c6572206973206e6f7420746865206d61737465724d696e746572426c61636b6c69737461626c653a2063616c6c6572206973206e6f742074686520626c61636b6c697374657246696174546f6b656e56325f323a2042616c616e636520657863656564732028325e323535202d20312946696174546f6b656e3a206275726e20616d6f756e7420657863656564732062616c616e636546696174546f6b656e3a2063616c6c6572206973206e6f742061206d696e74657246696174546f6b656e3a206e6577206d61737465724d696e74657220697320746865207a65726f2061646472657373526573637561626c653a2063616c6c6572206973206e6f7420746865207265736375657245524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636546696174546f6b656e3a206e657720626c61636b6c697374657220697320746865207a65726f206164647265737346696174546f6b656e56323a2063616c6c6572206d7573742062652074686520706179656546696174546f6b656e3a20636f6e747261637420697320616c726561647920696e697469616c697a656445524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737346696174546f6b656e3a206d696e7420616d6f756e742065786365656473206d696e746572416c6c6f77616e63655061757361626c653a2063616c6c6572206973206e6f7420746865207061757365725361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656446696174546f6b656e3a206e6577206f776e657220697320746865207a65726f206164647265737346696174546f6b656e56323a20617574686f72697a6174696f6e2069732075736564206f722063616e63656c6564426c61636b6c69737461626c653a206e657720626c61636b6c697374657220697320746865207a65726f2061646472657373426c61636b6c69737461626c653a206163636f756e7420697320626c61636b6c697374656446696174546f6b656e56323a20617574686f72697a6174696f6e206973206578706972656445524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220615e051a229e77d8da0781c2c1926a3017e6914f059e90a4aa05450168f36bdc64736f6c634300060c0033' + '0x60806040526001805460ff60a01b191690556000600b553480156200002357600080fd5b506200002f3362000035565b62000057565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b61508980620000676000396000f3fe608060405234801561001057600080fd5b50600436106103a45760003560e01c80638a6db9c3116101e9578063b7b728991161010f578063dd62ed3e116100ad578063ef55bec61161007c578063ef55bec614611069578063f2fde38b146110c8578063f9f92be4146110ee578063fe575a8714611114576103a4565b8063dd62ed3e14610fa8578063e3ee160e14610fd6578063e5a6b10f14611035578063e94a01021461103d576103a4565b8063cf092995116100e9578063cf09299514610e08578063d505accf14610edf578063d608ea6414610f30578063d916948714610fa0576103a4565b8063b7b7289914610d3d578063bd10243014610df8578063c2eeeebd14610e00576103a4565b8063a0cc6a6811610187578063aa20e1e411610156578063aa20e1e414610c95578063aa271e1a14610cbb578063ad38bf2214610ce1578063b2118a8d14610d07576103a4565b8063a0cc6a6814610c07578063a297ea5e14610c0f578063a457c2d714610c3d578063a9059cbb14610c69576103a4565b80638fa74a0e116101c35780638fa74a0e14610b2457806395d89b4114610b2c5780639fd0506d14610b345780639fd5a6cf14610b3c576103a4565b80638a6db9c314610aca5780638c2a993e14610af05780638da5cb5b14610b1c576103a4565b80633f4ba83a116102ce5780635a049a701161026c5780637ecebe001161023b5780637ecebe00146109bd5780637f2eecc3146109e35780638456cb59146109eb57806388b7ab63146109f3576103a4565b80635a049a70146109225780635c975abb1461096357806370a082311461096b57806374f4f54714610991576103a4565b8063430239b4116102a8578063430239b4146108065780634e44d956146108c857806354fd4d50146108f4578063554bab3c146108fc576103a4565b80633f4ba83a146107b557806340c10f19146107bd57806342966c68146107e9576103a4565b80633092afd51161034657806335d99f351161031557806335d99f35146107555780633644e5151461077957806338a63183146107815780633950935114610789576103a4565b80633092afd51461052a57806330adf81f14610550578063313ce567146105585780633357162b14610576576103a4565b80631a895266116103825780631a8952661461048057806323b872dd146104a85780632ab60045146104de5780632fc81e0914610504576103a4565b806306fdde03146103a9578063095ea7b31461042657806318160ddd14610466575b600080fd5b6103b161113a565b6040805160208082528351818301528351919283929083019185019080838360005b838110156103eb5781810151838201526020016103d3565b50505050905090810190601f1680156104185780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6104526004803603604081101561043c57600080fd5b506001600160a01b0381351690602001356111e6565b604080519115158252519081900360200190f35b61046e61125c565b60408051918252519081900360200190f35b6104a66004803603602081101561049657600080fd5b50356001600160a01b0316611262565b005b610452600480360360608110156104be57600080fd5b506001600160a01b038135811691602081013590911690604001356112eb565b6104a6600480360360208110156104f457600080fd5b50356001600160a01b03166114ec565b6104a66004803603602081101561051a57600080fd5b50356001600160a01b03166115f2565b6104526004803603602081101561054057600080fd5b50356001600160a01b031661163c565b61046e6116e3565b610560611707565b6040805160ff9092168252519081900360200190f35b6104a6600480360361010081101561058d57600080fd5b8101906020810181356401000000008111156105a857600080fd5b8201836020820111156105ba57600080fd5b803590602001918460018302840111640100000000831117156105dc57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929594936020810193503591505064010000000081111561062f57600080fd5b82018360208201111561064157600080fd5b8035906020019184600183028401116401000000008311171561066357600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092959493602081019350359150506401000000008111156106b657600080fd5b8201836020820111156106c857600080fd5b803590602001918460018302840111640100000000831117156106ea57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050813560ff1692505060208101356001600160a01b0390811691604081013582169160608201358116916080013516611710565b61075d61194f565b604080516001600160a01b039092168252519081900360200190f35b61046e61195e565b61075d61196d565b6104526004803603604081101561079f57600080fd5b506001600160a01b03813516906020013561197c565b6104a66119e9565b610452600480360360408110156107d357600080fd5b506001600160a01b038135169060200135611a85565b6104a6600480360360208110156107ff57600080fd5b5035611d68565b6104a66004803603604081101561081c57600080fd5b81019060208101813564010000000081111561083757600080fd5b82018360208201111561084957600080fd5b8035906020019184602083028401116401000000008311171561086b57600080fd5b91939092909160208101903564010000000081111561088957600080fd5b82018360208201111561089b57600080fd5b803590602001918460018302840111640100000000831117156108bd57600080fd5b509092509050611f77565b610452600480360360408110156108de57600080fd5b506001600160a01b0381351690602001356120b1565b6103b16121c7565b6104a66004803603602081101561091257600080fd5b50356001600160a01b03166121fe565b6104a6600480360360a081101561093857600080fd5b506001600160a01b038135169060208101359060ff604082013516906060810135906080013561230a565b61045261237d565b61046e6004803603602081101561098157600080fd5b50356001600160a01b031661238d565b6104a6600480360360408110156109a757600080fd5b506001600160a01b03813516906020013561239e565b61046e600480360360208110156109d357600080fd5b50356001600160a01b0316612419565b61046e612434565b6104a6612458565b6104a6600480360360e0811015610a0957600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359160808201359160a08101359181019060e0810160c0820135640100000000811115610a5557600080fd5b820183602082011115610a6757600080fd5b80359060200191846001830284011164010000000083111715610a8957600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506124fa945050505050565b61046e60048036036020811015610ae057600080fd5b50356001600160a01b03166125ff565b6104a660048036036040811015610b0657600080fd5b506001600160a01b03813516906020013561261a565b61075d612696565b61075d6126a5565b6103b16126ca565b61075d612743565b6104a6600480360360a0811015610b5257600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359181019060a081016080820135640100000000811115610b9257600080fd5b820183602082011115610ba457600080fd5b80359060200191846001830284011164010000000083111715610bc657600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612752945050505050565b61046e6127be565b6104a660048036036040811015610c2557600080fd5b506001600160a01b03813581169160200135166127e2565b61045260048036036040811015610c5357600080fd5b506001600160a01b038135169060200135612958565b61045260048036036040811015610c7f57600080fd5b506001600160a01b0381351690602001356129c5565b6104a660048036036020811015610cab57600080fd5b50356001600160a01b0316612ac9565b61045260048036036020811015610cd157600080fd5b50356001600160a01b0316612bd5565b6104a660048036036020811015610cf757600080fd5b50356001600160a01b0316612bf3565b6104a660048036036060811015610d1d57600080fd5b506001600160a01b03813581169160208101359091169060400135612cff565b6104a660048036036060811015610d5357600080fd5b6001600160a01b0382351691602081013591810190606081016040820135640100000000811115610d8357600080fd5b820183602082011115610d9557600080fd5b80359060200191846001830284011164010000000083111715610db757600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612d5c945050505050565b61075d612dc6565b61075d612dd5565b6104a6600480360360e0811015610e1e57600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359160808201359160a08101359181019060e0810160c0820135640100000000811115610e6a57600080fd5b820183602082011115610e7c57600080fd5b80359060200191846001830284011164010000000083111715610e9e57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612dfa945050505050565b6104a6600480360360e0811015610ef557600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c00135612ef4565b6104a660048036036020811015610f4657600080fd5b810190602081018135640100000000811115610f6157600080fd5b820183602082011115610f7357600080fd5b80359060200191846001830284011164010000000083111715610f9557600080fd5b509092509050612f6b565b61046e613025565b61046e60048036036040811015610fbe57600080fd5b506001600160a01b0381358116916020013516613049565b6104a66004803603610120811015610fed57600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060808101359060a08101359060ff60c0820135169060e0810135906101000135613074565b6103b161317d565b6104526004803603604081101561105357600080fd5b506001600160a01b0381351690602001356131f6565b6104a6600480360361012081101561108057600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060808101359060a08101359060ff60c0820135169060e0810135906101000135613221565b6104a6600480360360208110156110de57600080fd5b50356001600160a01b031661331d565b6104a66004803603602081101561110457600080fd5b50356001600160a01b0316613415565b6104526004803603602081101561112a57600080fd5b50356001600160a01b031661349e565b6004805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156111de5780601f106111b3576101008083540402835291602001916111de565b820191906000526020600020905b8154815290600101906020018083116111c157829003601f168201915b505050505081565b600154600090600160a01b900460ff1615611248576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6112533384846134a9565b50600192915050565b600b5490565b6002546001600160a01b031633146112ab5760405162461bcd60e51b815260040180806020018281038252602c815260200180614d05602c913960400191505060405180910390fd5b6112b481613595565b6040516001600160a01b038216907f117e3210bb9aa7d9baff172026820255c6f6c30ba8999d1c2fd88e2848137c4e90600090a250565b600154600090600160a01b900460ff161561134d576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b33611357816135a0565b156113935760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b8461139d816135a0565b156113d95760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b846113e3816135a0565b1561141f5760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b6001600160a01b0387166000908152600a602090815260408083203384529091529020548511156114815760405162461bcd60e51b8152600401808060200182810382526028815260200180614df56028913960400191505060405180910390fd5b61148c8787876135c1565b6001600160a01b0387166000908152600a602090815260408083203384529091529020546114ba908661370a565b6001600160a01b0388166000908152600a60209081526040808320338452909152902055600193505050509392505050565b6000546001600160a01b0316331461154b576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166115905760405162461bcd60e51b815260040180806020018281038252602a815260200180614c3e602a913960400191505060405180910390fd5b600e80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040517fe475e580d85111348e40d8ca33cfdd74c30fe1655c2d8537a13abc10065ffa5a90600090a250565b60125460ff1660011461160457600080fd5b600061160f30613767565b90508015611622576116223083836135c1565b61162b306137a4565b50506012805460ff19166002179055565b6008546000906001600160a01b031633146116885760405162461bcd60e51b8152600401808060200182810382526029815260200180614cdc6029913960400191505060405180910390fd5b6001600160a01b0382166000818152600c60209081526040808320805460ff19169055600d909152808220829055517fe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb666929190a2506001919050565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60065460ff1681565b600854600160a01b900460ff16156117595760405162461bcd60e51b815260040180806020018281038252602a815260200180614e70602a913960400191505060405180910390fd5b6001600160a01b03841661179e5760405162461bcd60e51b815260040180806020018281038252602f815260200180614da2602f913960400191505060405180910390fd5b6001600160a01b0383166117e35760405162461bcd60e51b8152600401808060200182810382526029815260200180614c156029913960400191505060405180910390fd5b6001600160a01b0382166118285760405162461bcd60e51b815260040180806020018281038252602e815260200180614e1d602e913960400191505060405180910390fd5b6001600160a01b03811661186d5760405162461bcd60e51b8152600401808060200182810382526028815260200180614f5d6028913960400191505060405180910390fd5b87516118809060049060208b01906149cc565b5086516118949060059060208a01906149cc565b5085516118a89060079060208901906149cc565b506006805460ff191660ff8716179055600880547fffffffffffffffffffffffff00000000000000000000000000000000000000009081166001600160a01b038781169190911790925560018054821686841617905560028054909116918416919091179055611917816137af565b5050600880547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16600160a01b179055505050505050565b6008546001600160a01b031681565b60006119686137e9565b905090565b600e546001600160a01b031690565b600154600090600160a01b900460ff16156119de576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6112533384846138de565b6001546001600160a01b03163314611a325760405162461bcd60e51b8152600401808060200182810382526022815260200180614f116022913960400191505060405180910390fd5b600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690556040517f7805862f689e2f13df9f062ff482ad3ad112aca9e0847911ed832e158c525b3390600090a1565b600154600090600160a01b900460ff1615611ae7576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff16611b355760405162461bcd60e51b8152600401808060200182810382526021815260200180614d816021913960400191505060405180910390fd5b33611b3f816135a0565b15611b7b5760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b83611b85816135a0565b15611bc15760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b6001600160a01b038516611c065760405162461bcd60e51b8152600401808060200182810382526023815260200180614baa6023913960400191505060405180910390fd5b60008411611c455760405162461bcd60e51b8152600401808060200182810382526029815260200180614c8d6029913960400191505060405180910390fd5b336000908152600d602052604090205480851115611c945760405162461bcd60e51b815260040180806020018281038252602e815260200180614ee3602e913960400191505060405180910390fd5b600b54611ca1908661391b565b600b55611cc086611cbb87611cb583613767565b9061391b565b61397c565b611cca818661370a565b336000818152600d602090815260409182902093909355805188815290516001600160a01b038a16937fab8530f87dc9b59234c4623bf917212bb2536d647574c8e7e5da92c2ede0c9f8928290030190a36040805186815290516001600160a01b038816916000917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a350600195945050505050565b600154600160a01b900460ff1615611dc7576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff16611e155760405162461bcd60e51b8152600401808060200182810382526021815260200180614d816021913960400191505060405180910390fd5b33611e1f816135a0565b15611e5b5760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b6000611e6633613767565b905060008311611ea75760405162461bcd60e51b8152600401808060200182810382526029815260200180614b816029913960400191505060405180910390fd5b82811015611ee65760405162461bcd60e51b8152600401808060200182810382526026815260200180614d5b6026913960400191505060405180910390fd5b600b54611ef3908461370a565b600b55611f0433611cbb838661370a565b60408051848152905133917fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5919081900360200190a260408051848152905160009133917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a3505050565b60125460ff16600214611f8957600080fd5b611f9560058383614a4a565b5060005b838110156120785760036000868684818110611fb157fe5b602090810292909201356001600160a01b03168352508101919091526040016000205460ff166120125760405162461bcd60e51b815260040180806020018281038252603d815260200180614ace603d913960400191505060405180910390fd5b61203685858381811061202157fe5b905060200201356001600160a01b03166137a4565b6003600086868481811061204657fe5b602090810292909201356001600160a01b0316835250810191909152604001600020805460ff19169055600101611f99565b50612082306137a4565b5050306000908152600360208190526040909120805460ff199081169091556012805490911690911790555050565b600154600090600160a01b900460ff1615612113576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6008546001600160a01b0316331461215c5760405162461bcd60e51b8152600401808060200182810382526029815260200180614cdc6029913960400191505060405180910390fd5b6001600160a01b0383166000818152600c60209081526040808320805460ff19166001179055600d825291829020859055815185815291517f46980fca912ef9bcdbd36877427b6b90e860769f604e89c0e67720cece530d209281900390910190a250600192915050565b60408051808201909152600181527f3200000000000000000000000000000000000000000000000000000000000000602082015290565b6000546001600160a01b0316331461225d576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166122a25760405162461bcd60e51b8152600401808060200182810382526028815260200180614b2e6028913960400191505060405180910390fd5b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691909117918290556040519116907fb80482a293ca2e013eda8683c9bd7fc8347cfdaeea5ede58cba46df502c2a60490600090a250565b600154600160a01b900460ff1615612369576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6123768585858585613a3c565b5050505050565b600154600160a01b900460ff1681565b600061239882613767565b92915050565b6123a66126a5565b6001600160a01b0316336001600160a01b03161461240b576040805162461bcd60e51b815260206004820152600c60248201527f4f4e4c595f474154455741590000000000000000000000000000000000000000604482015290519081900360640190fd5b6124158282613a7c565b5050565b6001600160a01b031660009081526011602052604090205490565b7fd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de881565b6001546001600160a01b031633146124a15760405162461bcd60e51b8152600401808060200182810382526022815260200180614f116022913960400191505060405180910390fd5b600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16600160a01b1790556040517f6985a02210a168e66602d3235cb6db0e70f92b3ba4d376a33c0f3d9434bff62590600090a1565b600154600160a01b900460ff1615612559576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b86612563816135a0565b1561259f5760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b866125a9816135a0565b156125e55760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b6125f489898989898989613c9e565b505050505050505050565b6001600160a01b03166000908152600d602052604090205490565b6126226126a5565b6001600160a01b0316336001600160a01b031614612687576040805162461bcd60e51b815260206004820152600c60248201527f4f4e4c595f474154455741590000000000000000000000000000000000000000604482015290519081900360640190fd5b6126918282611a85565b505050565b6000546001600160a01b031690565b7fdbf6298cab77bb44ebfd5abb25ed2538c2a55f7404c47e83e6531361fba28c245490565b6005805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156111de5780601f106111b3576101008083540402835291602001916111de565b6001546001600160a01b031681565b600154600160a01b900460ff16156127b1576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6123768585858585613d8b565b7f7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a226781565b60125460ff166003146127f457600080fd5b6001600160a01b03821661284f576040805162461bcd60e51b815260206004820152600f60248201527f494e56414c49445f474154455741590000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b0381166128aa576040805162461bcd60e51b815260206004820152601360248201527f494e56414c49445f434f554e5445525041525400000000000000000000000000604482015290519081900360640190fd5b60006128b46126a5565b6001600160a01b03161461290f576040805162461bcd60e51b815260206004820152600c60248201527f414c52454144595f494e49540000000000000000000000000000000000000000604482015290519081900360640190fd5b7fdbf6298cab77bb44ebfd5abb25ed2538c2a55f7404c47e83e6531361fba28c24919091557f54352c0d7cc5793352a36344bfdcdcf68ba6258544ce1aed71f60a74d882c19155565b600154600090600160a01b900460ff16156129ba576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b611253338484614001565b600154600090600160a01b900460ff1615612a27576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b33612a31816135a0565b15612a6d5760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b83612a77816135a0565b15612ab35760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b612abe3386866135c1565b506001949350505050565b6000546001600160a01b03163314612b28576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b038116612b6d5760405162461bcd60e51b815260040180806020018281038252602f815260200180614da2602f913960400191505060405180910390fd5b600880547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691909117918290556040519116907fdb66dfa9c6b8f5226fe9aac7e51897ae8ee94ac31dc70bb6c9900b2574b707e690600090a250565b6001600160a01b03166000908152600c602052604090205460ff1690565b6000546001600160a01b03163314612c52576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b038116612c975760405162461bcd60e51b8152600401808060200182810382526032815260200180614fb36032913960400191505060405180910390fd5b600280547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691909117918290556040519116907fc67398012c111ce95ecb7429b933096c977380ee6c421175a71a4a4c6c88c06e90600090a250565b600e546001600160a01b03163314612d485760405162461bcd60e51b8152600401808060200182810382526024815260200180614dd16024913960400191505060405180910390fd5b6126916001600160a01b0384168383614050565b600154600160a01b900460ff1615612dbb576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6126918383836140d0565b6002546001600160a01b031681565b7f54352c0d7cc5793352a36344bfdcdcf68ba6258544ce1aed71f60a74d882c1915490565b600154600160a01b900460ff1615612e59576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b86612e63816135a0565b15612e9f5760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b86612ea9816135a0565b15612ee55760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b6125f4898989898989896141a2565b600154600160a01b900460ff1615612f53576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b612f6287878787878787614233565b50505050505050565b600854600160a01b900460ff168015612f87575060125460ff16155b612f9057600080fd5b612f9c60048383614a4a565b5061301182828080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600181527f3200000000000000000000000000000000000000000000000000000000000000602082015291506142759050565b600f5550506012805460ff19166001179055565b7f158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a159742981565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205490565b600154600160a01b900460ff16156130d3576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b886130dd816135a0565b156131195760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b88613123816135a0565b1561315f5760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b6131708b8b8b8b8b8b8b8b8b61428b565b5050505050505050505050565b6007805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156111de5780601f106111b3576101008083540402835291602001916111de565b6001600160a01b03919091166000908152601060209081526040808320938352929052205460ff1690565b600154600160a01b900460ff1615613280576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b8861328a816135a0565b156132c65760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b886132d0816135a0565b1561330c5760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b6131708b8b8b8b8b8b8b8b8b6142cf565b6000546001600160a01b0316331461337c576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166133c15760405162461bcd60e51b8152600401808060200182810382526026815260200180614bcd6026913960400191505060405180910390fd5b600054604080516001600160a01b039283168152918316602083015280517f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09281900390910190a1613412816137af565b50565b6002546001600160a01b0316331461345e5760405162461bcd60e51b815260040180806020018281038252602c815260200180614d05602c913960400191505060405180910390fd5b613467816137a4565b6040516001600160a01b038216907fffa4e6181777692565cf28528fc88fd1516ea86b56da075235fa575af6a4b85590600090a250565b6000612398826135a0565b6001600160a01b0383166134ee5760405162461bcd60e51b8152600401808060200182810382526024815260200180614ebf6024913960400191505060405180910390fd5b6001600160a01b0382166135335760405162461bcd60e51b8152600401808060200182810382526022815260200180614bf36022913960400191505060405180910390fd5b6001600160a01b038084166000818152600a6020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b613412816000614313565b6001600160a01b031660009081526009602052604090205460ff1c60011490565b6001600160a01b0383166136065760405162461bcd60e51b8152600401808060200182810382526025815260200180614e9a6025913960400191505060405180910390fd5b6001600160a01b03821661364b5760405162461bcd60e51b8152600401808060200182810382526023815260200180614b0b6023913960400191505060405180910390fd5b61365483613767565b8111156136925760405162461bcd60e51b8152600401808060200182810382526026815260200180614cb66026913960400191505060405180910390fd5b6136a983611cbb836136a387613767565b9061370a565b6136ba82611cbb83611cb586613767565b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b600082821115613761576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6001600160a01b03166000908152600960205260409020547f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690565b613412816001614313565b600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6004805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815260009361196893919290918301828280156138965780601f1061386b57610100808354040283529160200191613896565b820191906000526020600020905b81548152906001019060200180831161387957829003601f168201915b50505050506040518060400160405280600181526020017f32000000000000000000000000000000000000000000000000000000000000008152506138d9614382565b614386565b6001600160a01b038084166000908152600a60209081526040808320938616835292905220546126919084908490613916908561391b565b6134a9565b600082820183811015613975576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8111156139db5760405162461bcd60e51b815260040180806020018281038252602a815260200180614d31602a913960400191505060405180910390fd5b6139e4826135a0565b15613a205760405162461bcd60e51b8152600401808060200182810382526025815260200180614c686025913960400191505060405180910390fd5b6001600160a01b03909116600090815260096020526040902055565b6123768585848487604051602001808481526020018381526020018260ff1660f81b815260010193505050506040516020818303038152906040526140d0565b600154600160a01b900460ff1615613adb576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff16613b295760405162461bcd60e51b8152600401808060200182810382526021815260200180614d816021913960400191505060405180910390fd5b81613b33816135a0565b15613b6f5760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b6000613b7a84613767565b905060008311613bbb5760405162461bcd60e51b8152600401808060200182810382526029815260200180614b816029913960400191505060405180910390fd5b82811015613bfa5760405162461bcd60e51b8152600401808060200182810382526026815260200180614d5b6026913960400191505060405180910390fd5b600b54613c07908461370a565b600b55613c1884611cbb838661370a565b6040805184815290516001600160a01b038616917fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5919081900360200190a26040805184815290516000916001600160a01b038716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a350505050565b6001600160a01b0386163314613ce55760405162461bcd60e51b8152600401808060200182810382526025815260200180614e4b6025913960400191505060405180910390fd5b613cf1878386866143fa565b604080517fd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de86020808301919091526001600160a01b03808b1683850152891660608301526080820188905260a0820187905260c0820186905260e0808301869052835180840390910181526101009092019092528051910120613d7690889083614486565b613d8087836145dd565b612f628787876135c1565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821480613db95750428210155b613e0a576040805162461bcd60e51b815260206004820152601e60248201527f46696174546f6b656e56323a207065726d697420697320657870697265640000604482015290519081900360640190fd5b6000613ea5613e176137e9565b6001600160a01b0380891660008181526011602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98184015280840194909452938b166060840152608083018a905260a083019390935260c08083018990528151808403909101815260e090920190528051910120614637565b905073__$715109b5d747ea58b675c6ea3f0dba8c60$__636ccea6528783856040518463ffffffff1660e01b815260040180846001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015613f25578181015183820152602001613f0d565b50505050905090810190601f168015613f525780820380516001836020036101000a031916815260200191505b5094505050505060206040518083038186803b158015613f7157600080fd5b505af4158015613f85573d6000803e3d6000fd5b505050506040513d6020811015613f9b57600080fd5b5051613fee576040805162461bcd60e51b815260206004820152601a60248201527f454950323631323a20696e76616c6964207369676e6174757265000000000000604482015290519081900360640190fd5b613ff98686866134a9565b505050505050565b61269183836139168460405180606001604052806025815260200161502f602591396001600160a01b03808a166000908152600a60209081526040808320938c16835292905220549190614671565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052612691908490614708565b6140da83836147b9565b614147837f158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a159742960001b858560405160200180848152602001836001600160a01b0316815260200182815260200193505050506040516020818303038152906040528051906020012083614486565b6001600160a01b0383166000818152601060209081526040808320868452909152808220805460ff19166001179055518492917f1cdd46ff242716cdaa72d159d339a485b3438398348d68f09d7c8c0a59353d8191a3505050565b6141ae878386866143fa565b604080517f7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a22676020808301919091526001600160a01b03808b1683850152891660608301526080820188905260a0820187905260c0820186905260e0808301869052835180840390910181526101009092019092528051910120613d7690889083614486565b612f6287878787868689604051602001808481526020018381526020018260ff1660f81b81526001019350505050604051602081830303815290604052613d8b565b600046614283848483614386565b949350505050565b6125f489898989898988888b604051602001808481526020018381526020018260ff1660f81b815260010193505050506040516020818303038152906040526141a2565b6125f489898989898988888b604051602001808481526020018381526020018260ff1660f81b81526001019350505050604051602081830303815290604052613c9e565b806143265761432182613767565b614362565b6001600160a01b0382166000908152600960205260409020547f8000000000000000000000000000000000000000000000000000000000000000175b6001600160a01b0390921660009081526009602052604090209190915550565b4690565b8251602093840120825192840192909220604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8187015280820194909452606084019190915260808301919091523060a0808401919091528151808403909101815260c09092019052805191012090565b8142116144385760405162461bcd60e51b815260040180806020018281038252602b815260200180614b56602b913960400191505060405180910390fd5b8042106144765760405162461bcd60e51b815260040180806020018281038252602581526020018061500a6025913960400191505060405180910390fd5b61448084846147b9565b50505050565b73__$715109b5d747ea58b675c6ea3f0dba8c60$__636ccea652846144b26144ac6137e9565b86614637565b846040518463ffffffff1660e01b815260040180846001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b838110156145145781810151838201526020016144fc565b50505050905090810190601f1680156145415780820380516001836020036101000a031916815260200191505b5094505050505060206040518083038186803b15801561456057600080fd5b505af4158015614574573d6000803e3d6000fd5b505050506040513d602081101561458a57600080fd5b5051612691576040805162461bcd60e51b815260206004820152601e60248201527f46696174546f6b656e56323a20696e76616c6964207369676e61747572650000604482015290519081900360640190fd5b6001600160a01b0382166000818152601060209081526040808320858452909152808220805460ff19166001179055518392917f98de503528ee59b575ef0c0a2576a82497bfc029a5685b209e9ec333479b10a591a35050565b6040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b600081848411156147005760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156146c55781810151838201526020016146ad565b50505050905090810190601f1680156146f25780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b606061475d826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661481c9092919063ffffffff16565b8051909150156126915780806020019051602081101561477c57600080fd5b50516126915760405162461bcd60e51b815260040180806020018281038252602a815260200180614f33602a913960400191505060405180910390fd5b6001600160a01b038216600090815260106020908152604080832084845290915290205460ff16156124155760405162461bcd60e51b815260040180806020018281038252602e815260200180614f85602e913960400191505060405180910390fd5b606061428384846000858561483085614960565b614881576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b602083106148de57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016148a1565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114614940576040519150601f19603f3d011682016040523d82523d6000602084013e614945565b606091505b5091509150614955828286614966565b979650505050505050565b3b151590565b60608315614975575081613975565b8251156149855782518084602001fd5b60405162461bcd60e51b81526020600482018181528451602484015284518593919283926044019190850190808383600083156146c55781810151838201526020016146ad565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10614a0d57805160ff1916838001178555614a3a565b82800160010185558215614a3a579182015b82811115614a3a578251825591602001919060010190614a1f565b50614a46929150614ab8565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10614a8b5782800160ff19823516178555614a3a565b82800160010185558215614a3a579182015b82811115614a3a578235825591602001919060010190614a9d565b5b80821115614a465760008155600101614ab956fe46696174546f6b656e56325f323a20426c61636b6c697374696e672070726576696f75736c7920756e626c61636b6c6973746564206163636f756e742145524332303a207472616e7366657220746f20746865207a65726f20616464726573735061757361626c653a206e65772070617573657220697320746865207a65726f206164647265737346696174546f6b656e56323a20617574686f72697a6174696f6e206973206e6f74207965742076616c696446696174546f6b656e3a206275726e20616d6f756e74206e6f742067726561746572207468616e203046696174546f6b656e3a206d696e7420746f20746865207a65726f20616464726573734f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737346696174546f6b656e3a206e65772070617573657220697320746865207a65726f2061646472657373526573637561626c653a206e6577207265736375657220697320746865207a65726f206164647265737346696174546f6b656e56325f323a204163636f756e7420697320626c61636b6c697374656446696174546f6b656e3a206d696e7420616d6f756e74206e6f742067726561746572207468616e203045524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636546696174546f6b656e3a2063616c6c6572206973206e6f7420746865206d61737465724d696e746572426c61636b6c69737461626c653a2063616c6c6572206973206e6f742074686520626c61636b6c697374657246696174546f6b656e56325f323a2042616c616e636520657863656564732028325e323535202d20312946696174546f6b656e3a206275726e20616d6f756e7420657863656564732062616c616e636546696174546f6b656e3a2063616c6c6572206973206e6f742061206d696e74657246696174546f6b656e3a206e6577206d61737465724d696e74657220697320746865207a65726f2061646472657373526573637561626c653a2063616c6c6572206973206e6f7420746865207265736375657245524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636546696174546f6b656e3a206e657720626c61636b6c697374657220697320746865207a65726f206164647265737346696174546f6b656e56323a2063616c6c6572206d7573742062652074686520706179656546696174546f6b656e3a20636f6e747261637420697320616c726561647920696e697469616c697a656445524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737346696174546f6b656e3a206d696e7420616d6f756e742065786365656473206d696e746572416c6c6f77616e63655061757361626c653a2063616c6c6572206973206e6f7420746865207061757365725361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656446696174546f6b656e3a206e6577206f776e657220697320746865207a65726f206164647265737346696174546f6b656e56323a20617574686f72697a6174696f6e2069732075736564206f722063616e63656c6564426c61636b6c69737461626c653a206e657720626c61636b6c697374657220697320746865207a65726f2061646472657373426c61636b6c69737461626c653a206163636f756e7420697320626c61636b6c697374656446696174546f6b656e56323a20617574686f72697a6174696f6e206973206578706972656445524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122069f43cc6c29d58063264d46f6f667d8af0c0a5209b8e811c80c4675b7ac594b364736f6c634300060c0033' const placeholder = '__$715109b5d747ea58b675c6ea3f0dba8c60$__' const libAddressStripped = sigCheckerLib.address.replace(/^0x/, '') diff --git a/test-foundry/util/TestUtil.sol b/test-foundry/util/TestUtil.sol index d1954e469c..c69795d935 100644 --- a/test-foundry/util/TestUtil.sol +++ b/test-foundry/util/TestUtil.sol @@ -26,13 +26,13 @@ library TestUtil { // insert lib address into bytecode bytes memory b1 = - hex"60806040526001805460ff60a01b191690556000600b553480156200002357600080fd5b506200002f3362000035565b62000057565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b61502e80620000676000396000f3fe608060405234801561001057600080fd5b50600436106103a45760003560e01c80638a6db9c3116101e9578063b7b728991161010f578063dd62ed3e116100ad578063ef55bec61161007c578063ef55bec614611069578063f2fde38b146110c8578063f9f92be4146110ee578063fe575a8714611114576103a4565b8063dd62ed3e14610fa8578063e3ee160e14610fd6578063e5a6b10f14611035578063e94a01021461103d576103a4565b8063cf092995116100e9578063cf09299514610e08578063d505accf14610edf578063d608ea6414610f30578063d916948714610fa0576103a4565b8063b7b7289914610d3d578063bd10243014610df8578063c2eeeebd14610e00576103a4565b8063a0cc6a6811610187578063aa20e1e411610156578063aa20e1e414610c95578063aa271e1a14610cbb578063ad38bf2214610ce1578063b2118a8d14610d07576103a4565b8063a0cc6a6814610c07578063a297ea5e14610c0f578063a457c2d714610c3d578063a9059cbb14610c69576103a4565b80638fa74a0e116101c35780638fa74a0e14610b2457806395d89b4114610b2c5780639fd0506d14610b345780639fd5a6cf14610b3c576103a4565b80638a6db9c314610aca5780638c2a993e14610af05780638da5cb5b14610b1c576103a4565b80633f4ba83a116102ce5780635a049a701161026c5780637ecebe001161023b5780637ecebe00146109bd5780637f2eecc3146109e35780638456cb59146109eb57806388b7ab63146109f3576103a4565b80635a049a70146109225780635c975abb1461096357806370a082311461096b57806374f4f54714610991576103a4565b8063430239b4116102a8578063430239b4146108065780634e44d956146108c857806354fd4d50146108f4578063554bab3c146108fc576103a4565b80633f4ba83a146107b557806340c10f19146107bd57806342966c68146107e9576103a4565b80633092afd51161034657806335d99f351161031557806335d99f35146107555780633644e5151461077957806338a63183146107815780633950935114610789576103a4565b80633092afd51461052a57806330adf81f14610550578063313ce567146105585780633357162b14610576576103a4565b80631a895266116103825780631a8952661461048057806323b872dd146104a85780632ab60045146104de5780632fc81e0914610504576103a4565b806306fdde03146103a9578063095ea7b31461042657806318160ddd14610466575b600080fd5b6103b161113a565b6040805160208082528351818301528351919283929083019185019080838360005b838110156103eb5781810151838201526020016103d3565b50505050905090810190601f1680156104185780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6104526004803603604081101561043c57600080fd5b506001600160a01b0381351690602001356111e6565b604080519115158252519081900360200190f35b61046e61125c565b60408051918252519081900360200190f35b6104a66004803603602081101561049657600080fd5b50356001600160a01b0316611262565b005b610452600480360360608110156104be57600080fd5b506001600160a01b038135811691602081013590911690604001356112eb565b6104a6600480360360208110156104f457600080fd5b50356001600160a01b03166114ec565b6104a66004803603602081101561051a57600080fd5b50356001600160a01b03166115f2565b6104526004803603602081101561054057600080fd5b50356001600160a01b031661163c565b61046e6116e3565b610560611707565b6040805160ff9092168252519081900360200190f35b6104a6600480360361010081101561058d57600080fd5b8101906020810181356401000000008111156105a857600080fd5b8201836020820111156105ba57600080fd5b803590602001918460018302840111640100000000831117156105dc57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929594936020810193503591505064010000000081111561062f57600080fd5b82018360208201111561064157600080fd5b8035906020019184600183028401116401000000008311171561066357600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092959493602081019350359150506401000000008111156106b657600080fd5b8201836020820111156106c857600080fd5b803590602001918460018302840111640100000000831117156106ea57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050813560ff1692505060208101356001600160a01b0390811691604081013582169160608201358116916080013516611710565b61075d61194f565b604080516001600160a01b039092168252519081900360200190f35b61046e61195e565b61075d61196d565b6104526004803603604081101561079f57600080fd5b506001600160a01b03813516906020013561197c565b6104a66119e9565b610452600480360360408110156107d357600080fd5b506001600160a01b038135169060200135611a85565b6104a6600480360360208110156107ff57600080fd5b5035611d68565b6104a66004803603604081101561081c57600080fd5b81019060208101813564010000000081111561083757600080fd5b82018360208201111561084957600080fd5b8035906020019184602083028401116401000000008311171561086b57600080fd5b91939092909160208101903564010000000081111561088957600080fd5b82018360208201111561089b57600080fd5b803590602001918460018302840111640100000000831117156108bd57600080fd5b509092509050611f77565b610452600480360360408110156108de57600080fd5b506001600160a01b0381351690602001356120b1565b6103b16121c7565b6104a66004803603602081101561091257600080fd5b50356001600160a01b03166121fe565b6104a6600480360360a081101561093857600080fd5b506001600160a01b038135169060208101359060ff604082013516906060810135906080013561230a565b61045261237d565b61046e6004803603602081101561098157600080fd5b50356001600160a01b031661238d565b6104a6600480360360408110156109a757600080fd5b506001600160a01b03813516906020013561239e565b61046e600480360360208110156109d357600080fd5b50356001600160a01b0316612419565b61046e612434565b6104a6612458565b6104a6600480360360e0811015610a0957600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359160808201359160a08101359181019060e0810160c0820135640100000000811115610a5557600080fd5b820183602082011115610a6757600080fd5b80359060200191846001830284011164010000000083111715610a8957600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506124fa945050505050565b61046e60048036036020811015610ae057600080fd5b50356001600160a01b03166125ff565b6104a660048036036040811015610b0657600080fd5b506001600160a01b03813516906020013561261a565b61075d612696565b61075d6126a5565b6103b16126ca565b61075d612743565b6104a6600480360360a0811015610b5257600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359181019060a081016080820135640100000000811115610b9257600080fd5b820183602082011115610ba457600080fd5b80359060200191846001830284011164010000000083111715610bc657600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612752945050505050565b61046e6127be565b6104a660048036036040811015610c2557600080fd5b506001600160a01b03813581169160200135166127e2565b61045260048036036040811015610c5357600080fd5b506001600160a01b0381351690602001356128fd565b61045260048036036040811015610c7f57600080fd5b506001600160a01b03813516906020013561296a565b6104a660048036036020811015610cab57600080fd5b50356001600160a01b0316612a6e565b61045260048036036020811015610cd157600080fd5b50356001600160a01b0316612b7a565b6104a660048036036020811015610cf757600080fd5b50356001600160a01b0316612b98565b6104a660048036036060811015610d1d57600080fd5b506001600160a01b03813581169160208101359091169060400135612ca4565b6104a660048036036060811015610d5357600080fd5b6001600160a01b0382351691602081013591810190606081016040820135640100000000811115610d8357600080fd5b820183602082011115610d9557600080fd5b80359060200191846001830284011164010000000083111715610db757600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612d01945050505050565b61075d612d6b565b61075d612d7a565b6104a6600480360360e0811015610e1e57600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359160808201359160a08101359181019060e0810160c0820135640100000000811115610e6a57600080fd5b820183602082011115610e7c57600080fd5b80359060200191846001830284011164010000000083111715610e9e57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612d9f945050505050565b6104a6600480360360e0811015610ef557600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c00135612e99565b6104a660048036036020811015610f4657600080fd5b810190602081018135640100000000811115610f6157600080fd5b820183602082011115610f7357600080fd5b80359060200191846001830284011164010000000083111715610f9557600080fd5b509092509050612f10565b61046e612fca565b61046e60048036036040811015610fbe57600080fd5b506001600160a01b0381358116916020013516612fee565b6104a66004803603610120811015610fed57600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060808101359060a08101359060ff60c0820135169060e0810135906101000135613019565b6103b1613122565b6104526004803603604081101561105357600080fd5b506001600160a01b03813516906020013561319b565b6104a6600480360361012081101561108057600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060808101359060a08101359060ff60c0820135169060e08101359061010001356131c6565b6104a6600480360360208110156110de57600080fd5b50356001600160a01b03166132c2565b6104a66004803603602081101561110457600080fd5b50356001600160a01b03166133ba565b6104526004803603602081101561112a57600080fd5b50356001600160a01b0316613443565b6004805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156111de5780601f106111b3576101008083540402835291602001916111de565b820191906000526020600020905b8154815290600101906020018083116111c157829003601f168201915b505050505081565b600154600090600160a01b900460ff1615611248576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b61125333848461344e565b50600192915050565b600b5490565b6002546001600160a01b031633146112ab5760405162461bcd60e51b815260040180806020018281038252602c815260200180614caa602c913960400191505060405180910390fd5b6112b48161353a565b6040516001600160a01b038216907f117e3210bb9aa7d9baff172026820255c6f6c30ba8999d1c2fd88e2848137c4e90600090a250565b600154600090600160a01b900460ff161561134d576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b3361135781613545565b156113935760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b8461139d81613545565b156113d95760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b846113e381613545565b1561141f5760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b6001600160a01b0387166000908152600a602090815260408083203384529091529020548511156114815760405162461bcd60e51b8152600401808060200182810382526028815260200180614d9a6028913960400191505060405180910390fd5b61148c878787613566565b6001600160a01b0387166000908152600a602090815260408083203384529091529020546114ba90866136af565b6001600160a01b0388166000908152600a60209081526040808320338452909152902055600193505050509392505050565b6000546001600160a01b0316331461154b576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166115905760405162461bcd60e51b815260040180806020018281038252602a815260200180614be3602a913960400191505060405180910390fd5b600e80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040517fe475e580d85111348e40d8ca33cfdd74c30fe1655c2d8537a13abc10065ffa5a90600090a250565b60125460ff1660011461160457600080fd5b600061160f3061370c565b9050801561162257611622308383613566565b61162b30613749565b50506012805460ff19166002179055565b6008546000906001600160a01b031633146116885760405162461bcd60e51b8152600401808060200182810382526029815260200180614c816029913960400191505060405180910390fd5b6001600160a01b0382166000818152600c60209081526040808320805460ff19169055600d909152808220829055517fe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb666929190a2506001919050565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60065460ff1681565b600854600160a01b900460ff16156117595760405162461bcd60e51b815260040180806020018281038252602a815260200180614e15602a913960400191505060405180910390fd5b6001600160a01b03841661179e5760405162461bcd60e51b815260040180806020018281038252602f815260200180614d47602f913960400191505060405180910390fd5b6001600160a01b0383166117e35760405162461bcd60e51b8152600401808060200182810382526029815260200180614bba6029913960400191505060405180910390fd5b6001600160a01b0382166118285760405162461bcd60e51b815260040180806020018281038252602e815260200180614dc2602e913960400191505060405180910390fd5b6001600160a01b03811661186d5760405162461bcd60e51b8152600401808060200182810382526028815260200180614f026028913960400191505060405180910390fd5b87516118809060049060208b0190614971565b5086516118949060059060208a0190614971565b5085516118a8906007906020890190614971565b506006805460ff191660ff8716179055600880547fffffffffffffffffffffffff00000000000000000000000000000000000000009081166001600160a01b03878116919091179092556001805482168684161790556002805490911691841691909117905561191781613754565b5050600880547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16600160a01b179055505050505050565b6008546001600160a01b031681565b600061196861378e565b905090565b600e546001600160a01b031690565b600154600090600160a01b900460ff16156119de576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b611253338484613883565b6001546001600160a01b03163314611a325760405162461bcd60e51b8152600401808060200182810382526022815260200180614eb66022913960400191505060405180910390fd5b600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690556040517f7805862f689e2f13df9f062ff482ad3ad112aca9e0847911ed832e158c525b3390600090a1565b600154600090600160a01b900460ff1615611ae7576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff16611b355760405162461bcd60e51b8152600401808060200182810382526021815260200180614d266021913960400191505060405180910390fd5b33611b3f81613545565b15611b7b5760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b83611b8581613545565b15611bc15760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b6001600160a01b038516611c065760405162461bcd60e51b8152600401808060200182810382526023815260200180614b4f6023913960400191505060405180910390fd5b60008411611c455760405162461bcd60e51b8152600401808060200182810382526029815260200180614c326029913960400191505060405180910390fd5b336000908152600d602052604090205480851115611c945760405162461bcd60e51b815260040180806020018281038252602e815260200180614e88602e913960400191505060405180910390fd5b600b54611ca190866138c0565b600b55611cc086611cbb87611cb58361370c565b906138c0565b613921565b611cca81866136af565b336000818152600d602090815260409182902093909355805188815290516001600160a01b038a16937fab8530f87dc9b59234c4623bf917212bb2536d647574c8e7e5da92c2ede0c9f8928290030190a36040805186815290516001600160a01b038816916000917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a350600195945050505050565b600154600160a01b900460ff1615611dc7576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff16611e155760405162461bcd60e51b8152600401808060200182810382526021815260200180614d266021913960400191505060405180910390fd5b33611e1f81613545565b15611e5b5760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b6000611e663361370c565b905060008311611ea75760405162461bcd60e51b8152600401808060200182810382526029815260200180614b266029913960400191505060405180910390fd5b82811015611ee65760405162461bcd60e51b8152600401808060200182810382526026815260200180614d006026913960400191505060405180910390fd5b600b54611ef390846136af565b600b55611f0433611cbb83866136af565b60408051848152905133917fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5919081900360200190a260408051848152905160009133917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a3505050565b60125460ff16600214611f8957600080fd5b611f95600583836149ef565b5060005b838110156120785760036000868684818110611fb157fe5b602090810292909201356001600160a01b03168352508101919091526040016000205460ff166120125760405162461bcd60e51b815260040180806020018281038252603d815260200180614a73603d913960400191505060405180910390fd5b61203685858381811061202157fe5b905060200201356001600160a01b0316613749565b6003600086868481811061204657fe5b602090810292909201356001600160a01b0316835250810191909152604001600020805460ff19169055600101611f99565b5061208230613749565b5050306000908152600360208190526040909120805460ff199081169091556012805490911690911790555050565b600154600090600160a01b900460ff1615612113576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6008546001600160a01b0316331461215c5760405162461bcd60e51b8152600401808060200182810382526029815260200180614c816029913960400191505060405180910390fd5b6001600160a01b0383166000818152600c60209081526040808320805460ff19166001179055600d825291829020859055815185815291517f46980fca912ef9bcdbd36877427b6b90e860769f604e89c0e67720cece530d209281900390910190a250600192915050565b60408051808201909152600181527f3200000000000000000000000000000000000000000000000000000000000000602082015290565b6000546001600160a01b0316331461225d576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166122a25760405162461bcd60e51b8152600401808060200182810382526028815260200180614ad36028913960400191505060405180910390fd5b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691909117918290556040519116907fb80482a293ca2e013eda8683c9bd7fc8347cfdaeea5ede58cba46df502c2a60490600090a250565b600154600160a01b900460ff1615612369576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b61237685858585856139e1565b5050505050565b600154600160a01b900460ff1681565b60006123988261370c565b92915050565b6123a66126a5565b6001600160a01b0316336001600160a01b03161461240b576040805162461bcd60e51b815260206004820152600c60248201527f4f4e4c595f474154455741590000000000000000000000000000000000000000604482015290519081900360640190fd5b6124158282613a21565b5050565b6001600160a01b031660009081526011602052604090205490565b7fd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de881565b6001546001600160a01b031633146124a15760405162461bcd60e51b8152600401808060200182810382526022815260200180614eb66022913960400191505060405180910390fd5b600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16600160a01b1790556040517f6985a02210a168e66602d3235cb6db0e70f92b3ba4d376a33c0f3d9434bff62590600090a1565b600154600160a01b900460ff1615612559576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b8661256381613545565b1561259f5760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b866125a981613545565b156125e55760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b6125f489898989898989613c43565b505050505050505050565b6001600160a01b03166000908152600d602052604090205490565b6126226126a5565b6001600160a01b0316336001600160a01b031614612687576040805162461bcd60e51b815260206004820152600c60248201527f4f4e4c595f474154455741590000000000000000000000000000000000000000604482015290519081900360640190fd5b6126918282611a85565b505050565b6000546001600160a01b031690565b7fdbf6298cab77bb44ebfd5abb25ed2538c2a55f7404c47e83e6531361fba28c245490565b6005805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156111de5780601f106111b3576101008083540402835291602001916111de565b6001546001600160a01b031681565b600154600160a01b900460ff16156127b1576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6123768585858585613d30565b7f7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a226781565b60125460ff166003146127f457600080fd5b6001600160a01b03821661284f576040805162461bcd60e51b815260206004820152600f60248201527f494e56414c49445f474154455741590000000000000000000000000000000000604482015290519081900360640190fd5b60006128596126a5565b6001600160a01b0316146128b4576040805162461bcd60e51b815260206004820152600c60248201527f414c52454144595f494e49540000000000000000000000000000000000000000604482015290519081900360640190fd5b7fdbf6298cab77bb44ebfd5abb25ed2538c2a55f7404c47e83e6531361fba28c24919091557f54352c0d7cc5793352a36344bfdcdcf68ba6258544ce1aed71f60a74d882c19155565b600154600090600160a01b900460ff161561295f576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b611253338484613fa6565b600154600090600160a01b900460ff16156129cc576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336129d681613545565b15612a125760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b83612a1c81613545565b15612a585760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b612a63338686613566565b506001949350505050565b6000546001600160a01b03163314612acd576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b038116612b125760405162461bcd60e51b815260040180806020018281038252602f815260200180614d47602f913960400191505060405180910390fd5b600880547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691909117918290556040519116907fdb66dfa9c6b8f5226fe9aac7e51897ae8ee94ac31dc70bb6c9900b2574b707e690600090a250565b6001600160a01b03166000908152600c602052604090205460ff1690565b6000546001600160a01b03163314612bf7576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b038116612c3c5760405162461bcd60e51b8152600401808060200182810382526032815260200180614f586032913960400191505060405180910390fd5b600280547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691909117918290556040519116907fc67398012c111ce95ecb7429b933096c977380ee6c421175a71a4a4c6c88c06e90600090a250565b600e546001600160a01b03163314612ced5760405162461bcd60e51b8152600401808060200182810382526024815260200180614d766024913960400191505060405180910390fd5b6126916001600160a01b0384168383613ff5565b600154600160a01b900460ff1615612d60576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b612691838383614075565b6002546001600160a01b031681565b7f54352c0d7cc5793352a36344bfdcdcf68ba6258544ce1aed71f60a74d882c1915490565b600154600160a01b900460ff1615612dfe576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b86612e0881613545565b15612e445760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b86612e4e81613545565b15612e8a5760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b6125f489898989898989614147565b600154600160a01b900460ff1615612ef8576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b612f07878787878787876141d8565b50505050505050565b600854600160a01b900460ff168015612f2c575060125460ff16155b612f3557600080fd5b612f41600483836149ef565b50612fb682828080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600181527f32000000000000000000000000000000000000000000000000000000000000006020820152915061421a9050565b600f5550506012805460ff19166001179055565b7f158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a159742981565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205490565b600154600160a01b900460ff1615613078576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b8861308281613545565b156130be5760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b886130c881613545565b156131045760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b6131158b8b8b8b8b8b8b8b8b614230565b5050505050505050505050565b6007805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156111de5780601f106111b3576101008083540402835291602001916111de565b6001600160a01b03919091166000908152601060209081526040808320938352929052205460ff1690565b600154600160a01b900460ff1615613225576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b8861322f81613545565b1561326b5760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b8861327581613545565b156132b15760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b6131158b8b8b8b8b8b8b8b8b614274565b6000546001600160a01b03163314613321576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166133665760405162461bcd60e51b8152600401808060200182810382526026815260200180614b726026913960400191505060405180910390fd5b600054604080516001600160a01b039283168152918316602083015280517f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09281900390910190a16133b781613754565b50565b6002546001600160a01b031633146134035760405162461bcd60e51b815260040180806020018281038252602c815260200180614caa602c913960400191505060405180910390fd5b61340c81613749565b6040516001600160a01b038216907fffa4e6181777692565cf28528fc88fd1516ea86b56da075235fa575af6a4b85590600090a250565b600061239882613545565b6001600160a01b0383166134935760405162461bcd60e51b8152600401808060200182810382526024815260200180614e646024913960400191505060405180910390fd5b6001600160a01b0382166134d85760405162461bcd60e51b8152600401808060200182810382526022815260200180614b986022913960400191505060405180910390fd5b6001600160a01b038084166000818152600a6020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6133b78160006142b8565b6001600160a01b031660009081526009602052604090205460ff1c60011490565b6001600160a01b0383166135ab5760405162461bcd60e51b8152600401808060200182810382526025815260200180614e3f6025913960400191505060405180910390fd5b6001600160a01b0382166135f05760405162461bcd60e51b8152600401808060200182810382526023815260200180614ab06023913960400191505060405180910390fd5b6135f98361370c565b8111156136375760405162461bcd60e51b8152600401808060200182810382526026815260200180614c5b6026913960400191505060405180910390fd5b61364e83611cbb836136488761370c565b906136af565b61365f82611cbb83611cb58661370c565b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b600082821115613706576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6001600160a01b03166000908152600960205260409020547f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690565b6133b78160016142b8565b600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6004805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152600093611968939192909183018282801561383b5780601f106138105761010080835404028352916020019161383b565b820191906000526020600020905b81548152906001019060200180831161381e57829003601f168201915b50505050506040518060400160405280600181526020017f320000000000000000000000000000000000000000000000000000000000000081525061387e614327565b61432b565b6001600160a01b038084166000908152600a602090815260408083209386168352929052205461269190849084906138bb90856138c0565b61344e565b60008282018381101561391a576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8111156139805760405162461bcd60e51b815260040180806020018281038252602a815260200180614cd6602a913960400191505060405180910390fd5b61398982613545565b156139c55760405162461bcd60e51b8152600401808060200182810382526025815260200180614c0d6025913960400191505060405180910390fd5b6001600160a01b03909116600090815260096020526040902055565b6123768585848487604051602001808481526020018381526020018260ff1660f81b81526001019350505050604051602081830303815290604052614075565b600154600160a01b900460ff1615613a80576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff16613ace5760405162461bcd60e51b8152600401808060200182810382526021815260200180614d266021913960400191505060405180910390fd5b81613ad881613545565b15613b145760405162461bcd60e51b8152600401808060200182810382526025815260200180614f8a6025913960400191505060405180910390fd5b6000613b1f8461370c565b905060008311613b605760405162461bcd60e51b8152600401808060200182810382526029815260200180614b266029913960400191505060405180910390fd5b82811015613b9f5760405162461bcd60e51b8152600401808060200182810382526026815260200180614d006026913960400191505060405180910390fd5b600b54613bac90846136af565b600b55613bbd84611cbb83866136af565b6040805184815290516001600160a01b038616917fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5919081900360200190a26040805184815290516000916001600160a01b038716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a350505050565b6001600160a01b0386163314613c8a5760405162461bcd60e51b8152600401808060200182810382526025815260200180614df06025913960400191505060405180910390fd5b613c968783868661439f565b604080517fd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de86020808301919091526001600160a01b03808b1683850152891660608301526080820188905260a0820187905260c0820186905260e0808301869052835180840390910181526101009092019092528051910120613d1b9088908361442b565b613d258783614582565b612f07878787613566565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821480613d5e5750428210155b613daf576040805162461bcd60e51b815260206004820152601e60248201527f46696174546f6b656e56323a207065726d697420697320657870697265640000604482015290519081900360640190fd5b6000613e4a613dbc61378e565b6001600160a01b0380891660008181526011602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98184015280840194909452938b166060840152608083018a905260a083019390935260c08083018990528151808403909101815260e0909201905280519101206145dc565b905073"; + hex"60806040526001805460ff60a01b191690556000600b553480156200002357600080fd5b506200002f3362000035565b62000057565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b61508980620000676000396000f3fe608060405234801561001057600080fd5b50600436106103a45760003560e01c80638a6db9c3116101e9578063b7b728991161010f578063dd62ed3e116100ad578063ef55bec61161007c578063ef55bec614611069578063f2fde38b146110c8578063f9f92be4146110ee578063fe575a8714611114576103a4565b8063dd62ed3e14610fa8578063e3ee160e14610fd6578063e5a6b10f14611035578063e94a01021461103d576103a4565b8063cf092995116100e9578063cf09299514610e08578063d505accf14610edf578063d608ea6414610f30578063d916948714610fa0576103a4565b8063b7b7289914610d3d578063bd10243014610df8578063c2eeeebd14610e00576103a4565b8063a0cc6a6811610187578063aa20e1e411610156578063aa20e1e414610c95578063aa271e1a14610cbb578063ad38bf2214610ce1578063b2118a8d14610d07576103a4565b8063a0cc6a6814610c07578063a297ea5e14610c0f578063a457c2d714610c3d578063a9059cbb14610c69576103a4565b80638fa74a0e116101c35780638fa74a0e14610b2457806395d89b4114610b2c5780639fd0506d14610b345780639fd5a6cf14610b3c576103a4565b80638a6db9c314610aca5780638c2a993e14610af05780638da5cb5b14610b1c576103a4565b80633f4ba83a116102ce5780635a049a701161026c5780637ecebe001161023b5780637ecebe00146109bd5780637f2eecc3146109e35780638456cb59146109eb57806388b7ab63146109f3576103a4565b80635a049a70146109225780635c975abb1461096357806370a082311461096b57806374f4f54714610991576103a4565b8063430239b4116102a8578063430239b4146108065780634e44d956146108c857806354fd4d50146108f4578063554bab3c146108fc576103a4565b80633f4ba83a146107b557806340c10f19146107bd57806342966c68146107e9576103a4565b80633092afd51161034657806335d99f351161031557806335d99f35146107555780633644e5151461077957806338a63183146107815780633950935114610789576103a4565b80633092afd51461052a57806330adf81f14610550578063313ce567146105585780633357162b14610576576103a4565b80631a895266116103825780631a8952661461048057806323b872dd146104a85780632ab60045146104de5780632fc81e0914610504576103a4565b806306fdde03146103a9578063095ea7b31461042657806318160ddd14610466575b600080fd5b6103b161113a565b6040805160208082528351818301528351919283929083019185019080838360005b838110156103eb5781810151838201526020016103d3565b50505050905090810190601f1680156104185780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6104526004803603604081101561043c57600080fd5b506001600160a01b0381351690602001356111e6565b604080519115158252519081900360200190f35b61046e61125c565b60408051918252519081900360200190f35b6104a66004803603602081101561049657600080fd5b50356001600160a01b0316611262565b005b610452600480360360608110156104be57600080fd5b506001600160a01b038135811691602081013590911690604001356112eb565b6104a6600480360360208110156104f457600080fd5b50356001600160a01b03166114ec565b6104a66004803603602081101561051a57600080fd5b50356001600160a01b03166115f2565b6104526004803603602081101561054057600080fd5b50356001600160a01b031661163c565b61046e6116e3565b610560611707565b6040805160ff9092168252519081900360200190f35b6104a6600480360361010081101561058d57600080fd5b8101906020810181356401000000008111156105a857600080fd5b8201836020820111156105ba57600080fd5b803590602001918460018302840111640100000000831117156105dc57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929594936020810193503591505064010000000081111561062f57600080fd5b82018360208201111561064157600080fd5b8035906020019184600183028401116401000000008311171561066357600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092959493602081019350359150506401000000008111156106b657600080fd5b8201836020820111156106c857600080fd5b803590602001918460018302840111640100000000831117156106ea57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050813560ff1692505060208101356001600160a01b0390811691604081013582169160608201358116916080013516611710565b61075d61194f565b604080516001600160a01b039092168252519081900360200190f35b61046e61195e565b61075d61196d565b6104526004803603604081101561079f57600080fd5b506001600160a01b03813516906020013561197c565b6104a66119e9565b610452600480360360408110156107d357600080fd5b506001600160a01b038135169060200135611a85565b6104a6600480360360208110156107ff57600080fd5b5035611d68565b6104a66004803603604081101561081c57600080fd5b81019060208101813564010000000081111561083757600080fd5b82018360208201111561084957600080fd5b8035906020019184602083028401116401000000008311171561086b57600080fd5b91939092909160208101903564010000000081111561088957600080fd5b82018360208201111561089b57600080fd5b803590602001918460018302840111640100000000831117156108bd57600080fd5b509092509050611f77565b610452600480360360408110156108de57600080fd5b506001600160a01b0381351690602001356120b1565b6103b16121c7565b6104a66004803603602081101561091257600080fd5b50356001600160a01b03166121fe565b6104a6600480360360a081101561093857600080fd5b506001600160a01b038135169060208101359060ff604082013516906060810135906080013561230a565b61045261237d565b61046e6004803603602081101561098157600080fd5b50356001600160a01b031661238d565b6104a6600480360360408110156109a757600080fd5b506001600160a01b03813516906020013561239e565b61046e600480360360208110156109d357600080fd5b50356001600160a01b0316612419565b61046e612434565b6104a6612458565b6104a6600480360360e0811015610a0957600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359160808201359160a08101359181019060e0810160c0820135640100000000811115610a5557600080fd5b820183602082011115610a6757600080fd5b80359060200191846001830284011164010000000083111715610a8957600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506124fa945050505050565b61046e60048036036020811015610ae057600080fd5b50356001600160a01b03166125ff565b6104a660048036036040811015610b0657600080fd5b506001600160a01b03813516906020013561261a565b61075d612696565b61075d6126a5565b6103b16126ca565b61075d612743565b6104a6600480360360a0811015610b5257600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359181019060a081016080820135640100000000811115610b9257600080fd5b820183602082011115610ba457600080fd5b80359060200191846001830284011164010000000083111715610bc657600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612752945050505050565b61046e6127be565b6104a660048036036040811015610c2557600080fd5b506001600160a01b03813581169160200135166127e2565b61045260048036036040811015610c5357600080fd5b506001600160a01b038135169060200135612958565b61045260048036036040811015610c7f57600080fd5b506001600160a01b0381351690602001356129c5565b6104a660048036036020811015610cab57600080fd5b50356001600160a01b0316612ac9565b61045260048036036020811015610cd157600080fd5b50356001600160a01b0316612bd5565b6104a660048036036020811015610cf757600080fd5b50356001600160a01b0316612bf3565b6104a660048036036060811015610d1d57600080fd5b506001600160a01b03813581169160208101359091169060400135612cff565b6104a660048036036060811015610d5357600080fd5b6001600160a01b0382351691602081013591810190606081016040820135640100000000811115610d8357600080fd5b820183602082011115610d9557600080fd5b80359060200191846001830284011164010000000083111715610db757600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612d5c945050505050565b61075d612dc6565b61075d612dd5565b6104a6600480360360e0811015610e1e57600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359160808201359160a08101359181019060e0810160c0820135640100000000811115610e6a57600080fd5b820183602082011115610e7c57600080fd5b80359060200191846001830284011164010000000083111715610e9e57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612dfa945050505050565b6104a6600480360360e0811015610ef557600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c00135612ef4565b6104a660048036036020811015610f4657600080fd5b810190602081018135640100000000811115610f6157600080fd5b820183602082011115610f7357600080fd5b80359060200191846001830284011164010000000083111715610f9557600080fd5b509092509050612f6b565b61046e613025565b61046e60048036036040811015610fbe57600080fd5b506001600160a01b0381358116916020013516613049565b6104a66004803603610120811015610fed57600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060808101359060a08101359060ff60c0820135169060e0810135906101000135613074565b6103b161317d565b6104526004803603604081101561105357600080fd5b506001600160a01b0381351690602001356131f6565b6104a6600480360361012081101561108057600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060808101359060a08101359060ff60c0820135169060e0810135906101000135613221565b6104a6600480360360208110156110de57600080fd5b50356001600160a01b031661331d565b6104a66004803603602081101561110457600080fd5b50356001600160a01b0316613415565b6104526004803603602081101561112a57600080fd5b50356001600160a01b031661349e565b6004805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156111de5780601f106111b3576101008083540402835291602001916111de565b820191906000526020600020905b8154815290600101906020018083116111c157829003601f168201915b505050505081565b600154600090600160a01b900460ff1615611248576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6112533384846134a9565b50600192915050565b600b5490565b6002546001600160a01b031633146112ab5760405162461bcd60e51b815260040180806020018281038252602c815260200180614d05602c913960400191505060405180910390fd5b6112b481613595565b6040516001600160a01b038216907f117e3210bb9aa7d9baff172026820255c6f6c30ba8999d1c2fd88e2848137c4e90600090a250565b600154600090600160a01b900460ff161561134d576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b33611357816135a0565b156113935760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b8461139d816135a0565b156113d95760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b846113e3816135a0565b1561141f5760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b6001600160a01b0387166000908152600a602090815260408083203384529091529020548511156114815760405162461bcd60e51b8152600401808060200182810382526028815260200180614df56028913960400191505060405180910390fd5b61148c8787876135c1565b6001600160a01b0387166000908152600a602090815260408083203384529091529020546114ba908661370a565b6001600160a01b0388166000908152600a60209081526040808320338452909152902055600193505050509392505050565b6000546001600160a01b0316331461154b576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166115905760405162461bcd60e51b815260040180806020018281038252602a815260200180614c3e602a913960400191505060405180910390fd5b600e80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040517fe475e580d85111348e40d8ca33cfdd74c30fe1655c2d8537a13abc10065ffa5a90600090a250565b60125460ff1660011461160457600080fd5b600061160f30613767565b90508015611622576116223083836135c1565b61162b306137a4565b50506012805460ff19166002179055565b6008546000906001600160a01b031633146116885760405162461bcd60e51b8152600401808060200182810382526029815260200180614cdc6029913960400191505060405180910390fd5b6001600160a01b0382166000818152600c60209081526040808320805460ff19169055600d909152808220829055517fe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb666929190a2506001919050565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60065460ff1681565b600854600160a01b900460ff16156117595760405162461bcd60e51b815260040180806020018281038252602a815260200180614e70602a913960400191505060405180910390fd5b6001600160a01b03841661179e5760405162461bcd60e51b815260040180806020018281038252602f815260200180614da2602f913960400191505060405180910390fd5b6001600160a01b0383166117e35760405162461bcd60e51b8152600401808060200182810382526029815260200180614c156029913960400191505060405180910390fd5b6001600160a01b0382166118285760405162461bcd60e51b815260040180806020018281038252602e815260200180614e1d602e913960400191505060405180910390fd5b6001600160a01b03811661186d5760405162461bcd60e51b8152600401808060200182810382526028815260200180614f5d6028913960400191505060405180910390fd5b87516118809060049060208b01906149cc565b5086516118949060059060208a01906149cc565b5085516118a89060079060208901906149cc565b506006805460ff191660ff8716179055600880547fffffffffffffffffffffffff00000000000000000000000000000000000000009081166001600160a01b038781169190911790925560018054821686841617905560028054909116918416919091179055611917816137af565b5050600880547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16600160a01b179055505050505050565b6008546001600160a01b031681565b60006119686137e9565b905090565b600e546001600160a01b031690565b600154600090600160a01b900460ff16156119de576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6112533384846138de565b6001546001600160a01b03163314611a325760405162461bcd60e51b8152600401808060200182810382526022815260200180614f116022913960400191505060405180910390fd5b600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690556040517f7805862f689e2f13df9f062ff482ad3ad112aca9e0847911ed832e158c525b3390600090a1565b600154600090600160a01b900460ff1615611ae7576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff16611b355760405162461bcd60e51b8152600401808060200182810382526021815260200180614d816021913960400191505060405180910390fd5b33611b3f816135a0565b15611b7b5760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b83611b85816135a0565b15611bc15760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b6001600160a01b038516611c065760405162461bcd60e51b8152600401808060200182810382526023815260200180614baa6023913960400191505060405180910390fd5b60008411611c455760405162461bcd60e51b8152600401808060200182810382526029815260200180614c8d6029913960400191505060405180910390fd5b336000908152600d602052604090205480851115611c945760405162461bcd60e51b815260040180806020018281038252602e815260200180614ee3602e913960400191505060405180910390fd5b600b54611ca1908661391b565b600b55611cc086611cbb87611cb583613767565b9061391b565b61397c565b611cca818661370a565b336000818152600d602090815260409182902093909355805188815290516001600160a01b038a16937fab8530f87dc9b59234c4623bf917212bb2536d647574c8e7e5da92c2ede0c9f8928290030190a36040805186815290516001600160a01b038816916000917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a350600195945050505050565b600154600160a01b900460ff1615611dc7576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff16611e155760405162461bcd60e51b8152600401808060200182810382526021815260200180614d816021913960400191505060405180910390fd5b33611e1f816135a0565b15611e5b5760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b6000611e6633613767565b905060008311611ea75760405162461bcd60e51b8152600401808060200182810382526029815260200180614b816029913960400191505060405180910390fd5b82811015611ee65760405162461bcd60e51b8152600401808060200182810382526026815260200180614d5b6026913960400191505060405180910390fd5b600b54611ef3908461370a565b600b55611f0433611cbb838661370a565b60408051848152905133917fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5919081900360200190a260408051848152905160009133917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a3505050565b60125460ff16600214611f8957600080fd5b611f9560058383614a4a565b5060005b838110156120785760036000868684818110611fb157fe5b602090810292909201356001600160a01b03168352508101919091526040016000205460ff166120125760405162461bcd60e51b815260040180806020018281038252603d815260200180614ace603d913960400191505060405180910390fd5b61203685858381811061202157fe5b905060200201356001600160a01b03166137a4565b6003600086868481811061204657fe5b602090810292909201356001600160a01b0316835250810191909152604001600020805460ff19169055600101611f99565b50612082306137a4565b5050306000908152600360208190526040909120805460ff199081169091556012805490911690911790555050565b600154600090600160a01b900460ff1615612113576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6008546001600160a01b0316331461215c5760405162461bcd60e51b8152600401808060200182810382526029815260200180614cdc6029913960400191505060405180910390fd5b6001600160a01b0383166000818152600c60209081526040808320805460ff19166001179055600d825291829020859055815185815291517f46980fca912ef9bcdbd36877427b6b90e860769f604e89c0e67720cece530d209281900390910190a250600192915050565b60408051808201909152600181527f3200000000000000000000000000000000000000000000000000000000000000602082015290565b6000546001600160a01b0316331461225d576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166122a25760405162461bcd60e51b8152600401808060200182810382526028815260200180614b2e6028913960400191505060405180910390fd5b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691909117918290556040519116907fb80482a293ca2e013eda8683c9bd7fc8347cfdaeea5ede58cba46df502c2a60490600090a250565b600154600160a01b900460ff1615612369576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6123768585858585613a3c565b5050505050565b600154600160a01b900460ff1681565b600061239882613767565b92915050565b6123a66126a5565b6001600160a01b0316336001600160a01b03161461240b576040805162461bcd60e51b815260206004820152600c60248201527f4f4e4c595f474154455741590000000000000000000000000000000000000000604482015290519081900360640190fd5b6124158282613a7c565b5050565b6001600160a01b031660009081526011602052604090205490565b7fd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de881565b6001546001600160a01b031633146124a15760405162461bcd60e51b8152600401808060200182810382526022815260200180614f116022913960400191505060405180910390fd5b600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16600160a01b1790556040517f6985a02210a168e66602d3235cb6db0e70f92b3ba4d376a33c0f3d9434bff62590600090a1565b600154600160a01b900460ff1615612559576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b86612563816135a0565b1561259f5760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b866125a9816135a0565b156125e55760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b6125f489898989898989613c9e565b505050505050505050565b6001600160a01b03166000908152600d602052604090205490565b6126226126a5565b6001600160a01b0316336001600160a01b031614612687576040805162461bcd60e51b815260206004820152600c60248201527f4f4e4c595f474154455741590000000000000000000000000000000000000000604482015290519081900360640190fd5b6126918282611a85565b505050565b6000546001600160a01b031690565b7fdbf6298cab77bb44ebfd5abb25ed2538c2a55f7404c47e83e6531361fba28c245490565b6005805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156111de5780601f106111b3576101008083540402835291602001916111de565b6001546001600160a01b031681565b600154600160a01b900460ff16156127b1576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6123768585858585613d8b565b7f7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a226781565b60125460ff166003146127f457600080fd5b6001600160a01b03821661284f576040805162461bcd60e51b815260206004820152600f60248201527f494e56414c49445f474154455741590000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b0381166128aa576040805162461bcd60e51b815260206004820152601360248201527f494e56414c49445f434f554e5445525041525400000000000000000000000000604482015290519081900360640190fd5b60006128b46126a5565b6001600160a01b03161461290f576040805162461bcd60e51b815260206004820152600c60248201527f414c52454144595f494e49540000000000000000000000000000000000000000604482015290519081900360640190fd5b7fdbf6298cab77bb44ebfd5abb25ed2538c2a55f7404c47e83e6531361fba28c24919091557f54352c0d7cc5793352a36344bfdcdcf68ba6258544ce1aed71f60a74d882c19155565b600154600090600160a01b900460ff16156129ba576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b611253338484614001565b600154600090600160a01b900460ff1615612a27576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b33612a31816135a0565b15612a6d5760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b83612a77816135a0565b15612ab35760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b612abe3386866135c1565b506001949350505050565b6000546001600160a01b03163314612b28576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b038116612b6d5760405162461bcd60e51b815260040180806020018281038252602f815260200180614da2602f913960400191505060405180910390fd5b600880547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691909117918290556040519116907fdb66dfa9c6b8f5226fe9aac7e51897ae8ee94ac31dc70bb6c9900b2574b707e690600090a250565b6001600160a01b03166000908152600c602052604090205460ff1690565b6000546001600160a01b03163314612c52576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b038116612c975760405162461bcd60e51b8152600401808060200182810382526032815260200180614fb36032913960400191505060405180910390fd5b600280547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691909117918290556040519116907fc67398012c111ce95ecb7429b933096c977380ee6c421175a71a4a4c6c88c06e90600090a250565b600e546001600160a01b03163314612d485760405162461bcd60e51b8152600401808060200182810382526024815260200180614dd16024913960400191505060405180910390fd5b6126916001600160a01b0384168383614050565b600154600160a01b900460ff1615612dbb576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6126918383836140d0565b6002546001600160a01b031681565b7f54352c0d7cc5793352a36344bfdcdcf68ba6258544ce1aed71f60a74d882c1915490565b600154600160a01b900460ff1615612e59576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b86612e63816135a0565b15612e9f5760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b86612ea9816135a0565b15612ee55760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b6125f4898989898989896141a2565b600154600160a01b900460ff1615612f53576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b612f6287878787878787614233565b50505050505050565b600854600160a01b900460ff168015612f87575060125460ff16155b612f9057600080fd5b612f9c60048383614a4a565b5061301182828080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600181527f3200000000000000000000000000000000000000000000000000000000000000602082015291506142759050565b600f5550506012805460ff19166001179055565b7f158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a159742981565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205490565b600154600160a01b900460ff16156130d3576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b886130dd816135a0565b156131195760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b88613123816135a0565b1561315f5760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b6131708b8b8b8b8b8b8b8b8b61428b565b5050505050505050505050565b6007805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156111de5780601f106111b3576101008083540402835291602001916111de565b6001600160a01b03919091166000908152601060209081526040808320938352929052205460ff1690565b600154600160a01b900460ff1615613280576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b8861328a816135a0565b156132c65760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b886132d0816135a0565b1561330c5760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b6131708b8b8b8b8b8b8b8b8b6142cf565b6000546001600160a01b0316331461337c576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166133c15760405162461bcd60e51b8152600401808060200182810382526026815260200180614bcd6026913960400191505060405180910390fd5b600054604080516001600160a01b039283168152918316602083015280517f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09281900390910190a1613412816137af565b50565b6002546001600160a01b0316331461345e5760405162461bcd60e51b815260040180806020018281038252602c815260200180614d05602c913960400191505060405180910390fd5b613467816137a4565b6040516001600160a01b038216907fffa4e6181777692565cf28528fc88fd1516ea86b56da075235fa575af6a4b85590600090a250565b6000612398826135a0565b6001600160a01b0383166134ee5760405162461bcd60e51b8152600401808060200182810382526024815260200180614ebf6024913960400191505060405180910390fd5b6001600160a01b0382166135335760405162461bcd60e51b8152600401808060200182810382526022815260200180614bf36022913960400191505060405180910390fd5b6001600160a01b038084166000818152600a6020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b613412816000614313565b6001600160a01b031660009081526009602052604090205460ff1c60011490565b6001600160a01b0383166136065760405162461bcd60e51b8152600401808060200182810382526025815260200180614e9a6025913960400191505060405180910390fd5b6001600160a01b03821661364b5760405162461bcd60e51b8152600401808060200182810382526023815260200180614b0b6023913960400191505060405180910390fd5b61365483613767565b8111156136925760405162461bcd60e51b8152600401808060200182810382526026815260200180614cb66026913960400191505060405180910390fd5b6136a983611cbb836136a387613767565b9061370a565b6136ba82611cbb83611cb586613767565b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b600082821115613761576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6001600160a01b03166000908152600960205260409020547f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690565b613412816001614313565b600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6004805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815260009361196893919290918301828280156138965780601f1061386b57610100808354040283529160200191613896565b820191906000526020600020905b81548152906001019060200180831161387957829003601f168201915b50505050506040518060400160405280600181526020017f32000000000000000000000000000000000000000000000000000000000000008152506138d9614382565b614386565b6001600160a01b038084166000908152600a60209081526040808320938616835292905220546126919084908490613916908561391b565b6134a9565b600082820183811015613975576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8111156139db5760405162461bcd60e51b815260040180806020018281038252602a815260200180614d31602a913960400191505060405180910390fd5b6139e4826135a0565b15613a205760405162461bcd60e51b8152600401808060200182810382526025815260200180614c686025913960400191505060405180910390fd5b6001600160a01b03909116600090815260096020526040902055565b6123768585848487604051602001808481526020018381526020018260ff1660f81b815260010193505050506040516020818303038152906040526140d0565b600154600160a01b900460ff1615613adb576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff16613b295760405162461bcd60e51b8152600401808060200182810382526021815260200180614d816021913960400191505060405180910390fd5b81613b33816135a0565b15613b6f5760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b6000613b7a84613767565b905060008311613bbb5760405162461bcd60e51b8152600401808060200182810382526029815260200180614b816029913960400191505060405180910390fd5b82811015613bfa5760405162461bcd60e51b8152600401808060200182810382526026815260200180614d5b6026913960400191505060405180910390fd5b600b54613c07908461370a565b600b55613c1884611cbb838661370a565b6040805184815290516001600160a01b038616917fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5919081900360200190a26040805184815290516000916001600160a01b038716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a350505050565b6001600160a01b0386163314613ce55760405162461bcd60e51b8152600401808060200182810382526025815260200180614e4b6025913960400191505060405180910390fd5b613cf1878386866143fa565b604080517fd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de86020808301919091526001600160a01b03808b1683850152891660608301526080820188905260a0820187905260c0820186905260e0808301869052835180840390910181526101009092019092528051910120613d7690889083614486565b613d8087836145dd565b612f628787876135c1565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821480613db95750428210155b613e0a576040805162461bcd60e51b815260206004820152601e60248201527f46696174546f6b656e56323a207065726d697420697320657870697265640000604482015290519081900360640190fd5b6000613ea5613e176137e9565b6001600160a01b0380891660008181526011602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98184015280840194909452938b166060840152608083018a905260a083019390935260c08083018990528151808403909101815260e090920190528051910120614637565b905073"; bytes memory b2 = - hex"636ccea6528783856040518463ffffffff1660e01b815260040180846001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015613eca578181015183820152602001613eb2565b50505050905090810190601f168015613ef75780820380516001836020036101000a031916815260200191505b5094505050505060206040518083038186803b158015613f1657600080fd5b505af4158015613f2a573d6000803e3d6000fd5b505050506040513d6020811015613f4057600080fd5b5051613f93576040805162461bcd60e51b815260206004820152601a60248201527f454950323631323a20696e76616c6964207369676e6174757265000000000000604482015290519081900360640190fd5b613f9e86868661344e565b505050505050565b61269183836138bb84604051806060016040528060258152602001614fd4602591396001600160a01b03808a166000908152600a60209081526040808320938c16835292905220549190614616565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790526126919084906146ad565b61407f838361475e565b6140ec837f158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a159742960001b858560405160200180848152602001836001600160a01b031681526020018281526020019350505050604051602081830303815290604052805190602001208361442b565b6001600160a01b0383166000818152601060209081526040808320868452909152808220805460ff19166001179055518492917f1cdd46ff242716cdaa72d159d339a485b3438398348d68f09d7c8c0a59353d8191a3505050565b6141538783868661439f565b604080517f7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a22676020808301919091526001600160a01b03808b1683850152891660608301526080820188905260a0820187905260c0820186905260e0808301869052835180840390910181526101009092019092528051910120613d1b9088908361442b565b612f0787878787868689604051602001808481526020018381526020018260ff1660f81b81526001019350505050604051602081830303815290604052613d30565b60004661422884848361432b565b949350505050565b6125f489898989898988888b604051602001808481526020018381526020018260ff1660f81b81526001019350505050604051602081830303815290604052614147565b6125f489898989898988888b604051602001808481526020018381526020018260ff1660f81b81526001019350505050604051602081830303815290604052613c43565b806142cb576142c68261370c565b614307565b6001600160a01b0382166000908152600960205260409020547f8000000000000000000000000000000000000000000000000000000000000000175b6001600160a01b0390921660009081526009602052604090209190915550565b4690565b8251602093840120825192840192909220604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8187015280820194909452606084019190915260808301919091523060a0808401919091528151808403909101815260c09092019052805191012090565b8142116143dd5760405162461bcd60e51b815260040180806020018281038252602b815260200180614afb602b913960400191505060405180910390fd5b80421061441b5760405162461bcd60e51b8152600401808060200182810382526025815260200180614faf6025913960400191505060405180910390fd5b614425848461475e565b50505050565b73"; + hex"636ccea6528783856040518463ffffffff1660e01b815260040180846001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015613f25578181015183820152602001613f0d565b50505050905090810190601f168015613f525780820380516001836020036101000a031916815260200191505b5094505050505060206040518083038186803b158015613f7157600080fd5b505af4158015613f85573d6000803e3d6000fd5b505050506040513d6020811015613f9b57600080fd5b5051613fee576040805162461bcd60e51b815260206004820152601a60248201527f454950323631323a20696e76616c6964207369676e6174757265000000000000604482015290519081900360640190fd5b613ff98686866134a9565b505050505050565b61269183836139168460405180606001604052806025815260200161502f602591396001600160a01b03808a166000908152600a60209081526040808320938c16835292905220549190614671565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052612691908490614708565b6140da83836147b9565b614147837f158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a159742960001b858560405160200180848152602001836001600160a01b0316815260200182815260200193505050506040516020818303038152906040528051906020012083614486565b6001600160a01b0383166000818152601060209081526040808320868452909152808220805460ff19166001179055518492917f1cdd46ff242716cdaa72d159d339a485b3438398348d68f09d7c8c0a59353d8191a3505050565b6141ae878386866143fa565b604080517f7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a22676020808301919091526001600160a01b03808b1683850152891660608301526080820188905260a0820187905260c0820186905260e0808301869052835180840390910181526101009092019092528051910120613d7690889083614486565b612f6287878787868689604051602001808481526020018381526020018260ff1660f81b81526001019350505050604051602081830303815290604052613d8b565b600046614283848483614386565b949350505050565b6125f489898989898988888b604051602001808481526020018381526020018260ff1660f81b815260010193505050506040516020818303038152906040526141a2565b6125f489898989898988888b604051602001808481526020018381526020018260ff1660f81b81526001019350505050604051602081830303815290604052613c9e565b806143265761432182613767565b614362565b6001600160a01b0382166000908152600960205260409020547f8000000000000000000000000000000000000000000000000000000000000000175b6001600160a01b0390921660009081526009602052604090209190915550565b4690565b8251602093840120825192840192909220604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8187015280820194909452606084019190915260808301919091523060a0808401919091528151808403909101815260c09092019052805191012090565b8142116144385760405162461bcd60e51b815260040180806020018281038252602b815260200180614b56602b913960400191505060405180910390fd5b8042106144765760405162461bcd60e51b815260040180806020018281038252602581526020018061500a6025913960400191505060405180910390fd5b61448084846147b9565b50505050565b73"; bytes memory b3 = - hex"636ccea6528461445761445161378e565b866145dc565b846040518463ffffffff1660e01b815260040180846001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b838110156144b95781810151838201526020016144a1565b50505050905090810190601f1680156144e65780820380516001836020036101000a031916815260200191505b5094505050505060206040518083038186803b15801561450557600080fd5b505af4158015614519573d6000803e3d6000fd5b505050506040513d602081101561452f57600080fd5b5051612691576040805162461bcd60e51b815260206004820152601e60248201527f46696174546f6b656e56323a20696e76616c6964207369676e61747572650000604482015290519081900360640190fd5b6001600160a01b0382166000818152601060209081526040808320858452909152808220805460ff19166001179055518392917f98de503528ee59b575ef0c0a2576a82497bfc029a5685b209e9ec333479b10a591a35050565b6040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b600081848411156146a55760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561466a578181015183820152602001614652565b50505050905090810190601f1680156146975780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6060614702826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166147c19092919063ffffffff16565b8051909150156126915780806020019051602081101561472157600080fd5b50516126915760405162461bcd60e51b815260040180806020018281038252602a815260200180614ed8602a913960400191505060405180910390fd5b6001600160a01b038216600090815260106020908152604080832084845290915290205460ff16156124155760405162461bcd60e51b815260040180806020018281038252602e815260200180614f2a602e913960400191505060405180910390fd5b60606142288484600085856147d585614905565b614826576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b6020831061488357805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101614846565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d80600081146148e5576040519150601f19603f3d011682016040523d82523d6000602084013e6148ea565b606091505b50915091506148fa82828661490b565b979650505050505050565b3b151590565b6060831561491a57508161391a565b82511561492a5782518084602001fd5b60405162461bcd60e51b815260206004820181815284516024840152845185939192839260440191908501908083836000831561466a578181015183820152602001614652565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106149b257805160ff19168380011785556149df565b828001600101855582156149df579182015b828111156149df5782518255916020019190600101906149c4565b506149eb929150614a5d565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10614a305782800160ff198235161785556149df565b828001600101855582156149df579182015b828111156149df578235825591602001919060010190614a42565b5b808211156149eb5760008155600101614a5e56fe46696174546f6b656e56325f323a20426c61636b6c697374696e672070726576696f75736c7920756e626c61636b6c6973746564206163636f756e742145524332303a207472616e7366657220746f20746865207a65726f20616464726573735061757361626c653a206e65772070617573657220697320746865207a65726f206164647265737346696174546f6b656e56323a20617574686f72697a6174696f6e206973206e6f74207965742076616c696446696174546f6b656e3a206275726e20616d6f756e74206e6f742067726561746572207468616e203046696174546f6b656e3a206d696e7420746f20746865207a65726f20616464726573734f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737346696174546f6b656e3a206e65772070617573657220697320746865207a65726f2061646472657373526573637561626c653a206e6577207265736375657220697320746865207a65726f206164647265737346696174546f6b656e56325f323a204163636f756e7420697320626c61636b6c697374656446696174546f6b656e3a206d696e7420616d6f756e74206e6f742067726561746572207468616e203045524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636546696174546f6b656e3a2063616c6c6572206973206e6f7420746865206d61737465724d696e746572426c61636b6c69737461626c653a2063616c6c6572206973206e6f742074686520626c61636b6c697374657246696174546f6b656e56325f323a2042616c616e636520657863656564732028325e323535202d20312946696174546f6b656e3a206275726e20616d6f756e7420657863656564732062616c616e636546696174546f6b656e3a2063616c6c6572206973206e6f742061206d696e74657246696174546f6b656e3a206e6577206d61737465724d696e74657220697320746865207a65726f2061646472657373526573637561626c653a2063616c6c6572206973206e6f7420746865207265736375657245524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636546696174546f6b656e3a206e657720626c61636b6c697374657220697320746865207a65726f206164647265737346696174546f6b656e56323a2063616c6c6572206d7573742062652074686520706179656546696174546f6b656e3a20636f6e747261637420697320616c726561647920696e697469616c697a656445524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737346696174546f6b656e3a206d696e7420616d6f756e742065786365656473206d696e746572416c6c6f77616e63655061757361626c653a2063616c6c6572206973206e6f7420746865207061757365725361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656446696174546f6b656e3a206e6577206f776e657220697320746865207a65726f206164647265737346696174546f6b656e56323a20617574686f72697a6174696f6e2069732075736564206f722063616e63656c6564426c61636b6c69737461626c653a206e657720626c61636b6c697374657220697320746865207a65726f2061646472657373426c61636b6c69737461626c653a206163636f756e7420697320626c61636b6c697374656446696174546f6b656e56323a20617574686f72697a6174696f6e206973206578706972656445524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220615e051a229e77d8da0781c2c1926a3017e6914f059e90a4aa05450168f36bdc64736f6c634300060c0033"; + hex"636ccea652846144b26144ac6137e9565b86614637565b846040518463ffffffff1660e01b815260040180846001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b838110156145145781810151838201526020016144fc565b50505050905090810190601f1680156145415780820380516001836020036101000a031916815260200191505b5094505050505060206040518083038186803b15801561456057600080fd5b505af4158015614574573d6000803e3d6000fd5b505050506040513d602081101561458a57600080fd5b5051612691576040805162461bcd60e51b815260206004820152601e60248201527f46696174546f6b656e56323a20696e76616c6964207369676e61747572650000604482015290519081900360640190fd5b6001600160a01b0382166000818152601060209081526040808320858452909152808220805460ff19166001179055518392917f98de503528ee59b575ef0c0a2576a82497bfc029a5685b209e9ec333479b10a591a35050565b6040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b600081848411156147005760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156146c55781810151838201526020016146ad565b50505050905090810190601f1680156146f25780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b606061475d826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661481c9092919063ffffffff16565b8051909150156126915780806020019051602081101561477c57600080fd5b50516126915760405162461bcd60e51b815260040180806020018281038252602a815260200180614f33602a913960400191505060405180910390fd5b6001600160a01b038216600090815260106020908152604080832084845290915290205460ff16156124155760405162461bcd60e51b815260040180806020018281038252602e815260200180614f85602e913960400191505060405180910390fd5b606061428384846000858561483085614960565b614881576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b602083106148de57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016148a1565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114614940576040519150601f19603f3d011682016040523d82523d6000602084013e614945565b606091505b5091509150614955828286614966565b979650505050505050565b3b151590565b60608315614975575081613975565b8251156149855782518084602001fd5b60405162461bcd60e51b81526020600482018181528451602484015284518593919283926044019190850190808383600083156146c55781810151838201526020016146ad565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10614a0d57805160ff1916838001178555614a3a565b82800160010185558215614a3a579182015b82811115614a3a578251825591602001919060010190614a1f565b50614a46929150614ab8565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10614a8b5782800160ff19823516178555614a3a565b82800160010185558215614a3a579182015b82811115614a3a578235825591602001919060010190614a9d565b5b80821115614a465760008155600101614ab956fe46696174546f6b656e56325f323a20426c61636b6c697374696e672070726576696f75736c7920756e626c61636b6c6973746564206163636f756e742145524332303a207472616e7366657220746f20746865207a65726f20616464726573735061757361626c653a206e65772070617573657220697320746865207a65726f206164647265737346696174546f6b656e56323a20617574686f72697a6174696f6e206973206e6f74207965742076616c696446696174546f6b656e3a206275726e20616d6f756e74206e6f742067726561746572207468616e203046696174546f6b656e3a206d696e7420746f20746865207a65726f20616464726573734f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737346696174546f6b656e3a206e65772070617573657220697320746865207a65726f2061646472657373526573637561626c653a206e6577207265736375657220697320746865207a65726f206164647265737346696174546f6b656e56325f323a204163636f756e7420697320626c61636b6c697374656446696174546f6b656e3a206d696e7420616d6f756e74206e6f742067726561746572207468616e203045524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636546696174546f6b656e3a2063616c6c6572206973206e6f7420746865206d61737465724d696e746572426c61636b6c69737461626c653a2063616c6c6572206973206e6f742074686520626c61636b6c697374657246696174546f6b656e56325f323a2042616c616e636520657863656564732028325e323535202d20312946696174546f6b656e3a206275726e20616d6f756e7420657863656564732062616c616e636546696174546f6b656e3a2063616c6c6572206973206e6f742061206d696e74657246696174546f6b656e3a206e6577206d61737465724d696e74657220697320746865207a65726f2061646472657373526573637561626c653a2063616c6c6572206973206e6f7420746865207265736375657245524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636546696174546f6b656e3a206e657720626c61636b6c697374657220697320746865207a65726f206164647265737346696174546f6b656e56323a2063616c6c6572206d7573742062652074686520706179656546696174546f6b656e3a20636f6e747261637420697320616c726561647920696e697469616c697a656445524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737346696174546f6b656e3a206d696e7420616d6f756e742065786365656473206d696e746572416c6c6f77616e63655061757361626c653a2063616c6c6572206973206e6f7420746865207061757365725361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656446696174546f6b656e3a206e6577206f776e657220697320746865207a65726f206164647265737346696174546f6b656e56323a20617574686f72697a6174696f6e2069732075736564206f722063616e63656c6564426c61636b6c69737461626c653a206e657720626c61636b6c697374657220697320746865207a65726f2061646472657373426c61636b6c69737461626c653a206163636f756e7420697320626c61636b6c697374656446696174546f6b656e56323a20617574686f72697a6174696f6e206973206578706972656445524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122069f43cc6c29d58063264d46f6f667d8af0c0a5209b8e811c80c4675b7ac594b364736f6c634300060c0033"; bytes memory libAddress = abi.encodePacked(sigCheckerAddress); From 9dab9f462192990170ad64136e9d503dddbdf39e Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Wed, 19 Jun 2024 14:40:09 +0200 Subject: [PATCH 16/20] Use FiatTokenV2_2 --- .../tokenbridge/libraries/IFiatToken.sol | 15 +++++ test-foundry/L2USDCGateway.t.sol | 63 ++++++++++--------- test-foundry/util/TestUtil.sol | 6 +- 3 files changed, 51 insertions(+), 33 deletions(-) diff --git a/contracts/tokenbridge/libraries/IFiatToken.sol b/contracts/tokenbridge/libraries/IFiatToken.sol index 95214835d1..7acd9fcafe 100644 --- a/contracts/tokenbridge/libraries/IFiatToken.sol +++ b/contracts/tokenbridge/libraries/IFiatToken.sol @@ -10,6 +10,21 @@ pragma solidity >0.6.0 <0.9.0; * This interface is used in the L1USDCGateway, L1OrbitUSDCGateway and L2USDCGateway contracts. */ interface IFiatToken { + function initialize( + string memory tokenName, + string memory tokenSymbol, + string memory tokenCurrency, + uint8 tokenDecimals, + address newMasterMinter, + address newPauser, + address newBlacklister, + address newOwner + ) external; + function initializeV2(string calldata newName) external; + function initializeV2_1(address lostAndFound) external; + function initializeV2_2(address[] calldata accountsToBlacklist, string calldata newSymbol) + external; + function configureMinter(address minter, uint256 minterAllowedAmount) external; function burn(uint256 _amount) external; function mint(address _to, uint256 _amount) external; } diff --git a/test-foundry/L2USDCGateway.t.sol b/test-foundry/L2USDCGateway.t.sol index 4436a6ee6f..2b1cd768d7 100644 --- a/test-foundry/L2USDCGateway.t.sol +++ b/test-foundry/L2USDCGateway.t.sol @@ -9,6 +9,8 @@ import {L1USDCGateway} from "contracts/tokenbridge/ethereum/gateway/L1USDCGatewa import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import {AddressAliasHelper} from "contracts/tokenbridge/libraries/AddressAliasHelper.sol"; import {L2GatewayToken} from "contracts/tokenbridge/libraries/L2GatewayToken.sol"; +import {IFiatToken} from "contracts/tokenbridge/libraries/IFiatToken.sol"; +import {TestUtil} from "./util/TestUtil.sol"; contract L2USDCGatewayTest is L2ArbitrumGatewayTest { L2USDCGateway public l2USDCGateway; @@ -16,14 +18,33 @@ contract L2USDCGatewayTest is L2ArbitrumGatewayTest { address public l2USDC; address public user = makeAddr("usdc_user"); address public owner = makeAddr("l2gw-owner"); + address masterMinter = makeAddr("masterMinter"); function setUp() public virtual { l2USDCGateway = new L2USDCGateway(); l2Gateway = L2ArbitrumGateway(address(l2USDCGateway)); - l2USDC = address(new MockFiatToken(address(l2USDCGateway))); - l2USDCGateway.initialize(l1Counterpart, router, l1USDC, l2USDC, owner); + address bridgedUsdcLogic = TestUtil.deployBridgedUsdcToken(); + l2USDC = TestUtil.deployProxy(bridgedUsdcLogic); + IFiatToken(l2USDC).initialize( + "USDC token", + "USDC.e", + "USD", + uint8(6), + masterMinter, + makeAddr("newPauser"), + makeAddr("newBlacklister"), + owner + ); + IFiatToken(l2USDC).initializeV2("USDC"); + IFiatToken(l2USDC).initializeV2_1(makeAddr("lostAndFound")); + IFiatToken(l2USDC).initializeV2_2(new address[](0), "USDC.e"); + + vm.prank(masterMinter); + IFiatToken(l2USDC).configureMinter(address(l2USDCGateway), type(uint256).max); + vm.prank(owner); + l2USDCGateway.initialize(l1Counterpart, router, l1USDC, l2USDC, owner); vm.etch(0x0000000000000000000000000000000000000064, address(arbSysMock).code); } @@ -127,7 +148,8 @@ contract L2USDCGatewayTest is L2ArbitrumGatewayTest { function test_outboundTransfer() public override { // mint token to user - deal(address(l2USDC), sender, 1 ether); + vm.prank(address(l2USDCGateway)); + IFiatToken(l2USDC).mint(sender, 20 ether); // withdrawal params uint256 withdrawalAmount = 200_500; @@ -155,7 +177,8 @@ contract L2USDCGatewayTest is L2ArbitrumGatewayTest { function test_outboundTransfer_4Args() public override { // mint token to user - deal(address(l2USDC), sender, 1 ether); + vm.prank(address(l2USDCGateway)); + IFiatToken(l2USDC).mint(sender, 20 ether); // withdrawal params uint256 withdrawalAmount = 200_500; @@ -199,13 +222,18 @@ contract L2USDCGatewayTest is L2ArbitrumGatewayTest { function test_pauseWithdrawals() public { assertEq(l2USDCGateway.withdrawalsPaused(), false, "Invalid withdrawalsPaused"); + uint256 mockL2Supply = 5000 ether; + vm.mockCall( + address(l2USDC), abi.encodeWithSignature("totalSupply()"), abi.encode(mockL2Supply) + ); + // events vm.expectEmit(true, true, true, true); emit TxToL1( address(l2USDCGateway), address(l1Counterpart), 0, - abi.encodeCall(L1USDCGateway.setL2GatewaySupply, (5000 ether)) + abi.encodeCall(L1USDCGateway.setL2GatewaySupply, mockL2Supply) ); vm.expectEmit(true, true, true, true); @@ -259,28 +287,3 @@ contract L2USDCGatewayTest is L2ArbitrumGatewayTest { event WithdrawalsPaused(); event WithdrawalsUnpaused(); } - -contract MockFiatToken is ERC20 { - address public minter; - - constructor(address _minter) ERC20("Bridged USDC", "USDC.e") { - minter = _minter; - } - - modifier onlyMinter() { - require(msg.sender == minter, "only minter"); - _; - } - - function totalSupply() public view override returns (uint256) { - return 5000 ether; - } - - function mint(address account, uint256 amount) public onlyMinter { - _mint(account, amount); - } - - function burn(uint256 amount) public onlyMinter { - _burn(msg.sender, amount); - } -} diff --git a/test-foundry/util/TestUtil.sol b/test-foundry/util/TestUtil.sol index c69795d935..2a8fcd026c 100644 --- a/test-foundry/util/TestUtil.sol +++ b/test-foundry/util/TestUtil.sol @@ -26,13 +26,13 @@ library TestUtil { // insert lib address into bytecode bytes memory b1 = - hex"60806040526001805460ff60a01b191690556000600b553480156200002357600080fd5b506200002f3362000035565b62000057565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b61508980620000676000396000f3fe608060405234801561001057600080fd5b50600436106103a45760003560e01c80638a6db9c3116101e9578063b7b728991161010f578063dd62ed3e116100ad578063ef55bec61161007c578063ef55bec614611069578063f2fde38b146110c8578063f9f92be4146110ee578063fe575a8714611114576103a4565b8063dd62ed3e14610fa8578063e3ee160e14610fd6578063e5a6b10f14611035578063e94a01021461103d576103a4565b8063cf092995116100e9578063cf09299514610e08578063d505accf14610edf578063d608ea6414610f30578063d916948714610fa0576103a4565b8063b7b7289914610d3d578063bd10243014610df8578063c2eeeebd14610e00576103a4565b8063a0cc6a6811610187578063aa20e1e411610156578063aa20e1e414610c95578063aa271e1a14610cbb578063ad38bf2214610ce1578063b2118a8d14610d07576103a4565b8063a0cc6a6814610c07578063a297ea5e14610c0f578063a457c2d714610c3d578063a9059cbb14610c69576103a4565b80638fa74a0e116101c35780638fa74a0e14610b2457806395d89b4114610b2c5780639fd0506d14610b345780639fd5a6cf14610b3c576103a4565b80638a6db9c314610aca5780638c2a993e14610af05780638da5cb5b14610b1c576103a4565b80633f4ba83a116102ce5780635a049a701161026c5780637ecebe001161023b5780637ecebe00146109bd5780637f2eecc3146109e35780638456cb59146109eb57806388b7ab63146109f3576103a4565b80635a049a70146109225780635c975abb1461096357806370a082311461096b57806374f4f54714610991576103a4565b8063430239b4116102a8578063430239b4146108065780634e44d956146108c857806354fd4d50146108f4578063554bab3c146108fc576103a4565b80633f4ba83a146107b557806340c10f19146107bd57806342966c68146107e9576103a4565b80633092afd51161034657806335d99f351161031557806335d99f35146107555780633644e5151461077957806338a63183146107815780633950935114610789576103a4565b80633092afd51461052a57806330adf81f14610550578063313ce567146105585780633357162b14610576576103a4565b80631a895266116103825780631a8952661461048057806323b872dd146104a85780632ab60045146104de5780632fc81e0914610504576103a4565b806306fdde03146103a9578063095ea7b31461042657806318160ddd14610466575b600080fd5b6103b161113a565b6040805160208082528351818301528351919283929083019185019080838360005b838110156103eb5781810151838201526020016103d3565b50505050905090810190601f1680156104185780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6104526004803603604081101561043c57600080fd5b506001600160a01b0381351690602001356111e6565b604080519115158252519081900360200190f35b61046e61125c565b60408051918252519081900360200190f35b6104a66004803603602081101561049657600080fd5b50356001600160a01b0316611262565b005b610452600480360360608110156104be57600080fd5b506001600160a01b038135811691602081013590911690604001356112eb565b6104a6600480360360208110156104f457600080fd5b50356001600160a01b03166114ec565b6104a66004803603602081101561051a57600080fd5b50356001600160a01b03166115f2565b6104526004803603602081101561054057600080fd5b50356001600160a01b031661163c565b61046e6116e3565b610560611707565b6040805160ff9092168252519081900360200190f35b6104a6600480360361010081101561058d57600080fd5b8101906020810181356401000000008111156105a857600080fd5b8201836020820111156105ba57600080fd5b803590602001918460018302840111640100000000831117156105dc57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929594936020810193503591505064010000000081111561062f57600080fd5b82018360208201111561064157600080fd5b8035906020019184600183028401116401000000008311171561066357600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092959493602081019350359150506401000000008111156106b657600080fd5b8201836020820111156106c857600080fd5b803590602001918460018302840111640100000000831117156106ea57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050813560ff1692505060208101356001600160a01b0390811691604081013582169160608201358116916080013516611710565b61075d61194f565b604080516001600160a01b039092168252519081900360200190f35b61046e61195e565b61075d61196d565b6104526004803603604081101561079f57600080fd5b506001600160a01b03813516906020013561197c565b6104a66119e9565b610452600480360360408110156107d357600080fd5b506001600160a01b038135169060200135611a85565b6104a6600480360360208110156107ff57600080fd5b5035611d68565b6104a66004803603604081101561081c57600080fd5b81019060208101813564010000000081111561083757600080fd5b82018360208201111561084957600080fd5b8035906020019184602083028401116401000000008311171561086b57600080fd5b91939092909160208101903564010000000081111561088957600080fd5b82018360208201111561089b57600080fd5b803590602001918460018302840111640100000000831117156108bd57600080fd5b509092509050611f77565b610452600480360360408110156108de57600080fd5b506001600160a01b0381351690602001356120b1565b6103b16121c7565b6104a66004803603602081101561091257600080fd5b50356001600160a01b03166121fe565b6104a6600480360360a081101561093857600080fd5b506001600160a01b038135169060208101359060ff604082013516906060810135906080013561230a565b61045261237d565b61046e6004803603602081101561098157600080fd5b50356001600160a01b031661238d565b6104a6600480360360408110156109a757600080fd5b506001600160a01b03813516906020013561239e565b61046e600480360360208110156109d357600080fd5b50356001600160a01b0316612419565b61046e612434565b6104a6612458565b6104a6600480360360e0811015610a0957600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359160808201359160a08101359181019060e0810160c0820135640100000000811115610a5557600080fd5b820183602082011115610a6757600080fd5b80359060200191846001830284011164010000000083111715610a8957600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506124fa945050505050565b61046e60048036036020811015610ae057600080fd5b50356001600160a01b03166125ff565b6104a660048036036040811015610b0657600080fd5b506001600160a01b03813516906020013561261a565b61075d612696565b61075d6126a5565b6103b16126ca565b61075d612743565b6104a6600480360360a0811015610b5257600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359181019060a081016080820135640100000000811115610b9257600080fd5b820183602082011115610ba457600080fd5b80359060200191846001830284011164010000000083111715610bc657600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612752945050505050565b61046e6127be565b6104a660048036036040811015610c2557600080fd5b506001600160a01b03813581169160200135166127e2565b61045260048036036040811015610c5357600080fd5b506001600160a01b038135169060200135612958565b61045260048036036040811015610c7f57600080fd5b506001600160a01b0381351690602001356129c5565b6104a660048036036020811015610cab57600080fd5b50356001600160a01b0316612ac9565b61045260048036036020811015610cd157600080fd5b50356001600160a01b0316612bd5565b6104a660048036036020811015610cf757600080fd5b50356001600160a01b0316612bf3565b6104a660048036036060811015610d1d57600080fd5b506001600160a01b03813581169160208101359091169060400135612cff565b6104a660048036036060811015610d5357600080fd5b6001600160a01b0382351691602081013591810190606081016040820135640100000000811115610d8357600080fd5b820183602082011115610d9557600080fd5b80359060200191846001830284011164010000000083111715610db757600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612d5c945050505050565b61075d612dc6565b61075d612dd5565b6104a6600480360360e0811015610e1e57600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359160808201359160a08101359181019060e0810160c0820135640100000000811115610e6a57600080fd5b820183602082011115610e7c57600080fd5b80359060200191846001830284011164010000000083111715610e9e57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612dfa945050505050565b6104a6600480360360e0811015610ef557600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c00135612ef4565b6104a660048036036020811015610f4657600080fd5b810190602081018135640100000000811115610f6157600080fd5b820183602082011115610f7357600080fd5b80359060200191846001830284011164010000000083111715610f9557600080fd5b509092509050612f6b565b61046e613025565b61046e60048036036040811015610fbe57600080fd5b506001600160a01b0381358116916020013516613049565b6104a66004803603610120811015610fed57600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060808101359060a08101359060ff60c0820135169060e0810135906101000135613074565b6103b161317d565b6104526004803603604081101561105357600080fd5b506001600160a01b0381351690602001356131f6565b6104a6600480360361012081101561108057600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060808101359060a08101359060ff60c0820135169060e0810135906101000135613221565b6104a6600480360360208110156110de57600080fd5b50356001600160a01b031661331d565b6104a66004803603602081101561110457600080fd5b50356001600160a01b0316613415565b6104526004803603602081101561112a57600080fd5b50356001600160a01b031661349e565b6004805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156111de5780601f106111b3576101008083540402835291602001916111de565b820191906000526020600020905b8154815290600101906020018083116111c157829003601f168201915b505050505081565b600154600090600160a01b900460ff1615611248576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6112533384846134a9565b50600192915050565b600b5490565b6002546001600160a01b031633146112ab5760405162461bcd60e51b815260040180806020018281038252602c815260200180614d05602c913960400191505060405180910390fd5b6112b481613595565b6040516001600160a01b038216907f117e3210bb9aa7d9baff172026820255c6f6c30ba8999d1c2fd88e2848137c4e90600090a250565b600154600090600160a01b900460ff161561134d576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b33611357816135a0565b156113935760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b8461139d816135a0565b156113d95760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b846113e3816135a0565b1561141f5760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b6001600160a01b0387166000908152600a602090815260408083203384529091529020548511156114815760405162461bcd60e51b8152600401808060200182810382526028815260200180614df56028913960400191505060405180910390fd5b61148c8787876135c1565b6001600160a01b0387166000908152600a602090815260408083203384529091529020546114ba908661370a565b6001600160a01b0388166000908152600a60209081526040808320338452909152902055600193505050509392505050565b6000546001600160a01b0316331461154b576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166115905760405162461bcd60e51b815260040180806020018281038252602a815260200180614c3e602a913960400191505060405180910390fd5b600e80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040517fe475e580d85111348e40d8ca33cfdd74c30fe1655c2d8537a13abc10065ffa5a90600090a250565b60125460ff1660011461160457600080fd5b600061160f30613767565b90508015611622576116223083836135c1565b61162b306137a4565b50506012805460ff19166002179055565b6008546000906001600160a01b031633146116885760405162461bcd60e51b8152600401808060200182810382526029815260200180614cdc6029913960400191505060405180910390fd5b6001600160a01b0382166000818152600c60209081526040808320805460ff19169055600d909152808220829055517fe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb666929190a2506001919050565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60065460ff1681565b600854600160a01b900460ff16156117595760405162461bcd60e51b815260040180806020018281038252602a815260200180614e70602a913960400191505060405180910390fd5b6001600160a01b03841661179e5760405162461bcd60e51b815260040180806020018281038252602f815260200180614da2602f913960400191505060405180910390fd5b6001600160a01b0383166117e35760405162461bcd60e51b8152600401808060200182810382526029815260200180614c156029913960400191505060405180910390fd5b6001600160a01b0382166118285760405162461bcd60e51b815260040180806020018281038252602e815260200180614e1d602e913960400191505060405180910390fd5b6001600160a01b03811661186d5760405162461bcd60e51b8152600401808060200182810382526028815260200180614f5d6028913960400191505060405180910390fd5b87516118809060049060208b01906149cc565b5086516118949060059060208a01906149cc565b5085516118a89060079060208901906149cc565b506006805460ff191660ff8716179055600880547fffffffffffffffffffffffff00000000000000000000000000000000000000009081166001600160a01b038781169190911790925560018054821686841617905560028054909116918416919091179055611917816137af565b5050600880547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16600160a01b179055505050505050565b6008546001600160a01b031681565b60006119686137e9565b905090565b600e546001600160a01b031690565b600154600090600160a01b900460ff16156119de576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6112533384846138de565b6001546001600160a01b03163314611a325760405162461bcd60e51b8152600401808060200182810382526022815260200180614f116022913960400191505060405180910390fd5b600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690556040517f7805862f689e2f13df9f062ff482ad3ad112aca9e0847911ed832e158c525b3390600090a1565b600154600090600160a01b900460ff1615611ae7576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff16611b355760405162461bcd60e51b8152600401808060200182810382526021815260200180614d816021913960400191505060405180910390fd5b33611b3f816135a0565b15611b7b5760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b83611b85816135a0565b15611bc15760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b6001600160a01b038516611c065760405162461bcd60e51b8152600401808060200182810382526023815260200180614baa6023913960400191505060405180910390fd5b60008411611c455760405162461bcd60e51b8152600401808060200182810382526029815260200180614c8d6029913960400191505060405180910390fd5b336000908152600d602052604090205480851115611c945760405162461bcd60e51b815260040180806020018281038252602e815260200180614ee3602e913960400191505060405180910390fd5b600b54611ca1908661391b565b600b55611cc086611cbb87611cb583613767565b9061391b565b61397c565b611cca818661370a565b336000818152600d602090815260409182902093909355805188815290516001600160a01b038a16937fab8530f87dc9b59234c4623bf917212bb2536d647574c8e7e5da92c2ede0c9f8928290030190a36040805186815290516001600160a01b038816916000917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a350600195945050505050565b600154600160a01b900460ff1615611dc7576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff16611e155760405162461bcd60e51b8152600401808060200182810382526021815260200180614d816021913960400191505060405180910390fd5b33611e1f816135a0565b15611e5b5760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b6000611e6633613767565b905060008311611ea75760405162461bcd60e51b8152600401808060200182810382526029815260200180614b816029913960400191505060405180910390fd5b82811015611ee65760405162461bcd60e51b8152600401808060200182810382526026815260200180614d5b6026913960400191505060405180910390fd5b600b54611ef3908461370a565b600b55611f0433611cbb838661370a565b60408051848152905133917fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5919081900360200190a260408051848152905160009133917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a3505050565b60125460ff16600214611f8957600080fd5b611f9560058383614a4a565b5060005b838110156120785760036000868684818110611fb157fe5b602090810292909201356001600160a01b03168352508101919091526040016000205460ff166120125760405162461bcd60e51b815260040180806020018281038252603d815260200180614ace603d913960400191505060405180910390fd5b61203685858381811061202157fe5b905060200201356001600160a01b03166137a4565b6003600086868481811061204657fe5b602090810292909201356001600160a01b0316835250810191909152604001600020805460ff19169055600101611f99565b50612082306137a4565b5050306000908152600360208190526040909120805460ff199081169091556012805490911690911790555050565b600154600090600160a01b900460ff1615612113576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6008546001600160a01b0316331461215c5760405162461bcd60e51b8152600401808060200182810382526029815260200180614cdc6029913960400191505060405180910390fd5b6001600160a01b0383166000818152600c60209081526040808320805460ff19166001179055600d825291829020859055815185815291517f46980fca912ef9bcdbd36877427b6b90e860769f604e89c0e67720cece530d209281900390910190a250600192915050565b60408051808201909152600181527f3200000000000000000000000000000000000000000000000000000000000000602082015290565b6000546001600160a01b0316331461225d576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166122a25760405162461bcd60e51b8152600401808060200182810382526028815260200180614b2e6028913960400191505060405180910390fd5b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691909117918290556040519116907fb80482a293ca2e013eda8683c9bd7fc8347cfdaeea5ede58cba46df502c2a60490600090a250565b600154600160a01b900460ff1615612369576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6123768585858585613a3c565b5050505050565b600154600160a01b900460ff1681565b600061239882613767565b92915050565b6123a66126a5565b6001600160a01b0316336001600160a01b03161461240b576040805162461bcd60e51b815260206004820152600c60248201527f4f4e4c595f474154455741590000000000000000000000000000000000000000604482015290519081900360640190fd5b6124158282613a7c565b5050565b6001600160a01b031660009081526011602052604090205490565b7fd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de881565b6001546001600160a01b031633146124a15760405162461bcd60e51b8152600401808060200182810382526022815260200180614f116022913960400191505060405180910390fd5b600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16600160a01b1790556040517f6985a02210a168e66602d3235cb6db0e70f92b3ba4d376a33c0f3d9434bff62590600090a1565b600154600160a01b900460ff1615612559576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b86612563816135a0565b1561259f5760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b866125a9816135a0565b156125e55760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b6125f489898989898989613c9e565b505050505050505050565b6001600160a01b03166000908152600d602052604090205490565b6126226126a5565b6001600160a01b0316336001600160a01b031614612687576040805162461bcd60e51b815260206004820152600c60248201527f4f4e4c595f474154455741590000000000000000000000000000000000000000604482015290519081900360640190fd5b6126918282611a85565b505050565b6000546001600160a01b031690565b7fdbf6298cab77bb44ebfd5abb25ed2538c2a55f7404c47e83e6531361fba28c245490565b6005805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156111de5780601f106111b3576101008083540402835291602001916111de565b6001546001600160a01b031681565b600154600160a01b900460ff16156127b1576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6123768585858585613d8b565b7f7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a226781565b60125460ff166003146127f457600080fd5b6001600160a01b03821661284f576040805162461bcd60e51b815260206004820152600f60248201527f494e56414c49445f474154455741590000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b0381166128aa576040805162461bcd60e51b815260206004820152601360248201527f494e56414c49445f434f554e5445525041525400000000000000000000000000604482015290519081900360640190fd5b60006128b46126a5565b6001600160a01b03161461290f576040805162461bcd60e51b815260206004820152600c60248201527f414c52454144595f494e49540000000000000000000000000000000000000000604482015290519081900360640190fd5b7fdbf6298cab77bb44ebfd5abb25ed2538c2a55f7404c47e83e6531361fba28c24919091557f54352c0d7cc5793352a36344bfdcdcf68ba6258544ce1aed71f60a74d882c19155565b600154600090600160a01b900460ff16156129ba576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b611253338484614001565b600154600090600160a01b900460ff1615612a27576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b33612a31816135a0565b15612a6d5760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b83612a77816135a0565b15612ab35760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b612abe3386866135c1565b506001949350505050565b6000546001600160a01b03163314612b28576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b038116612b6d5760405162461bcd60e51b815260040180806020018281038252602f815260200180614da2602f913960400191505060405180910390fd5b600880547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691909117918290556040519116907fdb66dfa9c6b8f5226fe9aac7e51897ae8ee94ac31dc70bb6c9900b2574b707e690600090a250565b6001600160a01b03166000908152600c602052604090205460ff1690565b6000546001600160a01b03163314612c52576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b038116612c975760405162461bcd60e51b8152600401808060200182810382526032815260200180614fb36032913960400191505060405180910390fd5b600280547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691909117918290556040519116907fc67398012c111ce95ecb7429b933096c977380ee6c421175a71a4a4c6c88c06e90600090a250565b600e546001600160a01b03163314612d485760405162461bcd60e51b8152600401808060200182810382526024815260200180614dd16024913960400191505060405180910390fd5b6126916001600160a01b0384168383614050565b600154600160a01b900460ff1615612dbb576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6126918383836140d0565b6002546001600160a01b031681565b7f54352c0d7cc5793352a36344bfdcdcf68ba6258544ce1aed71f60a74d882c1915490565b600154600160a01b900460ff1615612e59576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b86612e63816135a0565b15612e9f5760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b86612ea9816135a0565b15612ee55760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b6125f4898989898989896141a2565b600154600160a01b900460ff1615612f53576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b612f6287878787878787614233565b50505050505050565b600854600160a01b900460ff168015612f87575060125460ff16155b612f9057600080fd5b612f9c60048383614a4a565b5061301182828080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600181527f3200000000000000000000000000000000000000000000000000000000000000602082015291506142759050565b600f5550506012805460ff19166001179055565b7f158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a159742981565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205490565b600154600160a01b900460ff16156130d3576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b886130dd816135a0565b156131195760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b88613123816135a0565b1561315f5760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b6131708b8b8b8b8b8b8b8b8b61428b565b5050505050505050505050565b6007805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156111de5780601f106111b3576101008083540402835291602001916111de565b6001600160a01b03919091166000908152601060209081526040808320938352929052205460ff1690565b600154600160a01b900460ff1615613280576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b8861328a816135a0565b156132c65760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b886132d0816135a0565b1561330c5760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b6131708b8b8b8b8b8b8b8b8b6142cf565b6000546001600160a01b0316331461337c576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166133c15760405162461bcd60e51b8152600401808060200182810382526026815260200180614bcd6026913960400191505060405180910390fd5b600054604080516001600160a01b039283168152918316602083015280517f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09281900390910190a1613412816137af565b50565b6002546001600160a01b0316331461345e5760405162461bcd60e51b815260040180806020018281038252602c815260200180614d05602c913960400191505060405180910390fd5b613467816137a4565b6040516001600160a01b038216907fffa4e6181777692565cf28528fc88fd1516ea86b56da075235fa575af6a4b85590600090a250565b6000612398826135a0565b6001600160a01b0383166134ee5760405162461bcd60e51b8152600401808060200182810382526024815260200180614ebf6024913960400191505060405180910390fd5b6001600160a01b0382166135335760405162461bcd60e51b8152600401808060200182810382526022815260200180614bf36022913960400191505060405180910390fd5b6001600160a01b038084166000818152600a6020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b613412816000614313565b6001600160a01b031660009081526009602052604090205460ff1c60011490565b6001600160a01b0383166136065760405162461bcd60e51b8152600401808060200182810382526025815260200180614e9a6025913960400191505060405180910390fd5b6001600160a01b03821661364b5760405162461bcd60e51b8152600401808060200182810382526023815260200180614b0b6023913960400191505060405180910390fd5b61365483613767565b8111156136925760405162461bcd60e51b8152600401808060200182810382526026815260200180614cb66026913960400191505060405180910390fd5b6136a983611cbb836136a387613767565b9061370a565b6136ba82611cbb83611cb586613767565b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b600082821115613761576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6001600160a01b03166000908152600960205260409020547f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690565b613412816001614313565b600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6004805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815260009361196893919290918301828280156138965780601f1061386b57610100808354040283529160200191613896565b820191906000526020600020905b81548152906001019060200180831161387957829003601f168201915b50505050506040518060400160405280600181526020017f32000000000000000000000000000000000000000000000000000000000000008152506138d9614382565b614386565b6001600160a01b038084166000908152600a60209081526040808320938616835292905220546126919084908490613916908561391b565b6134a9565b600082820183811015613975576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8111156139db5760405162461bcd60e51b815260040180806020018281038252602a815260200180614d31602a913960400191505060405180910390fd5b6139e4826135a0565b15613a205760405162461bcd60e51b8152600401808060200182810382526025815260200180614c686025913960400191505060405180910390fd5b6001600160a01b03909116600090815260096020526040902055565b6123768585848487604051602001808481526020018381526020018260ff1660f81b815260010193505050506040516020818303038152906040526140d0565b600154600160a01b900460ff1615613adb576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff16613b295760405162461bcd60e51b8152600401808060200182810382526021815260200180614d816021913960400191505060405180910390fd5b81613b33816135a0565b15613b6f5760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b6000613b7a84613767565b905060008311613bbb5760405162461bcd60e51b8152600401808060200182810382526029815260200180614b816029913960400191505060405180910390fd5b82811015613bfa5760405162461bcd60e51b8152600401808060200182810382526026815260200180614d5b6026913960400191505060405180910390fd5b600b54613c07908461370a565b600b55613c1884611cbb838661370a565b6040805184815290516001600160a01b038616917fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5919081900360200190a26040805184815290516000916001600160a01b038716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a350505050565b6001600160a01b0386163314613ce55760405162461bcd60e51b8152600401808060200182810382526025815260200180614e4b6025913960400191505060405180910390fd5b613cf1878386866143fa565b604080517fd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de86020808301919091526001600160a01b03808b1683850152891660608301526080820188905260a0820187905260c0820186905260e0808301869052835180840390910181526101009092019092528051910120613d7690889083614486565b613d8087836145dd565b612f628787876135c1565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821480613db95750428210155b613e0a576040805162461bcd60e51b815260206004820152601e60248201527f46696174546f6b656e56323a207065726d697420697320657870697265640000604482015290519081900360640190fd5b6000613ea5613e176137e9565b6001600160a01b0380891660008181526011602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98184015280840194909452938b166060840152608083018a905260a083019390935260c08083018990528151808403909101815260e090920190528051910120614637565b905073"; + hex"60806040526001805460ff60a01b191690556000600b553480156200002357600080fd5b506200002f3362000035565b62000057565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b614aec80620000676000396000f3fe608060405234801561001057600080fd5b506004361061036d5760003560e01c80638456cb59116101d3578063b7b7289911610104578063e3ee160e116100a2578063ef55bec61161007c578063ef55bec614610f9c578063f2fde38b14610ffb578063f9f92be414611021578063fe575a87146110475761036d565b8063e3ee160e14610f09578063e5a6b10f14610f68578063e94a010214610f705761036d565b8063d505accf116100de578063d505accf14610e12578063d608ea6414610e63578063d916948714610ed3578063dd62ed3e14610edb5761036d565b8063b7b7289914610c78578063bd10243014610d33578063cf09299514610d3b5761036d565b8063a0cc6a6811610171578063aa20e1e41161014b578063aa20e1e414610bd0578063aa271e1a14610bf6578063ad38bf2214610c1c578063b2118a8d14610c425761036d565b8063a0cc6a6814610b70578063a457c2d714610b78578063a9059cbb14610ba45761036d565b80638da5cb5b116101ad5780638da5cb5b14610a8d57806395d89b4114610a955780639fd0506d14610a9d5780639fd5a6cf14610aa55761036d565b80638456cb591461098857806388b7ab63146109905780638a6db9c314610a675761036d565b806338a63183116102ad57806354fd4d501161024b5780635c975abb116102255780635c975abb1461092c57806370a08231146109345780637ecebe001461095a5780637f2eecc3146109805761036d565b806354fd4d50146108bd578063554bab3c146108c55780635a049a70146108eb5761036d565b806340c10f191161028757806340c10f191461078657806342966c68146107b2578063430239b4146107cf5780634e44d956146108915761036d565b806338a631831461074a57806339509351146107525780633f4ba83a1461077e5761036d565b80632fc81e091161031a578063313ce567116102f4578063313ce567146105215780633357162b1461053f57806335d99f351461071e5780633644e515146107425761036d565b80632fc81e09146104cd5780633092afd5146104f357806330adf81f146105195761036d565b80631a8952661161034b5780631a8952661461044957806323b872dd146104715780632ab60045146104a75761036d565b806306fdde0314610372578063095ea7b3146103ef57806318160ddd1461042f575b600080fd5b61037a61106d565b6040805160208082528351818301528351919283929083019185019080838360005b838110156103b457818101518382015260200161039c565b50505050905090810190601f1680156103e15780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61041b6004803603604081101561040557600080fd5b506001600160a01b038135169060200135611119565b604080519115158252519081900360200190f35b61043761118f565b60408051918252519081900360200190f35b61046f6004803603602081101561045f57600080fd5b50356001600160a01b0316611195565b005b61041b6004803603606081101561048757600080fd5b506001600160a01b0381358116916020810135909116906040013561121e565b61046f600480360360208110156104bd57600080fd5b50356001600160a01b031661141f565b61046f600480360360208110156104e357600080fd5b50356001600160a01b0316611525565b61041b6004803603602081101561050957600080fd5b50356001600160a01b031661156f565b610437611616565b61052961163a565b6040805160ff9092168252519081900360200190f35b61046f600480360361010081101561055657600080fd5b81019060208101813564010000000081111561057157600080fd5b82018360208201111561058357600080fd5b803590602001918460018302840111640100000000831117156105a557600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092959493602081019350359150506401000000008111156105f857600080fd5b82018360208201111561060a57600080fd5b8035906020019184600183028401116401000000008311171561062c57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929594936020810193503591505064010000000081111561067f57600080fd5b82018360208201111561069157600080fd5b803590602001918460018302840111640100000000831117156106b357600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050813560ff1692505060208101356001600160a01b0390811691604081013582169160608201358116916080013516611643565b610726611882565b604080516001600160a01b039092168252519081900360200190f35b610437611891565b6107266118a0565b61041b6004803603604081101561076857600080fd5b506001600160a01b0381351690602001356118af565b61046f61191c565b61041b6004803603604081101561079c57600080fd5b506001600160a01b0381351690602001356119b8565b61046f600480360360208110156107c857600080fd5b5035611c9b565b61046f600480360360408110156107e557600080fd5b81019060208101813564010000000081111561080057600080fd5b82018360208201111561081257600080fd5b8035906020019184602083028401116401000000008311171561083457600080fd5b91939092909160208101903564010000000081111561085257600080fd5b82018360208201111561086457600080fd5b8035906020019184600183028401116401000000008311171561088657600080fd5b509092509050611eaa565b61041b600480360360408110156108a757600080fd5b506001600160a01b038135169060200135611fe4565b61037a6120fa565b61046f600480360360208110156108db57600080fd5b50356001600160a01b0316612131565b61046f600480360360a081101561090157600080fd5b506001600160a01b038135169060208101359060ff604082013516906060810135906080013561223d565b61041b6122b0565b6104376004803603602081101561094a57600080fd5b50356001600160a01b03166122c0565b6104376004803603602081101561097057600080fd5b50356001600160a01b03166122d1565b6104376122ec565b61046f612310565b61046f600480360360e08110156109a657600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359160808201359160a08101359181019060e0810160c08201356401000000008111156109f257600080fd5b820183602082011115610a0457600080fd5b80359060200191846001830284011164010000000083111715610a2657600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506123b2945050505050565b61043760048036036020811015610a7d57600080fd5b50356001600160a01b03166124b7565b6107266124d2565b61037a6124e1565b61072661255a565b61046f600480360360a0811015610abb57600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359181019060a081016080820135640100000000811115610afb57600080fd5b820183602082011115610b0d57600080fd5b80359060200191846001830284011164010000000083111715610b2f57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612569945050505050565b6104376125d5565b61041b60048036036040811015610b8e57600080fd5b506001600160a01b0381351690602001356125f9565b61041b60048036036040811015610bba57600080fd5b506001600160a01b038135169060200135612666565b61046f60048036036020811015610be657600080fd5b50356001600160a01b031661276a565b61041b60048036036020811015610c0c57600080fd5b50356001600160a01b0316612876565b61046f60048036036020811015610c3257600080fd5b50356001600160a01b0316612894565b61046f60048036036060811015610c5857600080fd5b506001600160a01b038135811691602081013590911690604001356129a0565b61046f60048036036060811015610c8e57600080fd5b6001600160a01b0382351691602081013591810190606081016040820135640100000000811115610cbe57600080fd5b820183602082011115610cd057600080fd5b80359060200191846001830284011164010000000083111715610cf257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612a02945050505050565b610726612a6c565b61046f600480360360e0811015610d5157600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359160808201359160a08101359181019060e0810160c0820135640100000000811115610d9d57600080fd5b820183602082011115610daf57600080fd5b80359060200191846001830284011164010000000083111715610dd157600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612a7b945050505050565b61046f600480360360e0811015610e2857600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c00135612b75565b61046f60048036036020811015610e7957600080fd5b810190602081018135640100000000811115610e9457600080fd5b820183602082011115610ea657600080fd5b80359060200191846001830284011164010000000083111715610ec857600080fd5b509092509050612bec565b610437612ca6565b61043760048036036040811015610ef157600080fd5b506001600160a01b0381358116916020013516612cca565b61046f6004803603610120811015610f2057600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060808101359060a08101359060ff60c0820135169060e0810135906101000135612cf5565b61037a612dfe565b61041b60048036036040811015610f8657600080fd5b506001600160a01b038135169060200135612e77565b61046f6004803603610120811015610fb357600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060808101359060a08101359060ff60c0820135169060e0810135906101000135612ea2565b61046f6004803603602081101561101157600080fd5b50356001600160a01b0316612f9e565b61046f6004803603602081101561103757600080fd5b50356001600160a01b0316613096565b61041b6004803603602081101561105d57600080fd5b50356001600160a01b031661311f565b6004805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156111115780601f106110e657610100808354040283529160200191611111565b820191906000526020600020905b8154815290600101906020018083116110f457829003601f168201915b505050505081565b600154600090600160a01b900460ff161561117b576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b61118633848461312a565b50600192915050565b600b5490565b6002546001600160a01b031633146111de5760405162461bcd60e51b815260040180806020018281038252602c815260200180614768602c913960400191505060405180910390fd5b6111e781613216565b6040516001600160a01b038216907f117e3210bb9aa7d9baff172026820255c6f6c30ba8999d1c2fd88e2848137c4e90600090a250565b600154600090600160a01b900460ff1615611280576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b3361128a81613221565b156112c65760405162461bcd60e51b8152600401808060200182810382526025815260200180614a486025913960400191505060405180910390fd5b846112d081613221565b1561130c5760405162461bcd60e51b8152600401808060200182810382526025815260200180614a486025913960400191505060405180910390fd5b8461131681613221565b156113525760405162461bcd60e51b8152600401808060200182810382526025815260200180614a486025913960400191505060405180910390fd5b6001600160a01b0387166000908152600a602090815260408083203384529091529020548511156113b45760405162461bcd60e51b81526004018080602001828103825260288152602001806148586028913960400191505060405180910390fd5b6113bf878787613242565b6001600160a01b0387166000908152600a602090815260408083203384529091529020546113ed908661338b565b6001600160a01b0388166000908152600a60209081526040808320338452909152902055600193505050509392505050565b6000546001600160a01b0316331461147e576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166114c35760405162461bcd60e51b815260040180806020018281038252602a8152602001806146a1602a913960400191505060405180910390fd5b600e80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040517fe475e580d85111348e40d8ca33cfdd74c30fe1655c2d8537a13abc10065ffa5a90600090a250565b60125460ff1660011461153757600080fd5b6000611542306133e8565b9050801561155557611555308383613242565b61155e30613425565b50506012805460ff19166002179055565b6008546000906001600160a01b031633146115bb5760405162461bcd60e51b815260040180806020018281038252602981526020018061473f6029913960400191505060405180910390fd5b6001600160a01b0382166000818152600c60209081526040808320805460ff19169055600d909152808220829055517fe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb666929190a2506001919050565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60065460ff1681565b600854600160a01b900460ff161561168c5760405162461bcd60e51b815260040180806020018281038252602a8152602001806148d3602a913960400191505060405180910390fd5b6001600160a01b0384166116d15760405162461bcd60e51b815260040180806020018281038252602f815260200180614805602f913960400191505060405180910390fd5b6001600160a01b0383166117165760405162461bcd60e51b81526004018080602001828103825260298152602001806146786029913960400191505060405180910390fd5b6001600160a01b03821661175b5760405162461bcd60e51b815260040180806020018281038252602e815260200180614880602e913960400191505060405180910390fd5b6001600160a01b0381166117a05760405162461bcd60e51b81526004018080602001828103825260288152602001806149c06028913960400191505060405180910390fd5b87516117b39060049060208b019061442f565b5086516117c79060059060208a019061442f565b5085516117db90600790602089019061442f565b506006805460ff191660ff8716179055600880547fffffffffffffffffffffffff00000000000000000000000000000000000000009081166001600160a01b03878116919091179092556001805482168684161790556002805490911691841691909117905561184a81613430565b5050600880547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16600160a01b179055505050505050565b6008546001600160a01b031681565b600061189b61346a565b905090565b600e546001600160a01b031690565b600154600090600160a01b900460ff1615611911576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b61118633848461355f565b6001546001600160a01b031633146119655760405162461bcd60e51b81526004018080602001828103825260228152602001806149746022913960400191505060405180910390fd5b600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690556040517f7805862f689e2f13df9f062ff482ad3ad112aca9e0847911ed832e158c525b3390600090a1565b600154600090600160a01b900460ff1615611a1a576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff16611a685760405162461bcd60e51b81526004018080602001828103825260218152602001806147e46021913960400191505060405180910390fd5b33611a7281613221565b15611aae5760405162461bcd60e51b8152600401808060200182810382526025815260200180614a486025913960400191505060405180910390fd5b83611ab881613221565b15611af45760405162461bcd60e51b8152600401808060200182810382526025815260200180614a486025913960400191505060405180910390fd5b6001600160a01b038516611b395760405162461bcd60e51b815260040180806020018281038252602381526020018061460d6023913960400191505060405180910390fd5b60008411611b785760405162461bcd60e51b81526004018080602001828103825260298152602001806146f06029913960400191505060405180910390fd5b336000908152600d602052604090205480851115611bc75760405162461bcd60e51b815260040180806020018281038252602e815260200180614946602e913960400191505060405180910390fd5b600b54611bd4908661359c565b600b55611bf386611bee87611be8836133e8565b9061359c565b6135fd565b611bfd818661338b565b336000818152600d602090815260409182902093909355805188815290516001600160a01b038a16937fab8530f87dc9b59234c4623bf917212bb2536d647574c8e7e5da92c2ede0c9f8928290030190a36040805186815290516001600160a01b038816916000917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a350600195945050505050565b600154600160a01b900460ff1615611cfa576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff16611d485760405162461bcd60e51b81526004018080602001828103825260218152602001806147e46021913960400191505060405180910390fd5b33611d5281613221565b15611d8e5760405162461bcd60e51b8152600401808060200182810382526025815260200180614a486025913960400191505060405180910390fd5b6000611d99336133e8565b905060008311611dda5760405162461bcd60e51b81526004018080602001828103825260298152602001806145e46029913960400191505060405180910390fd5b82811015611e195760405162461bcd60e51b81526004018080602001828103825260268152602001806147be6026913960400191505060405180910390fd5b600b54611e26908461338b565b600b55611e3733611bee838661338b565b60408051848152905133917fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5919081900360200190a260408051848152905160009133917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a3505050565b60125460ff16600214611ebc57600080fd5b611ec8600583836144ad565b5060005b83811015611fab5760036000868684818110611ee457fe5b602090810292909201356001600160a01b03168352508101919091526040016000205460ff16611f455760405162461bcd60e51b815260040180806020018281038252603d815260200180614531603d913960400191505060405180910390fd5b611f69858583818110611f5457fe5b905060200201356001600160a01b0316613425565b60036000868684818110611f7957fe5b602090810292909201356001600160a01b0316835250810191909152604001600020805460ff19169055600101611ecc565b50611fb530613425565b5050306000908152600360208190526040909120805460ff199081169091556012805490911690911790555050565b600154600090600160a01b900460ff1615612046576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6008546001600160a01b0316331461208f5760405162461bcd60e51b815260040180806020018281038252602981526020018061473f6029913960400191505060405180910390fd5b6001600160a01b0383166000818152600c60209081526040808320805460ff19166001179055600d825291829020859055815185815291517f46980fca912ef9bcdbd36877427b6b90e860769f604e89c0e67720cece530d209281900390910190a250600192915050565b60408051808201909152600181527f3200000000000000000000000000000000000000000000000000000000000000602082015290565b6000546001600160a01b03163314612190576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166121d55760405162461bcd60e51b81526004018080602001828103825260288152602001806145916028913960400191505060405180910390fd5b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691909117918290556040519116907fb80482a293ca2e013eda8683c9bd7fc8347cfdaeea5ede58cba46df502c2a60490600090a250565b600154600160a01b900460ff161561229c576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6122a985858585856136bd565b5050505050565b600154600160a01b900460ff1681565b60006122cb826133e8565b92915050565b6001600160a01b031660009081526011602052604090205490565b7fd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de881565b6001546001600160a01b031633146123595760405162461bcd60e51b81526004018080602001828103825260228152602001806149746022913960400191505060405180910390fd5b600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16600160a01b1790556040517f6985a02210a168e66602d3235cb6db0e70f92b3ba4d376a33c0f3d9434bff62590600090a1565b600154600160a01b900460ff1615612411576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b8661241b81613221565b156124575760405162461bcd60e51b8152600401808060200182810382526025815260200180614a486025913960400191505060405180910390fd5b8661246181613221565b1561249d5760405162461bcd60e51b8152600401808060200182810382526025815260200180614a486025913960400191505060405180910390fd5b6124ac898989898989896136fd565b505050505050505050565b6001600160a01b03166000908152600d602052604090205490565b6000546001600160a01b031690565b6005805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156111115780601f106110e657610100808354040283529160200191611111565b6001546001600160a01b031681565b600154600160a01b900460ff16156125c8576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6122a985858585856137ea565b7f7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a226781565b600154600090600160a01b900460ff161561265b576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b611186338484613a60565b600154600090600160a01b900460ff16156126c8576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336126d281613221565b1561270e5760405162461bcd60e51b8152600401808060200182810382526025815260200180614a486025913960400191505060405180910390fd5b8361271881613221565b156127545760405162461bcd60e51b8152600401808060200182810382526025815260200180614a486025913960400191505060405180910390fd5b61275f338686613242565b506001949350505050565b6000546001600160a01b031633146127c9576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b03811661280e5760405162461bcd60e51b815260040180806020018281038252602f815260200180614805602f913960400191505060405180910390fd5b600880547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691909117918290556040519116907fdb66dfa9c6b8f5226fe9aac7e51897ae8ee94ac31dc70bb6c9900b2574b707e690600090a250565b6001600160a01b03166000908152600c602052604090205460ff1690565b6000546001600160a01b031633146128f3576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166129385760405162461bcd60e51b8152600401808060200182810382526032815260200180614a166032913960400191505060405180910390fd5b600280547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691909117918290556040519116907fc67398012c111ce95ecb7429b933096c977380ee6c421175a71a4a4c6c88c06e90600090a250565b600e546001600160a01b031633146129e95760405162461bcd60e51b81526004018080602001828103825260248152602001806148346024913960400191505060405180910390fd5b6129fd6001600160a01b0384168383613aaf565b505050565b600154600160a01b900460ff1615612a61576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6129fd838383613b2f565b6002546001600160a01b031681565b600154600160a01b900460ff1615612ada576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b86612ae481613221565b15612b205760405162461bcd60e51b8152600401808060200182810382526025815260200180614a486025913960400191505060405180910390fd5b86612b2a81613221565b15612b665760405162461bcd60e51b8152600401808060200182810382526025815260200180614a486025913960400191505060405180910390fd5b6124ac89898989898989613c01565b600154600160a01b900460ff1615612bd4576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b612be387878787878787613c92565b50505050505050565b600854600160a01b900460ff168015612c08575060125460ff16155b612c1157600080fd5b612c1d600483836144ad565b50612c9282828080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600181527f320000000000000000000000000000000000000000000000000000000000000060208201529150613cd49050565b600f5550506012805460ff19166001179055565b7f158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a159742981565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205490565b600154600160a01b900460ff1615612d54576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b88612d5e81613221565b15612d9a5760405162461bcd60e51b8152600401808060200182810382526025815260200180614a486025913960400191505060405180910390fd5b88612da481613221565b15612de05760405162461bcd60e51b8152600401808060200182810382526025815260200180614a486025913960400191505060405180910390fd5b612df18b8b8b8b8b8b8b8b8b613cea565b5050505050505050505050565b6007805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156111115780601f106110e657610100808354040283529160200191611111565b6001600160a01b03919091166000908152601060209081526040808320938352929052205460ff1690565b600154600160a01b900460ff1615612f01576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b88612f0b81613221565b15612f475760405162461bcd60e51b8152600401808060200182810382526025815260200180614a486025913960400191505060405180910390fd5b88612f5181613221565b15612f8d5760405162461bcd60e51b8152600401808060200182810382526025815260200180614a486025913960400191505060405180910390fd5b612df18b8b8b8b8b8b8b8b8b613d2e565b6000546001600160a01b03163314612ffd576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166130425760405162461bcd60e51b81526004018080602001828103825260268152602001806146306026913960400191505060405180910390fd5b600054604080516001600160a01b039283168152918316602083015280517f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09281900390910190a161309381613430565b50565b6002546001600160a01b031633146130df5760405162461bcd60e51b815260040180806020018281038252602c815260200180614768602c913960400191505060405180910390fd5b6130e881613425565b6040516001600160a01b038216907fffa4e6181777692565cf28528fc88fd1516ea86b56da075235fa575af6a4b85590600090a250565b60006122cb82613221565b6001600160a01b03831661316f5760405162461bcd60e51b81526004018080602001828103825260248152602001806149226024913960400191505060405180910390fd5b6001600160a01b0382166131b45760405162461bcd60e51b81526004018080602001828103825260228152602001806146566022913960400191505060405180910390fd5b6001600160a01b038084166000818152600a6020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b613093816000613d72565b6001600160a01b031660009081526009602052604090205460ff1c60011490565b6001600160a01b0383166132875760405162461bcd60e51b81526004018080602001828103825260258152602001806148fd6025913960400191505060405180910390fd5b6001600160a01b0382166132cc5760405162461bcd60e51b815260040180806020018281038252602381526020018061456e6023913960400191505060405180910390fd5b6132d5836133e8565b8111156133135760405162461bcd60e51b81526004018080602001828103825260268152602001806147196026913960400191505060405180910390fd5b61332a83611bee83613324876133e8565b9061338b565b61333b82611bee83611be8866133e8565b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6000828211156133e2576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6001600160a01b03166000908152600960205260409020547f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690565b613093816001613d72565b600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6004805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815260009361189b93919290918301828280156135175780601f106134ec57610100808354040283529160200191613517565b820191906000526020600020905b8154815290600101906020018083116134fa57829003601f168201915b50505050506040518060400160405280600181526020017f320000000000000000000000000000000000000000000000000000000000000081525061355a613de1565b613de5565b6001600160a01b038084166000908152600a60209081526040808320938616835292905220546129fd9084908490613597908561359c565b61312a565b6000828201838110156135f6576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81111561365c5760405162461bcd60e51b815260040180806020018281038252602a815260200180614794602a913960400191505060405180910390fd5b61366582613221565b156136a15760405162461bcd60e51b81526004018080602001828103825260258152602001806146cb6025913960400191505060405180910390fd5b6001600160a01b03909116600090815260096020526040902055565b6122a98585848487604051602001808481526020018381526020018260ff1660f81b81526001019350505050604051602081830303815290604052613b2f565b6001600160a01b03861633146137445760405162461bcd60e51b81526004018080602001828103825260258152602001806148ae6025913960400191505060405180910390fd5b61375087838686613e59565b604080517fd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de86020808301919091526001600160a01b03808b1683850152891660608301526080820188905260a0820187905260c0820186905260e08083018690528351808403909101815261010090920190925280519101206137d590889083613ee5565b6137df878361403c565b612be3878787613242565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214806138185750428210155b613869576040805162461bcd60e51b815260206004820152601e60248201527f46696174546f6b656e56323a207065726d697420697320657870697265640000604482015290519081900360640190fd5b600061390461387661346a565b6001600160a01b0380891660008181526011602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98184015280840194909452938b166060840152608083018a905260a083019390935260c08083018990528151808403909101815260e090920190528051910120614096565b905073"; bytes memory b2 = - hex"636ccea6528783856040518463ffffffff1660e01b815260040180846001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015613f25578181015183820152602001613f0d565b50505050905090810190601f168015613f525780820380516001836020036101000a031916815260200191505b5094505050505060206040518083038186803b158015613f7157600080fd5b505af4158015613f85573d6000803e3d6000fd5b505050506040513d6020811015613f9b57600080fd5b5051613fee576040805162461bcd60e51b815260206004820152601a60248201527f454950323631323a20696e76616c6964207369676e6174757265000000000000604482015290519081900360640190fd5b613ff98686866134a9565b505050505050565b61269183836139168460405180606001604052806025815260200161502f602591396001600160a01b03808a166000908152600a60209081526040808320938c16835292905220549190614671565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052612691908490614708565b6140da83836147b9565b614147837f158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a159742960001b858560405160200180848152602001836001600160a01b0316815260200182815260200193505050506040516020818303038152906040528051906020012083614486565b6001600160a01b0383166000818152601060209081526040808320868452909152808220805460ff19166001179055518492917f1cdd46ff242716cdaa72d159d339a485b3438398348d68f09d7c8c0a59353d8191a3505050565b6141ae878386866143fa565b604080517f7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a22676020808301919091526001600160a01b03808b1683850152891660608301526080820188905260a0820187905260c0820186905260e0808301869052835180840390910181526101009092019092528051910120613d7690889083614486565b612f6287878787868689604051602001808481526020018381526020018260ff1660f81b81526001019350505050604051602081830303815290604052613d8b565b600046614283848483614386565b949350505050565b6125f489898989898988888b604051602001808481526020018381526020018260ff1660f81b815260010193505050506040516020818303038152906040526141a2565b6125f489898989898988888b604051602001808481526020018381526020018260ff1660f81b81526001019350505050604051602081830303815290604052613c9e565b806143265761432182613767565b614362565b6001600160a01b0382166000908152600960205260409020547f8000000000000000000000000000000000000000000000000000000000000000175b6001600160a01b0390921660009081526009602052604090209190915550565b4690565b8251602093840120825192840192909220604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8187015280820194909452606084019190915260808301919091523060a0808401919091528151808403909101815260c09092019052805191012090565b8142116144385760405162461bcd60e51b815260040180806020018281038252602b815260200180614b56602b913960400191505060405180910390fd5b8042106144765760405162461bcd60e51b815260040180806020018281038252602581526020018061500a6025913960400191505060405180910390fd5b61448084846147b9565b50505050565b73"; + hex"636ccea6528783856040518463ffffffff1660e01b815260040180846001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561398457818101518382015260200161396c565b50505050905090810190601f1680156139b15780820380516001836020036101000a031916815260200191505b5094505050505060206040518083038186803b1580156139d057600080fd5b505af41580156139e4573d6000803e3d6000fd5b505050506040513d60208110156139fa57600080fd5b5051613a4d576040805162461bcd60e51b815260206004820152601a60248201527f454950323631323a20696e76616c6964207369676e6174757265000000000000604482015290519081900360640190fd5b613a5886868661312a565b505050505050565b6129fd838361359784604051806060016040528060258152602001614a92602591396001600160a01b03808a166000908152600a60209081526040808320938c168352929052205491906140d0565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790526129fd908490614167565b613b398383614218565b613ba6837f158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a159742960001b858560405160200180848152602001836001600160a01b0316815260200182815260200193505050506040516020818303038152906040528051906020012083613ee5565b6001600160a01b0383166000818152601060209081526040808320868452909152808220805460ff19166001179055518492917f1cdd46ff242716cdaa72d159d339a485b3438398348d68f09d7c8c0a59353d8191a3505050565b613c0d87838686613e59565b604080517f7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a22676020808301919091526001600160a01b03808b1683850152891660608301526080820188905260a0820187905260c0820186905260e08083018690528351808403909101815261010090920190925280519101206137d590889083613ee5565b612be387878787868689604051602001808481526020018381526020018260ff1660f81b815260010193505050506040516020818303038152906040526137ea565b600046613ce2848483613de5565b949350505050565b6124ac89898989898988888b604051602001808481526020018381526020018260ff1660f81b81526001019350505050604051602081830303815290604052613c01565b6124ac89898989898988888b604051602001808481526020018381526020018260ff1660f81b815260010193505050506040516020818303038152906040526136fd565b80613d8557613d80826133e8565b613dc1565b6001600160a01b0382166000908152600960205260409020547f8000000000000000000000000000000000000000000000000000000000000000175b6001600160a01b0390921660009081526009602052604090209190915550565b4690565b8251602093840120825192840192909220604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8187015280820194909452606084019190915260808301919091523060a0808401919091528151808403909101815260c09092019052805191012090565b814211613e975760405162461bcd60e51b815260040180806020018281038252602b8152602001806145b9602b913960400191505060405180910390fd5b804210613ed55760405162461bcd60e51b8152600401808060200182810382526025815260200180614a6d6025913960400191505060405180910390fd5b613edf8484614218565b50505050565b73"; bytes memory b3 = - hex"636ccea652846144b26144ac6137e9565b86614637565b846040518463ffffffff1660e01b815260040180846001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b838110156145145781810151838201526020016144fc565b50505050905090810190601f1680156145415780820380516001836020036101000a031916815260200191505b5094505050505060206040518083038186803b15801561456057600080fd5b505af4158015614574573d6000803e3d6000fd5b505050506040513d602081101561458a57600080fd5b5051612691576040805162461bcd60e51b815260206004820152601e60248201527f46696174546f6b656e56323a20696e76616c6964207369676e61747572650000604482015290519081900360640190fd5b6001600160a01b0382166000818152601060209081526040808320858452909152808220805460ff19166001179055518392917f98de503528ee59b575ef0c0a2576a82497bfc029a5685b209e9ec333479b10a591a35050565b6040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b600081848411156147005760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156146c55781810151838201526020016146ad565b50505050905090810190601f1680156146f25780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b606061475d826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661481c9092919063ffffffff16565b8051909150156126915780806020019051602081101561477c57600080fd5b50516126915760405162461bcd60e51b815260040180806020018281038252602a815260200180614f33602a913960400191505060405180910390fd5b6001600160a01b038216600090815260106020908152604080832084845290915290205460ff16156124155760405162461bcd60e51b815260040180806020018281038252602e815260200180614f85602e913960400191505060405180910390fd5b606061428384846000858561483085614960565b614881576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b602083106148de57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016148a1565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114614940576040519150601f19603f3d011682016040523d82523d6000602084013e614945565b606091505b5091509150614955828286614966565b979650505050505050565b3b151590565b60608315614975575081613975565b8251156149855782518084602001fd5b60405162461bcd60e51b81526020600482018181528451602484015284518593919283926044019190850190808383600083156146c55781810151838201526020016146ad565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10614a0d57805160ff1916838001178555614a3a565b82800160010185558215614a3a579182015b82811115614a3a578251825591602001919060010190614a1f565b50614a46929150614ab8565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10614a8b5782800160ff19823516178555614a3a565b82800160010185558215614a3a579182015b82811115614a3a578235825591602001919060010190614a9d565b5b80821115614a465760008155600101614ab956fe46696174546f6b656e56325f323a20426c61636b6c697374696e672070726576696f75736c7920756e626c61636b6c6973746564206163636f756e742145524332303a207472616e7366657220746f20746865207a65726f20616464726573735061757361626c653a206e65772070617573657220697320746865207a65726f206164647265737346696174546f6b656e56323a20617574686f72697a6174696f6e206973206e6f74207965742076616c696446696174546f6b656e3a206275726e20616d6f756e74206e6f742067726561746572207468616e203046696174546f6b656e3a206d696e7420746f20746865207a65726f20616464726573734f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737346696174546f6b656e3a206e65772070617573657220697320746865207a65726f2061646472657373526573637561626c653a206e6577207265736375657220697320746865207a65726f206164647265737346696174546f6b656e56325f323a204163636f756e7420697320626c61636b6c697374656446696174546f6b656e3a206d696e7420616d6f756e74206e6f742067726561746572207468616e203045524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636546696174546f6b656e3a2063616c6c6572206973206e6f7420746865206d61737465724d696e746572426c61636b6c69737461626c653a2063616c6c6572206973206e6f742074686520626c61636b6c697374657246696174546f6b656e56325f323a2042616c616e636520657863656564732028325e323535202d20312946696174546f6b656e3a206275726e20616d6f756e7420657863656564732062616c616e636546696174546f6b656e3a2063616c6c6572206973206e6f742061206d696e74657246696174546f6b656e3a206e6577206d61737465724d696e74657220697320746865207a65726f2061646472657373526573637561626c653a2063616c6c6572206973206e6f7420746865207265736375657245524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636546696174546f6b656e3a206e657720626c61636b6c697374657220697320746865207a65726f206164647265737346696174546f6b656e56323a2063616c6c6572206d7573742062652074686520706179656546696174546f6b656e3a20636f6e747261637420697320616c726561647920696e697469616c697a656445524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737346696174546f6b656e3a206d696e7420616d6f756e742065786365656473206d696e746572416c6c6f77616e63655061757361626c653a2063616c6c6572206973206e6f7420746865207061757365725361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656446696174546f6b656e3a206e6577206f776e657220697320746865207a65726f206164647265737346696174546f6b656e56323a20617574686f72697a6174696f6e2069732075736564206f722063616e63656c6564426c61636b6c69737461626c653a206e657720626c61636b6c697374657220697320746865207a65726f2061646472657373426c61636b6c69737461626c653a206163636f756e7420697320626c61636b6c697374656446696174546f6b656e56323a20617574686f72697a6174696f6e206973206578706972656445524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122069f43cc6c29d58063264d46f6f667d8af0c0a5209b8e811c80c4675b7ac594b364736f6c634300060c0033"; + hex"636ccea65284613f11613f0b61346a565b86614096565b846040518463ffffffff1660e01b815260040180846001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015613f73578181015183820152602001613f5b565b50505050905090810190601f168015613fa05780820380516001836020036101000a031916815260200191505b5094505050505060206040518083038186803b158015613fbf57600080fd5b505af4158015613fd3573d6000803e3d6000fd5b505050506040513d6020811015613fe957600080fd5b50516129fd576040805162461bcd60e51b815260206004820152601e60248201527f46696174546f6b656e56323a20696e76616c6964207369676e61747572650000604482015290519081900360640190fd5b6001600160a01b0382166000818152601060209081526040808320858452909152808220805460ff19166001179055518392917f98de503528ee59b575ef0c0a2576a82497bfc029a5685b209e9ec333479b10a591a35050565b6040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b6000818484111561415f5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561412457818101518382015260200161410c565b50505050905090810190601f1680156141515780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b60606141bc826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661427f9092919063ffffffff16565b8051909150156129fd578080602001905160208110156141db57600080fd5b50516129fd5760405162461bcd60e51b815260040180806020018281038252602a815260200180614996602a913960400191505060405180910390fd5b6001600160a01b038216600090815260106020908152604080832084845290915290205460ff161561427b5760405162461bcd60e51b815260040180806020018281038252602e8152602001806149e8602e913960400191505060405180910390fd5b5050565b6060613ce2848460008585614293856143c3565b6142e4576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b6020831061434157805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101614304565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d80600081146143a3576040519150601f19603f3d011682016040523d82523d6000602084013e6143a8565b606091505b50915091506143b88282866143c9565b979650505050505050565b3b151590565b606083156143d85750816135f6565b8251156143e85782518084602001fd5b60405162461bcd60e51b815260206004820181815284516024840152845185939192839260440191908501908083836000831561412457818101518382015260200161410c565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061447057805160ff191683800117855561449d565b8280016001018555821561449d579182015b8281111561449d578251825591602001919060010190614482565b506144a992915061451b565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106144ee5782800160ff1982351617855561449d565b8280016001018555821561449d579182015b8281111561449d578235825591602001919060010190614500565b5b808211156144a9576000815560010161451c56fe46696174546f6b656e56325f323a20426c61636b6c697374696e672070726576696f75736c7920756e626c61636b6c6973746564206163636f756e742145524332303a207472616e7366657220746f20746865207a65726f20616464726573735061757361626c653a206e65772070617573657220697320746865207a65726f206164647265737346696174546f6b656e56323a20617574686f72697a6174696f6e206973206e6f74207965742076616c696446696174546f6b656e3a206275726e20616d6f756e74206e6f742067726561746572207468616e203046696174546f6b656e3a206d696e7420746f20746865207a65726f20616464726573734f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737346696174546f6b656e3a206e65772070617573657220697320746865207a65726f2061646472657373526573637561626c653a206e6577207265736375657220697320746865207a65726f206164647265737346696174546f6b656e56325f323a204163636f756e7420697320626c61636b6c697374656446696174546f6b656e3a206d696e7420616d6f756e74206e6f742067726561746572207468616e203045524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636546696174546f6b656e3a2063616c6c6572206973206e6f7420746865206d61737465724d696e746572426c61636b6c69737461626c653a2063616c6c6572206973206e6f742074686520626c61636b6c697374657246696174546f6b656e56325f323a2042616c616e636520657863656564732028325e323535202d20312946696174546f6b656e3a206275726e20616d6f756e7420657863656564732062616c616e636546696174546f6b656e3a2063616c6c6572206973206e6f742061206d696e74657246696174546f6b656e3a206e6577206d61737465724d696e74657220697320746865207a65726f2061646472657373526573637561626c653a2063616c6c6572206973206e6f7420746865207265736375657245524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636546696174546f6b656e3a206e657720626c61636b6c697374657220697320746865207a65726f206164647265737346696174546f6b656e56323a2063616c6c6572206d7573742062652074686520706179656546696174546f6b656e3a20636f6e747261637420697320616c726561647920696e697469616c697a656445524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737346696174546f6b656e3a206d696e7420616d6f756e742065786365656473206d696e746572416c6c6f77616e63655061757361626c653a2063616c6c6572206973206e6f7420746865207061757365725361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656446696174546f6b656e3a206e6577206f776e657220697320746865207a65726f206164647265737346696174546f6b656e56323a20617574686f72697a6174696f6e2069732075736564206f722063616e63656c6564426c61636b6c69737461626c653a206e657720626c61636b6c697374657220697320746865207a65726f2061646472657373426c61636b6c69737461626c653a206163636f756e7420697320626c61636b6c697374656446696174546f6b656e56323a20617574686f72697a6174696f6e206973206578706972656445524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa26469706673582212206b5e166c9bb86d4031d11482d2bd231c0f948b4d47fe27594c561c1db6a6c61364736f6c634300060c0033"; bytes memory libAddress = abi.encodePacked(sigCheckerAddress); From 925b3401c0307e65b521c65948b3e8b28dc6f15f Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 20 Jun 2024 10:28:55 +0200 Subject: [PATCH 17/20] Bump SDK --- package.json | 2 +- yarn.lock | 21 +++++++++++++++++---- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 92b8884871..57acfc0f2f 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "@openzeppelin/contracts-upgradeable": "4.8.3" }, "devDependencies": { - "@arbitrum/sdk": "^3.1.3", + "@arbitrum/sdk": "^3.5.1", "@nomiclabs/hardhat-ethers": "^2.0.1", "@nomiclabs/hardhat-etherscan": "^3.1.0", "@nomiclabs/hardhat-waffle": "^2.0.1", diff --git a/yarn.lock b/yarn.lock index a33ede27d2..86903fde2e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17,14 +17,15 @@ "@openzeppelin/contracts-upgradeable" "4.5.2" patch-package "^6.4.7" -"@arbitrum/sdk@^3.1.3": - version "3.1.9" - resolved "https://registry.yarnpkg.com/@arbitrum/sdk/-/sdk-3.1.9.tgz#a511bc70cdd0a947445e4e27833c242ccb77ddf5" - integrity sha512-7Rf75cKmQ8nutTV+2JAOXcI6DKG4D7QCJz1JL2nq6hUpRuw4jyKn+irLqJtcIExssylLWt3t/pKV6fYseCYKNg== +"@arbitrum/sdk@^3.5.1": + version "3.5.1" + resolved "https://registry.yarnpkg.com/@arbitrum/sdk/-/sdk-3.5.1.tgz#9606b726101e62ca32953386a9ba341041e40c47" + integrity sha512-UQ5nUSmvFzEYpAbf1CKkYZmGGq9WysRASOWEAimc63EYVwkOV31hU5m8Dnj6JiJtLcO8mFYnTlVsJGex5oxntw== dependencies: "@ethersproject/address" "^5.0.8" "@ethersproject/bignumber" "^5.1.1" "@ethersproject/bytes" "^5.0.8" + async-mutex "^0.4.0" ethers "^5.1.0" "@babel/code-frame@7.12.11": @@ -1953,6 +1954,13 @@ async-limiter@~1.0.0: resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== +async-mutex@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/async-mutex/-/async-mutex-0.4.1.tgz#bccf55b96f2baf8df90ed798cb5544a1f6ee4c2c" + integrity sha512-WfoBo4E/TbCX1G95XTjbWTE3X2XLG0m1Xbv2cwOtuPdyH9CZvnaA5nCt1ucjaKEgW2A5IF71hxrRhr83Je5xjA== + dependencies: + tslib "^2.4.0" + async@1.x, async@^1.4.2: version "1.5.2" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" @@ -9733,6 +9741,11 @@ tslib@^1.13.0, tslib@^1.8.1, tslib@^1.9.3: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== +tslib@^2.4.0: + version "2.6.3" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.3.tgz#0438f810ad7a9edcde7a241c3d80db693c8cbfe0" + integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ== + tslint@^6.1.3: version "6.1.3" resolved "https://registry.yarnpkg.com/tslint/-/tslint-6.1.3.tgz#5c23b2eccc32487d5523bd3a470e9aa31789d904" From d19bb45ccc2747ea27a8c568867c56dc28c088ec Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 20 Jun 2024 11:06:28 +0200 Subject: [PATCH 18/20] Adapt network registration to the new SDK requirements --- .../local-deployment/localDeploymentLib.ts | 154 ++++++++++++------ 1 file changed, 103 insertions(+), 51 deletions(-) diff --git a/scripts/local-deployment/localDeploymentLib.ts b/scripts/local-deployment/localDeploymentLib.ts index 9288cca116..71ebaea20d 100644 --- a/scripts/local-deployment/localDeploymentLib.ts +++ b/scripts/local-deployment/localDeploymentLib.ts @@ -10,7 +10,6 @@ import { getEstimateForDeployingFactory, registerGateway, } from '../atomicTokenBridgeDeployer' -import { l2Networks } from '@arbitrum/sdk/dist/lib/dataEntities/networks' import { IOwnable__factory, TestWETH9__factory } from '../../build/types' const LOCALHOST_L2_RPC = 'http://localhost:8547' @@ -71,39 +70,29 @@ export const setupTokenBridgeInLocalEnv = async () => { new ethers.providers.JsonRpcProvider(childRpc) ) + /// register networks const { l1Network, l2Network: coreL2Network } = await getLocalNetworks( parentRpc, childRpc, rollupAddress ) - - // register - needed for retryables - const existingL2Network = l2Networks[coreL2Network.chainID.toString()] - if (!existingL2Network) { - addCustomNetwork({ - customL1Network: l1Network, - customL2Network: { - ...coreL2Network, - tokenBridge: { - l1CustomGateway: '', - l1ERC20Gateway: '', - l1GatewayRouter: '', - l1MultiCall: '', - l1ProxyAdmin: '', - l1Weth: '', - l1WethGateway: '', - - l2CustomGateway: '', - l2ERC20Gateway: '', - l2GatewayRouter: '', - l2Multicall: '', - l2ProxyAdmin: '', - l2Weth: '', - l2WethGateway: '', - }, - }, - }) + const _l1Network = l1Network as L2Network + const ethLocal: L1Network = { + blockTime: 10, + chainID: _l1Network.partnerChainID, + explorerUrl: '', + isCustom: true, + name: 'EthLocal', + partnerChainIDs: [_l1Network.chainID], + isArbitrum: false, } + addCustomNetwork({ + customL1Network: ethLocal, + customL2Network: _l1Network, + }) + addCustomNetwork({ + customL2Network: coreL2Network, + }) // prerequisite - deploy L1 creator and set templates console.log('Deploying L1TokenBridgeCreator') @@ -203,13 +192,73 @@ export const getLocalNetworks = async ( l2Url: string, rollupAddress?: string ): Promise<{ - l1Network: L1Network - l2Network: Omit + l1Network: L1Network | L2Network + l2Network: L2Network }> => { const l1Provider = new JsonRpcProvider(l1Url) const l2Provider = new JsonRpcProvider(l2Url) - let deploymentData: string + const l1NetworkInfo = await l1Provider.getNetwork() + const l2NetworkInfo = await l2Provider.getNetwork() + + /// get parent chain info + const container = execSync( + 'docker ps --filter "name=sequencer" --format "{{.Names}}"' + ) + .toString() + .trim() + const l2DeploymentData = execSync( + `docker exec ${container} cat /config/deployment.json` + ).toString() + const l2Data = JSON.parse(l2DeploymentData) as { + bridge: string + inbox: string + ['sequencer-inbox']: string + rollup: string + } + + const l1Network: L1Network | L2Network = { + partnerChainID: 1337, + partnerChainIDs: [l2NetworkInfo.chainId], + isArbitrum: true, + confirmPeriodBlocks: 20, + retryableLifetimeSeconds: 7 * 24 * 60 * 60, + nitroGenesisBlock: 0, + nitroGenesisL1Block: 0, + depositTimeout: 900000, + chainID: 412346, + explorerUrl: '', + isCustom: true, + name: 'ArbLocal', + blockTime: 0.25, + ethBridge: { + bridge: l2Data.bridge, + inbox: l2Data.inbox, + outbox: '', + rollup: l2Data.rollup, + sequencerInbox: l2Data['sequencer-inbox'], + }, + tokenBridge: { + l1CustomGateway: '', + l1ERC20Gateway: '', + l1GatewayRouter: '', + l1MultiCall: '', + l1ProxyAdmin: '', + l1Weth: '', + l1WethGateway: '', + + l2CustomGateway: '', + l2ERC20Gateway: '', + l2GatewayRouter: '', + l2Multicall: '', + l2ProxyAdmin: '', + l2Weth: '', + l2WethGateway: '', + }, + } + + /// get L3 info + let deploymentData: string let data = { bridge: '', inbox: '', @@ -242,28 +291,14 @@ export const getLocalNetworks = async ( data.rollup = rollupAddress! } - const rollup = RollupAdminLogic__factory.connect(data.rollup, l1Provider) - const confirmPeriodBlocks = await rollup.confirmPeriodBlocks() - const bridge = Bridge__factory.connect(data.bridge, l1Provider) const outboxAddr = await bridge.allowedOutboxList(0) - const l1NetworkInfo = await l1Provider.getNetwork() - const l2NetworkInfo = await l2Provider.getNetwork() - - const l1Network: L1Network = { - blockTime: 10, - chainID: l1NetworkInfo.chainId, - explorerUrl: '', - isCustom: true, - name: 'EthLocal', - partnerChainIDs: [l2NetworkInfo.chainId], - isArbitrum: false, - } - - const l2Network: Omit = { + const l2Network: L2Network = { + partnerChainID: l1NetworkInfo.chainId, + partnerChainIDs: [], chainID: l2NetworkInfo.chainId, - confirmPeriodBlocks: confirmPeriodBlocks.toNumber(), + confirmPeriodBlocks: 20, ethBridge: { bridge: data.bridge, inbox: data.inbox, @@ -274,12 +309,29 @@ export const getLocalNetworks = async ( explorerUrl: '', isArbitrum: true, isCustom: true, - name: 'ArbLocal', - partnerChainID: l1NetworkInfo.chainId, + blockTime: 0.25, + name: 'OrbitLocal', retryableLifetimeSeconds: 7 * 24 * 60 * 60, nitroGenesisBlock: 0, nitroGenesisL1Block: 0, depositTimeout: 900000, + tokenBridge: { + l1CustomGateway: '', + l1ERC20Gateway: '', + l1GatewayRouter: '', + l1MultiCall: '', + l1ProxyAdmin: '', + l1Weth: '', + l1WethGateway: '', + + l2CustomGateway: '', + l2ERC20Gateway: '', + l2GatewayRouter: '', + l2Multicall: '', + l2ProxyAdmin: '', + l2Weth: '', + l2WethGateway: '', + }, } return { l1Network, From d345b734ea0ba0157979d9d79df2c4cf10c90f92 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 20 Jun 2024 13:09:11 +0200 Subject: [PATCH 19/20] Update e2e test to latest design --- .../tokenbridge/libraries/IFiatToken.sol | 107 ++++++++++++- .../test/IFiatTokenArbitrumOrbitV2_2.sol | 21 --- test-e2e/orbitTokenBridge.ts | 143 +++++++++++++----- 3 files changed, 203 insertions(+), 68 deletions(-) delete mode 100644 contracts/tokenbridge/test/IFiatTokenArbitrumOrbitV2_2.sol diff --git a/contracts/tokenbridge/libraries/IFiatToken.sol b/contracts/tokenbridge/libraries/IFiatToken.sol index 7acd9fcafe..78be6e869c 100644 --- a/contracts/tokenbridge/libraries/IFiatToken.sol +++ b/contracts/tokenbridge/libraries/IFiatToken.sol @@ -4,12 +4,28 @@ pragma solidity >0.6.0 <0.9.0; /** * @title IFiatToken - * @dev Part of the interface that is used in Circle's referent implementation of the USDC + * @dev Interface contains functions from Circle's referent implementation of the USDC * Ref: https://github.com/circlefin/stablecoin-evm * * This interface is used in the L1USDCGateway, L1OrbitUSDCGateway and L2USDCGateway contracts. */ interface IFiatToken { + function allowance(address owner, address spender) external view returns (uint256); + function approve(address spender, uint256 value) external returns (bool); + function authorizationState(address authorizer, bytes32 nonce) external view returns (bool); + function balanceOf(address account) external view returns (uint256); + function blacklist(address _account) external; + function blacklister() external view returns (address); + function burn(uint256 _amount) external; + function cancelAuthorization(address authorizer, bytes32 nonce, uint8 v, bytes32 r, bytes32 s) + external; + function cancelAuthorization(address authorizer, bytes32 nonce, bytes memory signature) + external; + function configureMinter(address minter, uint256 minterAllowedAmount) external returns (bool); + function currency() external view returns (string memory); + function decimals() external view returns (uint8); + function decreaseAllowance(address spender, uint256 decrement) external returns (bool); + function increaseAllowance(address spender, uint256 increment) external returns (bool); function initialize( string memory tokenName, string memory tokenSymbol, @@ -20,11 +36,90 @@ interface IFiatToken { address newBlacklister, address newOwner ) external; - function initializeV2(string calldata newName) external; + function initializeV2(string memory newName) external; function initializeV2_1(address lostAndFound) external; - function initializeV2_2(address[] calldata accountsToBlacklist, string calldata newSymbol) + function initializeV2_2(address[] memory accountsToBlacklist, string memory newSymbol) external; - function configureMinter(address minter, uint256 minterAllowedAmount) external; - function burn(uint256 _amount) external; - function mint(address _to, uint256 _amount) external; + function isBlacklisted(address _account) external view returns (bool); + function isMinter(address account) external view returns (bool); + function masterMinter() external view returns (address); + function mint(address _to, uint256 _amount) external returns (bool); + function minterAllowance(address minter) external view returns (uint256); + function name() external view returns (string memory); + function nonces(address owner) external view returns (uint256); + function owner() external view returns (address); + function pause() external; + function paused() external view returns (bool); + function pauser() external view returns (address); + function permit( + address owner, + address spender, + uint256 value, + uint256 deadline, + bytes memory signature + ) external; + function permit( + address owner, + address spender, + uint256 value, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) external; + function receiveWithAuthorization( + address from, + address to, + uint256 value, + uint256 validAfter, + uint256 validBefore, + bytes32 nonce, + bytes memory signature + ) external; + function receiveWithAuthorization( + address from, + address to, + uint256 value, + uint256 validAfter, + uint256 validBefore, + bytes32 nonce, + uint8 v, + bytes32 r, + bytes32 s + ) external; + function removeMinter(address minter) external returns (bool); + function rescueERC20(address tokenContract, address to, uint256 amount) external; + function rescuer() external view returns (address); + function symbol() external view returns (string memory); + function totalSupply() external view returns (uint256); + function transfer(address to, uint256 value) external returns (bool); + function transferFrom(address from, address to, uint256 value) external returns (bool); + function transferOwnership(address newOwner) external; + function transferWithAuthorization( + address from, + address to, + uint256 value, + uint256 validAfter, + uint256 validBefore, + bytes32 nonce, + bytes memory signature + ) external; + function transferWithAuthorization( + address from, + address to, + uint256 value, + uint256 validAfter, + uint256 validBefore, + bytes32 nonce, + uint8 v, + bytes32 r, + bytes32 s + ) external; + function unBlacklist(address _account) external; + function unpause() external; + function updateBlacklister(address _newBlacklister) external; + function updateMasterMinter(address _newMasterMinter) external; + function updatePauser(address _newPauser) external; + function updateRescuer(address newRescuer) external; + function version() external pure returns (string memory); } diff --git a/contracts/tokenbridge/test/IFiatTokenArbitrumOrbitV2_2.sol b/contracts/tokenbridge/test/IFiatTokenArbitrumOrbitV2_2.sol deleted file mode 100644 index c4b1cce3b7..0000000000 --- a/contracts/tokenbridge/test/IFiatTokenArbitrumOrbitV2_2.sol +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.0; - -interface IFiatTokenArbitrumOrbitV2_2 { - function initialize( - string memory tokenName, - string memory tokenSymbol, - string memory tokenCurrency, - uint8 tokenDecimals, - address newMasterMinter, - address newPauser, - address newBlacklister, - address newOwner - ) external; - function initializeV2(string calldata newName) external; - function initializeV2_1(address lostAndFound) external; - function initializeV2_2(address[] calldata accountsToBlacklist, string calldata newSymbol) - external; - function initializeArbitrumOrbit(address _l2Gateway, address _l1Token) external; - function configureMinter(address minter, uint256 minterAllowedAmount) external; -} diff --git a/test-e2e/orbitTokenBridge.ts b/test-e2e/orbitTokenBridge.ts index a3bdd00ac5..7b683e30f7 100644 --- a/test-e2e/orbitTokenBridge.ts +++ b/test-e2e/orbitTokenBridge.ts @@ -35,11 +35,12 @@ import { TestOrbitCustomTokenL1__factory, TransparentUpgradeableProxy__factory, UpgradeExecutor__factory, - IFiatTokenArbitrumOrbitV22__factory, + IFiatToken__factory, } from '../build/types' import { defaultAbiCoder } from 'ethers/lib/utils' import { BigNumber, Wallet, ethers } from 'ethers' import { exit } from 'process' +import { getNetwork } from '@arbitrum/sdk/dist/lib/dataEntities/networks' const config = { parentUrl: 'http://localhost:8547', @@ -646,7 +647,7 @@ describe('orbitTokenBridge', () => { ).to.be.eq(tokenTotalFeeAmount) }) - it('can upgrade from bridged USDC to native USDC when eth is native token', async function () { + it.only('can upgrade from bridged USDC to native USDC when eth is native token', async function () { /// test applicable only for eth based chains if (nativeToken) { return @@ -691,19 +692,34 @@ describe('orbitTokenBridge', () => { console.log('L2USDCGateway address: ', l2USDCCustomGateway.address) /// create l1 usdc behind proxy - const l1UsdcFactory = await new MockL1Usdc__factory( - deployerL1Wallet - ).deploy() - const l1UsdcLogic = await l1UsdcFactory.deployed() + const l1UsdcLogic = await _deployBridgedUsdcToken(deployerL1Wallet) const tupL1UsdcFactory = await new TransparentUpgradeableProxy__factory( deployerL1Wallet ).deploy(l1UsdcLogic.address, proxyAdmin.address, '0x') const tupL1Usdc = await tupL1UsdcFactory.deployed() - const l1Usdc = MockL1Usdc__factory.connect( + const l1UsdcInit = IFiatToken__factory.connect( tupL1Usdc.address, deployerL1Wallet ) - await (await l1Usdc.initialize()).wait() + const masterMinterL1 = deployerL1Wallet + await ( + await l1UsdcInit.initialize( + 'USDC token', + 'USDC.e', + 'USD', + 6, + masterMinterL1.address, + ethers.Wallet.createRandom().address, + ethers.Wallet.createRandom().address, + deployerL2Wallet.address + ) + ).wait() + await (await l1UsdcInit.initializeV2('USDC')).wait() + await ( + await l1UsdcInit.initializeV2_1(ethers.Wallet.createRandom().address) + ).wait() + await (await l1UsdcInit.initializeV2_2([], 'USDC')).wait() + const l1Usdc = IERC20__factory.connect(l1UsdcInit.address, deployerL1Wallet) console.log('L1 USDC address: ', l1Usdc.address) /// create l2 usdc behind proxy @@ -712,18 +728,18 @@ describe('orbitTokenBridge', () => { deployerL2Wallet ).deploy(l2UsdcLogic.address, proxyAdminL2.address, '0x') const tupL2Usdc = await tupL2UsdcFactory.deployed() - const l2UsdcInit = IFiatTokenArbitrumOrbitV22__factory.connect( + const l2UsdcInit = IFiatToken__factory.connect( tupL2Usdc.address, deployerL2Wallet ) - const masterMinter = deployerL2Wallet + const masterMinterL2 = deployerL2Wallet await ( await l2UsdcInit.initialize( 'USDC token', 'USDC.e', 'USD', 6, - masterMinter.address, + masterMinterL2.address, ethers.Wallet.createRandom().address, ethers.Wallet.createRandom().address, deployerL2Wallet.address @@ -734,21 +750,6 @@ describe('orbitTokenBridge', () => { await l2UsdcInit.initializeV2_1(ethers.Wallet.createRandom().address) ).wait() await (await l2UsdcInit.initializeV2_2([], 'USDC.e')).wait() - await ( - await l2UsdcInit.initializeArbitrumOrbit( - l2USDCCustomGateway.address, - l1Usdc.address - ) - ).wait() - - await ( - await l2UsdcInit - .connect(masterMinter) - .configureMinter( - l2USDCCustomGateway.address, - ethers.constants.MaxUint256 - ) - ).wait() const l2Usdc = IERC20__factory.connect(l2UsdcInit.address, deployerL2Wallet) console.log('L2 USDC address: ', l2Usdc.address) @@ -826,9 +827,38 @@ describe('orbitTokenBridge', () => { ) expect(await l2USDCCustomGateway.withdrawalsPaused()).to.be.eq(false) + /// add minter role with max allowance to L2 gateway + await ( + await l2UsdcInit + .connect(masterMinterL2) + .configureMinter( + l2USDCCustomGateway.address, + ethers.constants.MaxUint256 + ) + ).wait() + expect(await l2UsdcInit.isMinter(l2USDCCustomGateway.address)).to.be.eq( + true + ) + console.log('Minter role with max allowance granted to L2 USDC gateway') + + /// mint some USDC to user + await ( + await l1UsdcInit + .connect(masterMinterL1) + .configureMinter( + masterMinterL1.address, + ethers.utils.parseEther('1000') + ) + ).wait() + await ( + await l1UsdcInit + .connect(masterMinterL1) + .mint(userL1Wallet.address, ethers.utils.parseEther('10')) + ).wait() + console.log('Minted USDC to user') + /// do a deposit const depositAmount = ethers.utils.parseEther('2') - await (await l1Usdc.transfer(userL1Wallet.address, depositAmount)).wait() await ( await l1Usdc .connect(userL1Wallet) @@ -852,17 +882,37 @@ describe('orbitTokenBridge', () => { expect(await l1Usdc.balanceOf(l1USDCCustomGateway.address)).to.be.eq( depositAmount ) + expect(await l2Usdc.totalSupply()).to.be.eq(depositAmount) console.log('Deposited USDC') /// pause deposits await (await l1USDCCustomGateway.pauseDeposits()).wait() expect(await l1USDCCustomGateway.depositsPaused()).to.be.eq(true) + console.log('Deposits paused') - /// pause withdrawals - await (await l2USDCCustomGateway.pauseWithdrawals()).wait() + /// chain owner/circle checks that all pending deposits (all retryables depositing usdc) are executed + + /// pause withdrawals and send L2 supply to L1 + const pauseReceipt = await ( + await l2USDCCustomGateway.pauseWithdrawals() + ).wait() + const l2PauseReceipt = new L2TransactionReceipt(pauseReceipt) + const messages = await l2PauseReceipt.getL2ToL1Messages(userL1Wallet) + const l2ToL1Msg = messages[0] + const timeToWaitMs = 60 * 1000 + await l2ToL1Msg.waitUntilReadyToExecute( + deployerL2Wallet.provider!, + timeToWaitMs + ) + // execute msg on L1 + await (await l2ToL1Msg.execute(deployerL2Wallet.provider!)).wait() + + // check withdrawals are paused and l2 supply is set in l1 gateway expect(await l2USDCCustomGateway.withdrawalsPaused()).to.be.eq(true) + expect(await l1USDCCustomGateway.l2GatewaySupply()).to.be.gt(0) + console.log('Withdrawals paused and L2 supply set in L1 gateway') - /// transfer ownership to circle + /// make circle the burner const circleWallet = ethers.Wallet.createRandom().connect(parentProvider) await ( await deployerL1Wallet.sendTransaction({ @@ -870,20 +920,31 @@ describe('orbitTokenBridge', () => { value: ethers.utils.parseEther('1'), }) ).wait() - - await (await l1Usdc.setOwner(circleWallet.address)).wait() - await (await l1USDCCustomGateway.setOwner(circleWallet.address)).wait() - console.log('L1 USDC and L1 USDC gateway ownership transferred to circle') - - /// circle checks that deposits are paused, all in-flight deposits and withdrawals are processed + await (await l1USDCCustomGateway.setBurner(circleWallet.address)).wait() /// add minter rights to usdc gateway so it can burn USDC await ( - await l1Usdc.connect(circleWallet).addMinter(l1USDCCustomGateway.address) + await l1UsdcInit.configureMinter(l1USDCCustomGateway.address, 0) ).wait() - console.log('Minter rights added to USDC gateway') + console.log('Minter role with 0 allowance added to L1 USDC gateway') - /// burn USDC + /// remove minter role from the L2 gateway + await ( + await l2UsdcInit + .connect(masterMinterL2) + .removeMinter(l2USDCCustomGateway.address) + ).wait() + expect(await l2UsdcInit.isMinter(l2USDCCustomGateway.address)).to.be.eq( + false + ) + console.log('Minter role removed from L2 USDC gateway') + + /// transfer child chain USDC ownership to circle + await (await l2UsdcInit.transferOwnership(circleWallet.address)).wait() + expect(await l2UsdcInit.owner()).to.be.eq(circleWallet.address) + console.log('L2 USDC ownership transferred to circle') + + /// circle burns USDC on L1 await ( await l1USDCCustomGateway.connect(circleWallet).burnLockedUSDC() ).wait() @@ -958,7 +1019,7 @@ describe('orbitTokenBridge', () => { deployerL2Wallet ).deploy(l2UsdcLogic.address, proxyAdminL2.address, '0x') const tupL2Usdc = await tupL2UsdcFactory.deployed() - const l2UsdcInit = IFiatTokenArbitrumOrbitV22__factory.connect( + const l2UsdcInit = IFiatToken__factory.connect( tupL2Usdc.address, deployerL2Wallet ) @@ -1244,7 +1305,7 @@ async function _deployBridgedUsdcToken(deployer: Wallet) { // prepare bridged usdc bytecode const bytecodeWithPlaceholder: string = - '0x60806040526001805460ff60a01b191690556000600b553480156200002357600080fd5b506200002f3362000035565b62000057565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b61508980620000676000396000f3fe608060405234801561001057600080fd5b50600436106103a45760003560e01c80638a6db9c3116101e9578063b7b728991161010f578063dd62ed3e116100ad578063ef55bec61161007c578063ef55bec614611069578063f2fde38b146110c8578063f9f92be4146110ee578063fe575a8714611114576103a4565b8063dd62ed3e14610fa8578063e3ee160e14610fd6578063e5a6b10f14611035578063e94a01021461103d576103a4565b8063cf092995116100e9578063cf09299514610e08578063d505accf14610edf578063d608ea6414610f30578063d916948714610fa0576103a4565b8063b7b7289914610d3d578063bd10243014610df8578063c2eeeebd14610e00576103a4565b8063a0cc6a6811610187578063aa20e1e411610156578063aa20e1e414610c95578063aa271e1a14610cbb578063ad38bf2214610ce1578063b2118a8d14610d07576103a4565b8063a0cc6a6814610c07578063a297ea5e14610c0f578063a457c2d714610c3d578063a9059cbb14610c69576103a4565b80638fa74a0e116101c35780638fa74a0e14610b2457806395d89b4114610b2c5780639fd0506d14610b345780639fd5a6cf14610b3c576103a4565b80638a6db9c314610aca5780638c2a993e14610af05780638da5cb5b14610b1c576103a4565b80633f4ba83a116102ce5780635a049a701161026c5780637ecebe001161023b5780637ecebe00146109bd5780637f2eecc3146109e35780638456cb59146109eb57806388b7ab63146109f3576103a4565b80635a049a70146109225780635c975abb1461096357806370a082311461096b57806374f4f54714610991576103a4565b8063430239b4116102a8578063430239b4146108065780634e44d956146108c857806354fd4d50146108f4578063554bab3c146108fc576103a4565b80633f4ba83a146107b557806340c10f19146107bd57806342966c68146107e9576103a4565b80633092afd51161034657806335d99f351161031557806335d99f35146107555780633644e5151461077957806338a63183146107815780633950935114610789576103a4565b80633092afd51461052a57806330adf81f14610550578063313ce567146105585780633357162b14610576576103a4565b80631a895266116103825780631a8952661461048057806323b872dd146104a85780632ab60045146104de5780632fc81e0914610504576103a4565b806306fdde03146103a9578063095ea7b31461042657806318160ddd14610466575b600080fd5b6103b161113a565b6040805160208082528351818301528351919283929083019185019080838360005b838110156103eb5781810151838201526020016103d3565b50505050905090810190601f1680156104185780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6104526004803603604081101561043c57600080fd5b506001600160a01b0381351690602001356111e6565b604080519115158252519081900360200190f35b61046e61125c565b60408051918252519081900360200190f35b6104a66004803603602081101561049657600080fd5b50356001600160a01b0316611262565b005b610452600480360360608110156104be57600080fd5b506001600160a01b038135811691602081013590911690604001356112eb565b6104a6600480360360208110156104f457600080fd5b50356001600160a01b03166114ec565b6104a66004803603602081101561051a57600080fd5b50356001600160a01b03166115f2565b6104526004803603602081101561054057600080fd5b50356001600160a01b031661163c565b61046e6116e3565b610560611707565b6040805160ff9092168252519081900360200190f35b6104a6600480360361010081101561058d57600080fd5b8101906020810181356401000000008111156105a857600080fd5b8201836020820111156105ba57600080fd5b803590602001918460018302840111640100000000831117156105dc57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929594936020810193503591505064010000000081111561062f57600080fd5b82018360208201111561064157600080fd5b8035906020019184600183028401116401000000008311171561066357600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092959493602081019350359150506401000000008111156106b657600080fd5b8201836020820111156106c857600080fd5b803590602001918460018302840111640100000000831117156106ea57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050813560ff1692505060208101356001600160a01b0390811691604081013582169160608201358116916080013516611710565b61075d61194f565b604080516001600160a01b039092168252519081900360200190f35b61046e61195e565b61075d61196d565b6104526004803603604081101561079f57600080fd5b506001600160a01b03813516906020013561197c565b6104a66119e9565b610452600480360360408110156107d357600080fd5b506001600160a01b038135169060200135611a85565b6104a6600480360360208110156107ff57600080fd5b5035611d68565b6104a66004803603604081101561081c57600080fd5b81019060208101813564010000000081111561083757600080fd5b82018360208201111561084957600080fd5b8035906020019184602083028401116401000000008311171561086b57600080fd5b91939092909160208101903564010000000081111561088957600080fd5b82018360208201111561089b57600080fd5b803590602001918460018302840111640100000000831117156108bd57600080fd5b509092509050611f77565b610452600480360360408110156108de57600080fd5b506001600160a01b0381351690602001356120b1565b6103b16121c7565b6104a66004803603602081101561091257600080fd5b50356001600160a01b03166121fe565b6104a6600480360360a081101561093857600080fd5b506001600160a01b038135169060208101359060ff604082013516906060810135906080013561230a565b61045261237d565b61046e6004803603602081101561098157600080fd5b50356001600160a01b031661238d565b6104a6600480360360408110156109a757600080fd5b506001600160a01b03813516906020013561239e565b61046e600480360360208110156109d357600080fd5b50356001600160a01b0316612419565b61046e612434565b6104a6612458565b6104a6600480360360e0811015610a0957600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359160808201359160a08101359181019060e0810160c0820135640100000000811115610a5557600080fd5b820183602082011115610a6757600080fd5b80359060200191846001830284011164010000000083111715610a8957600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506124fa945050505050565b61046e60048036036020811015610ae057600080fd5b50356001600160a01b03166125ff565b6104a660048036036040811015610b0657600080fd5b506001600160a01b03813516906020013561261a565b61075d612696565b61075d6126a5565b6103b16126ca565b61075d612743565b6104a6600480360360a0811015610b5257600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359181019060a081016080820135640100000000811115610b9257600080fd5b820183602082011115610ba457600080fd5b80359060200191846001830284011164010000000083111715610bc657600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612752945050505050565b61046e6127be565b6104a660048036036040811015610c2557600080fd5b506001600160a01b03813581169160200135166127e2565b61045260048036036040811015610c5357600080fd5b506001600160a01b038135169060200135612958565b61045260048036036040811015610c7f57600080fd5b506001600160a01b0381351690602001356129c5565b6104a660048036036020811015610cab57600080fd5b50356001600160a01b0316612ac9565b61045260048036036020811015610cd157600080fd5b50356001600160a01b0316612bd5565b6104a660048036036020811015610cf757600080fd5b50356001600160a01b0316612bf3565b6104a660048036036060811015610d1d57600080fd5b506001600160a01b03813581169160208101359091169060400135612cff565b6104a660048036036060811015610d5357600080fd5b6001600160a01b0382351691602081013591810190606081016040820135640100000000811115610d8357600080fd5b820183602082011115610d9557600080fd5b80359060200191846001830284011164010000000083111715610db757600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612d5c945050505050565b61075d612dc6565b61075d612dd5565b6104a6600480360360e0811015610e1e57600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359160808201359160a08101359181019060e0810160c0820135640100000000811115610e6a57600080fd5b820183602082011115610e7c57600080fd5b80359060200191846001830284011164010000000083111715610e9e57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612dfa945050505050565b6104a6600480360360e0811015610ef557600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c00135612ef4565b6104a660048036036020811015610f4657600080fd5b810190602081018135640100000000811115610f6157600080fd5b820183602082011115610f7357600080fd5b80359060200191846001830284011164010000000083111715610f9557600080fd5b509092509050612f6b565b61046e613025565b61046e60048036036040811015610fbe57600080fd5b506001600160a01b0381358116916020013516613049565b6104a66004803603610120811015610fed57600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060808101359060a08101359060ff60c0820135169060e0810135906101000135613074565b6103b161317d565b6104526004803603604081101561105357600080fd5b506001600160a01b0381351690602001356131f6565b6104a6600480360361012081101561108057600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060808101359060a08101359060ff60c0820135169060e0810135906101000135613221565b6104a6600480360360208110156110de57600080fd5b50356001600160a01b031661331d565b6104a66004803603602081101561110457600080fd5b50356001600160a01b0316613415565b6104526004803603602081101561112a57600080fd5b50356001600160a01b031661349e565b6004805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156111de5780601f106111b3576101008083540402835291602001916111de565b820191906000526020600020905b8154815290600101906020018083116111c157829003601f168201915b505050505081565b600154600090600160a01b900460ff1615611248576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6112533384846134a9565b50600192915050565b600b5490565b6002546001600160a01b031633146112ab5760405162461bcd60e51b815260040180806020018281038252602c815260200180614d05602c913960400191505060405180910390fd5b6112b481613595565b6040516001600160a01b038216907f117e3210bb9aa7d9baff172026820255c6f6c30ba8999d1c2fd88e2848137c4e90600090a250565b600154600090600160a01b900460ff161561134d576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b33611357816135a0565b156113935760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b8461139d816135a0565b156113d95760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b846113e3816135a0565b1561141f5760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b6001600160a01b0387166000908152600a602090815260408083203384529091529020548511156114815760405162461bcd60e51b8152600401808060200182810382526028815260200180614df56028913960400191505060405180910390fd5b61148c8787876135c1565b6001600160a01b0387166000908152600a602090815260408083203384529091529020546114ba908661370a565b6001600160a01b0388166000908152600a60209081526040808320338452909152902055600193505050509392505050565b6000546001600160a01b0316331461154b576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166115905760405162461bcd60e51b815260040180806020018281038252602a815260200180614c3e602a913960400191505060405180910390fd5b600e80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040517fe475e580d85111348e40d8ca33cfdd74c30fe1655c2d8537a13abc10065ffa5a90600090a250565b60125460ff1660011461160457600080fd5b600061160f30613767565b90508015611622576116223083836135c1565b61162b306137a4565b50506012805460ff19166002179055565b6008546000906001600160a01b031633146116885760405162461bcd60e51b8152600401808060200182810382526029815260200180614cdc6029913960400191505060405180910390fd5b6001600160a01b0382166000818152600c60209081526040808320805460ff19169055600d909152808220829055517fe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb666929190a2506001919050565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60065460ff1681565b600854600160a01b900460ff16156117595760405162461bcd60e51b815260040180806020018281038252602a815260200180614e70602a913960400191505060405180910390fd5b6001600160a01b03841661179e5760405162461bcd60e51b815260040180806020018281038252602f815260200180614da2602f913960400191505060405180910390fd5b6001600160a01b0383166117e35760405162461bcd60e51b8152600401808060200182810382526029815260200180614c156029913960400191505060405180910390fd5b6001600160a01b0382166118285760405162461bcd60e51b815260040180806020018281038252602e815260200180614e1d602e913960400191505060405180910390fd5b6001600160a01b03811661186d5760405162461bcd60e51b8152600401808060200182810382526028815260200180614f5d6028913960400191505060405180910390fd5b87516118809060049060208b01906149cc565b5086516118949060059060208a01906149cc565b5085516118a89060079060208901906149cc565b506006805460ff191660ff8716179055600880547fffffffffffffffffffffffff00000000000000000000000000000000000000009081166001600160a01b038781169190911790925560018054821686841617905560028054909116918416919091179055611917816137af565b5050600880547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16600160a01b179055505050505050565b6008546001600160a01b031681565b60006119686137e9565b905090565b600e546001600160a01b031690565b600154600090600160a01b900460ff16156119de576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6112533384846138de565b6001546001600160a01b03163314611a325760405162461bcd60e51b8152600401808060200182810382526022815260200180614f116022913960400191505060405180910390fd5b600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690556040517f7805862f689e2f13df9f062ff482ad3ad112aca9e0847911ed832e158c525b3390600090a1565b600154600090600160a01b900460ff1615611ae7576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff16611b355760405162461bcd60e51b8152600401808060200182810382526021815260200180614d816021913960400191505060405180910390fd5b33611b3f816135a0565b15611b7b5760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b83611b85816135a0565b15611bc15760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b6001600160a01b038516611c065760405162461bcd60e51b8152600401808060200182810382526023815260200180614baa6023913960400191505060405180910390fd5b60008411611c455760405162461bcd60e51b8152600401808060200182810382526029815260200180614c8d6029913960400191505060405180910390fd5b336000908152600d602052604090205480851115611c945760405162461bcd60e51b815260040180806020018281038252602e815260200180614ee3602e913960400191505060405180910390fd5b600b54611ca1908661391b565b600b55611cc086611cbb87611cb583613767565b9061391b565b61397c565b611cca818661370a565b336000818152600d602090815260409182902093909355805188815290516001600160a01b038a16937fab8530f87dc9b59234c4623bf917212bb2536d647574c8e7e5da92c2ede0c9f8928290030190a36040805186815290516001600160a01b038816916000917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a350600195945050505050565b600154600160a01b900460ff1615611dc7576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff16611e155760405162461bcd60e51b8152600401808060200182810382526021815260200180614d816021913960400191505060405180910390fd5b33611e1f816135a0565b15611e5b5760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b6000611e6633613767565b905060008311611ea75760405162461bcd60e51b8152600401808060200182810382526029815260200180614b816029913960400191505060405180910390fd5b82811015611ee65760405162461bcd60e51b8152600401808060200182810382526026815260200180614d5b6026913960400191505060405180910390fd5b600b54611ef3908461370a565b600b55611f0433611cbb838661370a565b60408051848152905133917fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5919081900360200190a260408051848152905160009133917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a3505050565b60125460ff16600214611f8957600080fd5b611f9560058383614a4a565b5060005b838110156120785760036000868684818110611fb157fe5b602090810292909201356001600160a01b03168352508101919091526040016000205460ff166120125760405162461bcd60e51b815260040180806020018281038252603d815260200180614ace603d913960400191505060405180910390fd5b61203685858381811061202157fe5b905060200201356001600160a01b03166137a4565b6003600086868481811061204657fe5b602090810292909201356001600160a01b0316835250810191909152604001600020805460ff19169055600101611f99565b50612082306137a4565b5050306000908152600360208190526040909120805460ff199081169091556012805490911690911790555050565b600154600090600160a01b900460ff1615612113576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6008546001600160a01b0316331461215c5760405162461bcd60e51b8152600401808060200182810382526029815260200180614cdc6029913960400191505060405180910390fd5b6001600160a01b0383166000818152600c60209081526040808320805460ff19166001179055600d825291829020859055815185815291517f46980fca912ef9bcdbd36877427b6b90e860769f604e89c0e67720cece530d209281900390910190a250600192915050565b60408051808201909152600181527f3200000000000000000000000000000000000000000000000000000000000000602082015290565b6000546001600160a01b0316331461225d576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166122a25760405162461bcd60e51b8152600401808060200182810382526028815260200180614b2e6028913960400191505060405180910390fd5b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691909117918290556040519116907fb80482a293ca2e013eda8683c9bd7fc8347cfdaeea5ede58cba46df502c2a60490600090a250565b600154600160a01b900460ff1615612369576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6123768585858585613a3c565b5050505050565b600154600160a01b900460ff1681565b600061239882613767565b92915050565b6123a66126a5565b6001600160a01b0316336001600160a01b03161461240b576040805162461bcd60e51b815260206004820152600c60248201527f4f4e4c595f474154455741590000000000000000000000000000000000000000604482015290519081900360640190fd5b6124158282613a7c565b5050565b6001600160a01b031660009081526011602052604090205490565b7fd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de881565b6001546001600160a01b031633146124a15760405162461bcd60e51b8152600401808060200182810382526022815260200180614f116022913960400191505060405180910390fd5b600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16600160a01b1790556040517f6985a02210a168e66602d3235cb6db0e70f92b3ba4d376a33c0f3d9434bff62590600090a1565b600154600160a01b900460ff1615612559576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b86612563816135a0565b1561259f5760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b866125a9816135a0565b156125e55760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b6125f489898989898989613c9e565b505050505050505050565b6001600160a01b03166000908152600d602052604090205490565b6126226126a5565b6001600160a01b0316336001600160a01b031614612687576040805162461bcd60e51b815260206004820152600c60248201527f4f4e4c595f474154455741590000000000000000000000000000000000000000604482015290519081900360640190fd5b6126918282611a85565b505050565b6000546001600160a01b031690565b7fdbf6298cab77bb44ebfd5abb25ed2538c2a55f7404c47e83e6531361fba28c245490565b6005805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156111de5780601f106111b3576101008083540402835291602001916111de565b6001546001600160a01b031681565b600154600160a01b900460ff16156127b1576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6123768585858585613d8b565b7f7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a226781565b60125460ff166003146127f457600080fd5b6001600160a01b03821661284f576040805162461bcd60e51b815260206004820152600f60248201527f494e56414c49445f474154455741590000000000000000000000000000000000604482015290519081900360640190fd5b6001600160a01b0381166128aa576040805162461bcd60e51b815260206004820152601360248201527f494e56414c49445f434f554e5445525041525400000000000000000000000000604482015290519081900360640190fd5b60006128b46126a5565b6001600160a01b03161461290f576040805162461bcd60e51b815260206004820152600c60248201527f414c52454144595f494e49540000000000000000000000000000000000000000604482015290519081900360640190fd5b7fdbf6298cab77bb44ebfd5abb25ed2538c2a55f7404c47e83e6531361fba28c24919091557f54352c0d7cc5793352a36344bfdcdcf68ba6258544ce1aed71f60a74d882c19155565b600154600090600160a01b900460ff16156129ba576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b611253338484614001565b600154600090600160a01b900460ff1615612a27576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b33612a31816135a0565b15612a6d5760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b83612a77816135a0565b15612ab35760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b612abe3386866135c1565b506001949350505050565b6000546001600160a01b03163314612b28576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b038116612b6d5760405162461bcd60e51b815260040180806020018281038252602f815260200180614da2602f913960400191505060405180910390fd5b600880547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691909117918290556040519116907fdb66dfa9c6b8f5226fe9aac7e51897ae8ee94ac31dc70bb6c9900b2574b707e690600090a250565b6001600160a01b03166000908152600c602052604090205460ff1690565b6000546001600160a01b03163314612c52576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b038116612c975760405162461bcd60e51b8152600401808060200182810382526032815260200180614fb36032913960400191505060405180910390fd5b600280547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691909117918290556040519116907fc67398012c111ce95ecb7429b933096c977380ee6c421175a71a4a4c6c88c06e90600090a250565b600e546001600160a01b03163314612d485760405162461bcd60e51b8152600401808060200182810382526024815260200180614dd16024913960400191505060405180910390fd5b6126916001600160a01b0384168383614050565b600154600160a01b900460ff1615612dbb576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6126918383836140d0565b6002546001600160a01b031681565b7f54352c0d7cc5793352a36344bfdcdcf68ba6258544ce1aed71f60a74d882c1915490565b600154600160a01b900460ff1615612e59576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b86612e63816135a0565b15612e9f5760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b86612ea9816135a0565b15612ee55760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b6125f4898989898989896141a2565b600154600160a01b900460ff1615612f53576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b612f6287878787878787614233565b50505050505050565b600854600160a01b900460ff168015612f87575060125460ff16155b612f9057600080fd5b612f9c60048383614a4a565b5061301182828080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600181527f3200000000000000000000000000000000000000000000000000000000000000602082015291506142759050565b600f5550506012805460ff19166001179055565b7f158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a159742981565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205490565b600154600160a01b900460ff16156130d3576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b886130dd816135a0565b156131195760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b88613123816135a0565b1561315f5760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b6131708b8b8b8b8b8b8b8b8b61428b565b5050505050505050505050565b6007805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156111de5780601f106111b3576101008083540402835291602001916111de565b6001600160a01b03919091166000908152601060209081526040808320938352929052205460ff1690565b600154600160a01b900460ff1615613280576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b8861328a816135a0565b156132c65760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b886132d0816135a0565b1561330c5760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b6131708b8b8b8b8b8b8b8b8b6142cf565b6000546001600160a01b0316331461337c576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166133c15760405162461bcd60e51b8152600401808060200182810382526026815260200180614bcd6026913960400191505060405180910390fd5b600054604080516001600160a01b039283168152918316602083015280517f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09281900390910190a1613412816137af565b50565b6002546001600160a01b0316331461345e5760405162461bcd60e51b815260040180806020018281038252602c815260200180614d05602c913960400191505060405180910390fd5b613467816137a4565b6040516001600160a01b038216907fffa4e6181777692565cf28528fc88fd1516ea86b56da075235fa575af6a4b85590600090a250565b6000612398826135a0565b6001600160a01b0383166134ee5760405162461bcd60e51b8152600401808060200182810382526024815260200180614ebf6024913960400191505060405180910390fd5b6001600160a01b0382166135335760405162461bcd60e51b8152600401808060200182810382526022815260200180614bf36022913960400191505060405180910390fd5b6001600160a01b038084166000818152600a6020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b613412816000614313565b6001600160a01b031660009081526009602052604090205460ff1c60011490565b6001600160a01b0383166136065760405162461bcd60e51b8152600401808060200182810382526025815260200180614e9a6025913960400191505060405180910390fd5b6001600160a01b03821661364b5760405162461bcd60e51b8152600401808060200182810382526023815260200180614b0b6023913960400191505060405180910390fd5b61365483613767565b8111156136925760405162461bcd60e51b8152600401808060200182810382526026815260200180614cb66026913960400191505060405180910390fd5b6136a983611cbb836136a387613767565b9061370a565b6136ba82611cbb83611cb586613767565b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b600082821115613761576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6001600160a01b03166000908152600960205260409020547f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690565b613412816001614313565b600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6004805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815260009361196893919290918301828280156138965780601f1061386b57610100808354040283529160200191613896565b820191906000526020600020905b81548152906001019060200180831161387957829003601f168201915b50505050506040518060400160405280600181526020017f32000000000000000000000000000000000000000000000000000000000000008152506138d9614382565b614386565b6001600160a01b038084166000908152600a60209081526040808320938616835292905220546126919084908490613916908561391b565b6134a9565b600082820183811015613975576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8111156139db5760405162461bcd60e51b815260040180806020018281038252602a815260200180614d31602a913960400191505060405180910390fd5b6139e4826135a0565b15613a205760405162461bcd60e51b8152600401808060200182810382526025815260200180614c686025913960400191505060405180910390fd5b6001600160a01b03909116600090815260096020526040902055565b6123768585848487604051602001808481526020018381526020018260ff1660f81b815260010193505050506040516020818303038152906040526140d0565b600154600160a01b900460ff1615613adb576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff16613b295760405162461bcd60e51b8152600401808060200182810382526021815260200180614d816021913960400191505060405180910390fd5b81613b33816135a0565b15613b6f5760405162461bcd60e51b8152600401808060200182810382526025815260200180614fe56025913960400191505060405180910390fd5b6000613b7a84613767565b905060008311613bbb5760405162461bcd60e51b8152600401808060200182810382526029815260200180614b816029913960400191505060405180910390fd5b82811015613bfa5760405162461bcd60e51b8152600401808060200182810382526026815260200180614d5b6026913960400191505060405180910390fd5b600b54613c07908461370a565b600b55613c1884611cbb838661370a565b6040805184815290516001600160a01b038616917fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5919081900360200190a26040805184815290516000916001600160a01b038716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a350505050565b6001600160a01b0386163314613ce55760405162461bcd60e51b8152600401808060200182810382526025815260200180614e4b6025913960400191505060405180910390fd5b613cf1878386866143fa565b604080517fd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de86020808301919091526001600160a01b03808b1683850152891660608301526080820188905260a0820187905260c0820186905260e0808301869052835180840390910181526101009092019092528051910120613d7690889083614486565b613d8087836145dd565b612f628787876135c1565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821480613db95750428210155b613e0a576040805162461bcd60e51b815260206004820152601e60248201527f46696174546f6b656e56323a207065726d697420697320657870697265640000604482015290519081900360640190fd5b6000613ea5613e176137e9565b6001600160a01b0380891660008181526011602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98184015280840194909452938b166060840152608083018a905260a083019390935260c08083018990528151808403909101815260e090920190528051910120614637565b905073__$715109b5d747ea58b675c6ea3f0dba8c60$__636ccea6528783856040518463ffffffff1660e01b815260040180846001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015613f25578181015183820152602001613f0d565b50505050905090810190601f168015613f525780820380516001836020036101000a031916815260200191505b5094505050505060206040518083038186803b158015613f7157600080fd5b505af4158015613f85573d6000803e3d6000fd5b505050506040513d6020811015613f9b57600080fd5b5051613fee576040805162461bcd60e51b815260206004820152601a60248201527f454950323631323a20696e76616c6964207369676e6174757265000000000000604482015290519081900360640190fd5b613ff98686866134a9565b505050505050565b61269183836139168460405180606001604052806025815260200161502f602591396001600160a01b03808a166000908152600a60209081526040808320938c16835292905220549190614671565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052612691908490614708565b6140da83836147b9565b614147837f158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a159742960001b858560405160200180848152602001836001600160a01b0316815260200182815260200193505050506040516020818303038152906040528051906020012083614486565b6001600160a01b0383166000818152601060209081526040808320868452909152808220805460ff19166001179055518492917f1cdd46ff242716cdaa72d159d339a485b3438398348d68f09d7c8c0a59353d8191a3505050565b6141ae878386866143fa565b604080517f7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a22676020808301919091526001600160a01b03808b1683850152891660608301526080820188905260a0820187905260c0820186905260e0808301869052835180840390910181526101009092019092528051910120613d7690889083614486565b612f6287878787868689604051602001808481526020018381526020018260ff1660f81b81526001019350505050604051602081830303815290604052613d8b565b600046614283848483614386565b949350505050565b6125f489898989898988888b604051602001808481526020018381526020018260ff1660f81b815260010193505050506040516020818303038152906040526141a2565b6125f489898989898988888b604051602001808481526020018381526020018260ff1660f81b81526001019350505050604051602081830303815290604052613c9e565b806143265761432182613767565b614362565b6001600160a01b0382166000908152600960205260409020547f8000000000000000000000000000000000000000000000000000000000000000175b6001600160a01b0390921660009081526009602052604090209190915550565b4690565b8251602093840120825192840192909220604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8187015280820194909452606084019190915260808301919091523060a0808401919091528151808403909101815260c09092019052805191012090565b8142116144385760405162461bcd60e51b815260040180806020018281038252602b815260200180614b56602b913960400191505060405180910390fd5b8042106144765760405162461bcd60e51b815260040180806020018281038252602581526020018061500a6025913960400191505060405180910390fd5b61448084846147b9565b50505050565b73__$715109b5d747ea58b675c6ea3f0dba8c60$__636ccea652846144b26144ac6137e9565b86614637565b846040518463ffffffff1660e01b815260040180846001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b838110156145145781810151838201526020016144fc565b50505050905090810190601f1680156145415780820380516001836020036101000a031916815260200191505b5094505050505060206040518083038186803b15801561456057600080fd5b505af4158015614574573d6000803e3d6000fd5b505050506040513d602081101561458a57600080fd5b5051612691576040805162461bcd60e51b815260206004820152601e60248201527f46696174546f6b656e56323a20696e76616c6964207369676e61747572650000604482015290519081900360640190fd5b6001600160a01b0382166000818152601060209081526040808320858452909152808220805460ff19166001179055518392917f98de503528ee59b575ef0c0a2576a82497bfc029a5685b209e9ec333479b10a591a35050565b6040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b600081848411156147005760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156146c55781810151838201526020016146ad565b50505050905090810190601f1680156146f25780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b606061475d826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661481c9092919063ffffffff16565b8051909150156126915780806020019051602081101561477c57600080fd5b50516126915760405162461bcd60e51b815260040180806020018281038252602a815260200180614f33602a913960400191505060405180910390fd5b6001600160a01b038216600090815260106020908152604080832084845290915290205460ff16156124155760405162461bcd60e51b815260040180806020018281038252602e815260200180614f85602e913960400191505060405180910390fd5b606061428384846000858561483085614960565b614881576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b602083106148de57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016148a1565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114614940576040519150601f19603f3d011682016040523d82523d6000602084013e614945565b606091505b5091509150614955828286614966565b979650505050505050565b3b151590565b60608315614975575081613975565b8251156149855782518084602001fd5b60405162461bcd60e51b81526020600482018181528451602484015284518593919283926044019190850190808383600083156146c55781810151838201526020016146ad565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10614a0d57805160ff1916838001178555614a3a565b82800160010185558215614a3a579182015b82811115614a3a578251825591602001919060010190614a1f565b50614a46929150614ab8565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10614a8b5782800160ff19823516178555614a3a565b82800160010185558215614a3a579182015b82811115614a3a578235825591602001919060010190614a9d565b5b80821115614a465760008155600101614ab956fe46696174546f6b656e56325f323a20426c61636b6c697374696e672070726576696f75736c7920756e626c61636b6c6973746564206163636f756e742145524332303a207472616e7366657220746f20746865207a65726f20616464726573735061757361626c653a206e65772070617573657220697320746865207a65726f206164647265737346696174546f6b656e56323a20617574686f72697a6174696f6e206973206e6f74207965742076616c696446696174546f6b656e3a206275726e20616d6f756e74206e6f742067726561746572207468616e203046696174546f6b656e3a206d696e7420746f20746865207a65726f20616464726573734f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737346696174546f6b656e3a206e65772070617573657220697320746865207a65726f2061646472657373526573637561626c653a206e6577207265736375657220697320746865207a65726f206164647265737346696174546f6b656e56325f323a204163636f756e7420697320626c61636b6c697374656446696174546f6b656e3a206d696e7420616d6f756e74206e6f742067726561746572207468616e203045524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636546696174546f6b656e3a2063616c6c6572206973206e6f7420746865206d61737465724d696e746572426c61636b6c69737461626c653a2063616c6c6572206973206e6f742074686520626c61636b6c697374657246696174546f6b656e56325f323a2042616c616e636520657863656564732028325e323535202d20312946696174546f6b656e3a206275726e20616d6f756e7420657863656564732062616c616e636546696174546f6b656e3a2063616c6c6572206973206e6f742061206d696e74657246696174546f6b656e3a206e6577206d61737465724d696e74657220697320746865207a65726f2061646472657373526573637561626c653a2063616c6c6572206973206e6f7420746865207265736375657245524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636546696174546f6b656e3a206e657720626c61636b6c697374657220697320746865207a65726f206164647265737346696174546f6b656e56323a2063616c6c6572206d7573742062652074686520706179656546696174546f6b656e3a20636f6e747261637420697320616c726561647920696e697469616c697a656445524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737346696174546f6b656e3a206d696e7420616d6f756e742065786365656473206d696e746572416c6c6f77616e63655061757361626c653a2063616c6c6572206973206e6f7420746865207061757365725361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656446696174546f6b656e3a206e6577206f776e657220697320746865207a65726f206164647265737346696174546f6b656e56323a20617574686f72697a6174696f6e2069732075736564206f722063616e63656c6564426c61636b6c69737461626c653a206e657720626c61636b6c697374657220697320746865207a65726f2061646472657373426c61636b6c69737461626c653a206163636f756e7420697320626c61636b6c697374656446696174546f6b656e56323a20617574686f72697a6174696f6e206973206578706972656445524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122069f43cc6c29d58063264d46f6f667d8af0c0a5209b8e811c80c4675b7ac594b364736f6c634300060c0033' + '0x60806040526001805460ff60a01b191690556000600b553480156200002357600080fd5b506200002f3362000035565b62000057565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b614aec80620000676000396000f3fe608060405234801561001057600080fd5b506004361061036d5760003560e01c80638456cb59116101d3578063b7b7289911610104578063e3ee160e116100a2578063ef55bec61161007c578063ef55bec614610f9c578063f2fde38b14610ffb578063f9f92be414611021578063fe575a87146110475761036d565b8063e3ee160e14610f09578063e5a6b10f14610f68578063e94a010214610f705761036d565b8063d505accf116100de578063d505accf14610e12578063d608ea6414610e63578063d916948714610ed3578063dd62ed3e14610edb5761036d565b8063b7b7289914610c78578063bd10243014610d33578063cf09299514610d3b5761036d565b8063a0cc6a6811610171578063aa20e1e41161014b578063aa20e1e414610bd0578063aa271e1a14610bf6578063ad38bf2214610c1c578063b2118a8d14610c425761036d565b8063a0cc6a6814610b70578063a457c2d714610b78578063a9059cbb14610ba45761036d565b80638da5cb5b116101ad5780638da5cb5b14610a8d57806395d89b4114610a955780639fd0506d14610a9d5780639fd5a6cf14610aa55761036d565b80638456cb591461098857806388b7ab63146109905780638a6db9c314610a675761036d565b806338a63183116102ad57806354fd4d501161024b5780635c975abb116102255780635c975abb1461092c57806370a08231146109345780637ecebe001461095a5780637f2eecc3146109805761036d565b806354fd4d50146108bd578063554bab3c146108c55780635a049a70146108eb5761036d565b806340c10f191161028757806340c10f191461078657806342966c68146107b2578063430239b4146107cf5780634e44d956146108915761036d565b806338a631831461074a57806339509351146107525780633f4ba83a1461077e5761036d565b80632fc81e091161031a578063313ce567116102f4578063313ce567146105215780633357162b1461053f57806335d99f351461071e5780633644e515146107425761036d565b80632fc81e09146104cd5780633092afd5146104f357806330adf81f146105195761036d565b80631a8952661161034b5780631a8952661461044957806323b872dd146104715780632ab60045146104a75761036d565b806306fdde0314610372578063095ea7b3146103ef57806318160ddd1461042f575b600080fd5b61037a61106d565b6040805160208082528351818301528351919283929083019185019080838360005b838110156103b457818101518382015260200161039c565b50505050905090810190601f1680156103e15780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61041b6004803603604081101561040557600080fd5b506001600160a01b038135169060200135611119565b604080519115158252519081900360200190f35b61043761118f565b60408051918252519081900360200190f35b61046f6004803603602081101561045f57600080fd5b50356001600160a01b0316611195565b005b61041b6004803603606081101561048757600080fd5b506001600160a01b0381358116916020810135909116906040013561121e565b61046f600480360360208110156104bd57600080fd5b50356001600160a01b031661141f565b61046f600480360360208110156104e357600080fd5b50356001600160a01b0316611525565b61041b6004803603602081101561050957600080fd5b50356001600160a01b031661156f565b610437611616565b61052961163a565b6040805160ff9092168252519081900360200190f35b61046f600480360361010081101561055657600080fd5b81019060208101813564010000000081111561057157600080fd5b82018360208201111561058357600080fd5b803590602001918460018302840111640100000000831117156105a557600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092959493602081019350359150506401000000008111156105f857600080fd5b82018360208201111561060a57600080fd5b8035906020019184600183028401116401000000008311171561062c57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929594936020810193503591505064010000000081111561067f57600080fd5b82018360208201111561069157600080fd5b803590602001918460018302840111640100000000831117156106b357600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050813560ff1692505060208101356001600160a01b0390811691604081013582169160608201358116916080013516611643565b610726611882565b604080516001600160a01b039092168252519081900360200190f35b610437611891565b6107266118a0565b61041b6004803603604081101561076857600080fd5b506001600160a01b0381351690602001356118af565b61046f61191c565b61041b6004803603604081101561079c57600080fd5b506001600160a01b0381351690602001356119b8565b61046f600480360360208110156107c857600080fd5b5035611c9b565b61046f600480360360408110156107e557600080fd5b81019060208101813564010000000081111561080057600080fd5b82018360208201111561081257600080fd5b8035906020019184602083028401116401000000008311171561083457600080fd5b91939092909160208101903564010000000081111561085257600080fd5b82018360208201111561086457600080fd5b8035906020019184600183028401116401000000008311171561088657600080fd5b509092509050611eaa565b61041b600480360360408110156108a757600080fd5b506001600160a01b038135169060200135611fe4565b61037a6120fa565b61046f600480360360208110156108db57600080fd5b50356001600160a01b0316612131565b61046f600480360360a081101561090157600080fd5b506001600160a01b038135169060208101359060ff604082013516906060810135906080013561223d565b61041b6122b0565b6104376004803603602081101561094a57600080fd5b50356001600160a01b03166122c0565b6104376004803603602081101561097057600080fd5b50356001600160a01b03166122d1565b6104376122ec565b61046f612310565b61046f600480360360e08110156109a657600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359160808201359160a08101359181019060e0810160c08201356401000000008111156109f257600080fd5b820183602082011115610a0457600080fd5b80359060200191846001830284011164010000000083111715610a2657600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506123b2945050505050565b61043760048036036020811015610a7d57600080fd5b50356001600160a01b03166124b7565b6107266124d2565b61037a6124e1565b61072661255a565b61046f600480360360a0811015610abb57600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359181019060a081016080820135640100000000811115610afb57600080fd5b820183602082011115610b0d57600080fd5b80359060200191846001830284011164010000000083111715610b2f57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612569945050505050565b6104376125d5565b61041b60048036036040811015610b8e57600080fd5b506001600160a01b0381351690602001356125f9565b61041b60048036036040811015610bba57600080fd5b506001600160a01b038135169060200135612666565b61046f60048036036020811015610be657600080fd5b50356001600160a01b031661276a565b61041b60048036036020811015610c0c57600080fd5b50356001600160a01b0316612876565b61046f60048036036020811015610c3257600080fd5b50356001600160a01b0316612894565b61046f60048036036060811015610c5857600080fd5b506001600160a01b038135811691602081013590911690604001356129a0565b61046f60048036036060811015610c8e57600080fd5b6001600160a01b0382351691602081013591810190606081016040820135640100000000811115610cbe57600080fd5b820183602082011115610cd057600080fd5b80359060200191846001830284011164010000000083111715610cf257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612a02945050505050565b610726612a6c565b61046f600480360360e0811015610d5157600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359160808201359160a08101359181019060e0810160c0820135640100000000811115610d9d57600080fd5b820183602082011115610daf57600080fd5b80359060200191846001830284011164010000000083111715610dd157600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612a7b945050505050565b61046f600480360360e0811015610e2857600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c00135612b75565b61046f60048036036020811015610e7957600080fd5b810190602081018135640100000000811115610e9457600080fd5b820183602082011115610ea657600080fd5b80359060200191846001830284011164010000000083111715610ec857600080fd5b509092509050612bec565b610437612ca6565b61043760048036036040811015610ef157600080fd5b506001600160a01b0381358116916020013516612cca565b61046f6004803603610120811015610f2057600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060808101359060a08101359060ff60c0820135169060e0810135906101000135612cf5565b61037a612dfe565b61041b60048036036040811015610f8657600080fd5b506001600160a01b038135169060200135612e77565b61046f6004803603610120811015610fb357600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060808101359060a08101359060ff60c0820135169060e0810135906101000135612ea2565b61046f6004803603602081101561101157600080fd5b50356001600160a01b0316612f9e565b61046f6004803603602081101561103757600080fd5b50356001600160a01b0316613096565b61041b6004803603602081101561105d57600080fd5b50356001600160a01b031661311f565b6004805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156111115780601f106110e657610100808354040283529160200191611111565b820191906000526020600020905b8154815290600101906020018083116110f457829003601f168201915b505050505081565b600154600090600160a01b900460ff161561117b576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b61118633848461312a565b50600192915050565b600b5490565b6002546001600160a01b031633146111de5760405162461bcd60e51b815260040180806020018281038252602c815260200180614768602c913960400191505060405180910390fd5b6111e781613216565b6040516001600160a01b038216907f117e3210bb9aa7d9baff172026820255c6f6c30ba8999d1c2fd88e2848137c4e90600090a250565b600154600090600160a01b900460ff1615611280576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b3361128a81613221565b156112c65760405162461bcd60e51b8152600401808060200182810382526025815260200180614a486025913960400191505060405180910390fd5b846112d081613221565b1561130c5760405162461bcd60e51b8152600401808060200182810382526025815260200180614a486025913960400191505060405180910390fd5b8461131681613221565b156113525760405162461bcd60e51b8152600401808060200182810382526025815260200180614a486025913960400191505060405180910390fd5b6001600160a01b0387166000908152600a602090815260408083203384529091529020548511156113b45760405162461bcd60e51b81526004018080602001828103825260288152602001806148586028913960400191505060405180910390fd5b6113bf878787613242565b6001600160a01b0387166000908152600a602090815260408083203384529091529020546113ed908661338b565b6001600160a01b0388166000908152600a60209081526040808320338452909152902055600193505050509392505050565b6000546001600160a01b0316331461147e576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166114c35760405162461bcd60e51b815260040180806020018281038252602a8152602001806146a1602a913960400191505060405180910390fd5b600e80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040517fe475e580d85111348e40d8ca33cfdd74c30fe1655c2d8537a13abc10065ffa5a90600090a250565b60125460ff1660011461153757600080fd5b6000611542306133e8565b9050801561155557611555308383613242565b61155e30613425565b50506012805460ff19166002179055565b6008546000906001600160a01b031633146115bb5760405162461bcd60e51b815260040180806020018281038252602981526020018061473f6029913960400191505060405180910390fd5b6001600160a01b0382166000818152600c60209081526040808320805460ff19169055600d909152808220829055517fe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb666929190a2506001919050565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60065460ff1681565b600854600160a01b900460ff161561168c5760405162461bcd60e51b815260040180806020018281038252602a8152602001806148d3602a913960400191505060405180910390fd5b6001600160a01b0384166116d15760405162461bcd60e51b815260040180806020018281038252602f815260200180614805602f913960400191505060405180910390fd5b6001600160a01b0383166117165760405162461bcd60e51b81526004018080602001828103825260298152602001806146786029913960400191505060405180910390fd5b6001600160a01b03821661175b5760405162461bcd60e51b815260040180806020018281038252602e815260200180614880602e913960400191505060405180910390fd5b6001600160a01b0381166117a05760405162461bcd60e51b81526004018080602001828103825260288152602001806149c06028913960400191505060405180910390fd5b87516117b39060049060208b019061442f565b5086516117c79060059060208a019061442f565b5085516117db90600790602089019061442f565b506006805460ff191660ff8716179055600880547fffffffffffffffffffffffff00000000000000000000000000000000000000009081166001600160a01b03878116919091179092556001805482168684161790556002805490911691841691909117905561184a81613430565b5050600880547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16600160a01b179055505050505050565b6008546001600160a01b031681565b600061189b61346a565b905090565b600e546001600160a01b031690565b600154600090600160a01b900460ff1615611911576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b61118633848461355f565b6001546001600160a01b031633146119655760405162461bcd60e51b81526004018080602001828103825260228152602001806149746022913960400191505060405180910390fd5b600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690556040517f7805862f689e2f13df9f062ff482ad3ad112aca9e0847911ed832e158c525b3390600090a1565b600154600090600160a01b900460ff1615611a1a576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff16611a685760405162461bcd60e51b81526004018080602001828103825260218152602001806147e46021913960400191505060405180910390fd5b33611a7281613221565b15611aae5760405162461bcd60e51b8152600401808060200182810382526025815260200180614a486025913960400191505060405180910390fd5b83611ab881613221565b15611af45760405162461bcd60e51b8152600401808060200182810382526025815260200180614a486025913960400191505060405180910390fd5b6001600160a01b038516611b395760405162461bcd60e51b815260040180806020018281038252602381526020018061460d6023913960400191505060405180910390fd5b60008411611b785760405162461bcd60e51b81526004018080602001828103825260298152602001806146f06029913960400191505060405180910390fd5b336000908152600d602052604090205480851115611bc75760405162461bcd60e51b815260040180806020018281038252602e815260200180614946602e913960400191505060405180910390fd5b600b54611bd4908661359c565b600b55611bf386611bee87611be8836133e8565b9061359c565b6135fd565b611bfd818661338b565b336000818152600d602090815260409182902093909355805188815290516001600160a01b038a16937fab8530f87dc9b59234c4623bf917212bb2536d647574c8e7e5da92c2ede0c9f8928290030190a36040805186815290516001600160a01b038816916000917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a350600195945050505050565b600154600160a01b900460ff1615611cfa576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336000908152600c602052604090205460ff16611d485760405162461bcd60e51b81526004018080602001828103825260218152602001806147e46021913960400191505060405180910390fd5b33611d5281613221565b15611d8e5760405162461bcd60e51b8152600401808060200182810382526025815260200180614a486025913960400191505060405180910390fd5b6000611d99336133e8565b905060008311611dda5760405162461bcd60e51b81526004018080602001828103825260298152602001806145e46029913960400191505060405180910390fd5b82811015611e195760405162461bcd60e51b81526004018080602001828103825260268152602001806147be6026913960400191505060405180910390fd5b600b54611e26908461338b565b600b55611e3733611bee838661338b565b60408051848152905133917fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5919081900360200190a260408051848152905160009133917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a3505050565b60125460ff16600214611ebc57600080fd5b611ec8600583836144ad565b5060005b83811015611fab5760036000868684818110611ee457fe5b602090810292909201356001600160a01b03168352508101919091526040016000205460ff16611f455760405162461bcd60e51b815260040180806020018281038252603d815260200180614531603d913960400191505060405180910390fd5b611f69858583818110611f5457fe5b905060200201356001600160a01b0316613425565b60036000868684818110611f7957fe5b602090810292909201356001600160a01b0316835250810191909152604001600020805460ff19169055600101611ecc565b50611fb530613425565b5050306000908152600360208190526040909120805460ff199081169091556012805490911690911790555050565b600154600090600160a01b900460ff1615612046576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6008546001600160a01b0316331461208f5760405162461bcd60e51b815260040180806020018281038252602981526020018061473f6029913960400191505060405180910390fd5b6001600160a01b0383166000818152600c60209081526040808320805460ff19166001179055600d825291829020859055815185815291517f46980fca912ef9bcdbd36877427b6b90e860769f604e89c0e67720cece530d209281900390910190a250600192915050565b60408051808201909152600181527f3200000000000000000000000000000000000000000000000000000000000000602082015290565b6000546001600160a01b03163314612190576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166121d55760405162461bcd60e51b81526004018080602001828103825260288152602001806145916028913960400191505060405180910390fd5b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691909117918290556040519116907fb80482a293ca2e013eda8683c9bd7fc8347cfdaeea5ede58cba46df502c2a60490600090a250565b600154600160a01b900460ff161561229c576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6122a985858585856136bd565b5050505050565b600154600160a01b900460ff1681565b60006122cb826133e8565b92915050565b6001600160a01b031660009081526011602052604090205490565b7fd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de881565b6001546001600160a01b031633146123595760405162461bcd60e51b81526004018080602001828103825260228152602001806149746022913960400191505060405180910390fd5b600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16600160a01b1790556040517f6985a02210a168e66602d3235cb6db0e70f92b3ba4d376a33c0f3d9434bff62590600090a1565b600154600160a01b900460ff1615612411576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b8661241b81613221565b156124575760405162461bcd60e51b8152600401808060200182810382526025815260200180614a486025913960400191505060405180910390fd5b8661246181613221565b1561249d5760405162461bcd60e51b8152600401808060200182810382526025815260200180614a486025913960400191505060405180910390fd5b6124ac898989898989896136fd565b505050505050505050565b6001600160a01b03166000908152600d602052604090205490565b6000546001600160a01b031690565b6005805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156111115780601f106110e657610100808354040283529160200191611111565b6001546001600160a01b031681565b600154600160a01b900460ff16156125c8576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6122a985858585856137ea565b7f7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a226781565b600154600090600160a01b900460ff161561265b576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b611186338484613a60565b600154600090600160a01b900460ff16156126c8576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b336126d281613221565b1561270e5760405162461bcd60e51b8152600401808060200182810382526025815260200180614a486025913960400191505060405180910390fd5b8361271881613221565b156127545760405162461bcd60e51b8152600401808060200182810382526025815260200180614a486025913960400191505060405180910390fd5b61275f338686613242565b506001949350505050565b6000546001600160a01b031633146127c9576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b03811661280e5760405162461bcd60e51b815260040180806020018281038252602f815260200180614805602f913960400191505060405180910390fd5b600880547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691909117918290556040519116907fdb66dfa9c6b8f5226fe9aac7e51897ae8ee94ac31dc70bb6c9900b2574b707e690600090a250565b6001600160a01b03166000908152600c602052604090205460ff1690565b6000546001600160a01b031633146128f3576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166129385760405162461bcd60e51b8152600401808060200182810382526032815260200180614a166032913960400191505060405180910390fd5b600280547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691909117918290556040519116907fc67398012c111ce95ecb7429b933096c977380ee6c421175a71a4a4c6c88c06e90600090a250565b600e546001600160a01b031633146129e95760405162461bcd60e51b81526004018080602001828103825260248152602001806148346024913960400191505060405180910390fd5b6129fd6001600160a01b0384168383613aaf565b505050565b600154600160a01b900460ff1615612a61576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6129fd838383613b2f565b6002546001600160a01b031681565b600154600160a01b900460ff1615612ada576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b86612ae481613221565b15612b205760405162461bcd60e51b8152600401808060200182810382526025815260200180614a486025913960400191505060405180910390fd5b86612b2a81613221565b15612b665760405162461bcd60e51b8152600401808060200182810382526025815260200180614a486025913960400191505060405180910390fd5b6124ac89898989898989613c01565b600154600160a01b900460ff1615612bd4576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b612be387878787878787613c92565b50505050505050565b600854600160a01b900460ff168015612c08575060125460ff16155b612c1157600080fd5b612c1d600483836144ad565b50612c9282828080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600181527f320000000000000000000000000000000000000000000000000000000000000060208201529150613cd49050565b600f5550506012805460ff19166001179055565b7f158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a159742981565b6001600160a01b039182166000908152600a6020908152604080832093909416825291909152205490565b600154600160a01b900460ff1615612d54576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b88612d5e81613221565b15612d9a5760405162461bcd60e51b8152600401808060200182810382526025815260200180614a486025913960400191505060405180910390fd5b88612da481613221565b15612de05760405162461bcd60e51b8152600401808060200182810382526025815260200180614a486025913960400191505060405180910390fd5b612df18b8b8b8b8b8b8b8b8b613cea565b5050505050505050505050565b6007805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156111115780601f106110e657610100808354040283529160200191611111565b6001600160a01b03919091166000908152601060209081526040808320938352929052205460ff1690565b600154600160a01b900460ff1615612f01576040805162461bcd60e51b815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b88612f0b81613221565b15612f475760405162461bcd60e51b8152600401808060200182810382526025815260200180614a486025913960400191505060405180910390fd5b88612f5181613221565b15612f8d5760405162461bcd60e51b8152600401808060200182810382526025815260200180614a486025913960400191505060405180910390fd5b612df18b8b8b8b8b8b8b8b8b613d2e565b6000546001600160a01b03163314612ffd576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166130425760405162461bcd60e51b81526004018080602001828103825260268152602001806146306026913960400191505060405180910390fd5b600054604080516001600160a01b039283168152918316602083015280517f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09281900390910190a161309381613430565b50565b6002546001600160a01b031633146130df5760405162461bcd60e51b815260040180806020018281038252602c815260200180614768602c913960400191505060405180910390fd5b6130e881613425565b6040516001600160a01b038216907fffa4e6181777692565cf28528fc88fd1516ea86b56da075235fa575af6a4b85590600090a250565b60006122cb82613221565b6001600160a01b03831661316f5760405162461bcd60e51b81526004018080602001828103825260248152602001806149226024913960400191505060405180910390fd5b6001600160a01b0382166131b45760405162461bcd60e51b81526004018080602001828103825260228152602001806146566022913960400191505060405180910390fd5b6001600160a01b038084166000818152600a6020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b613093816000613d72565b6001600160a01b031660009081526009602052604090205460ff1c60011490565b6001600160a01b0383166132875760405162461bcd60e51b81526004018080602001828103825260258152602001806148fd6025913960400191505060405180910390fd5b6001600160a01b0382166132cc5760405162461bcd60e51b815260040180806020018281038252602381526020018061456e6023913960400191505060405180910390fd5b6132d5836133e8565b8111156133135760405162461bcd60e51b81526004018080602001828103825260268152602001806147196026913960400191505060405180910390fd5b61332a83611bee83613324876133e8565b9061338b565b61333b82611bee83611be8866133e8565b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6000828211156133e2576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6001600160a01b03166000908152600960205260409020547f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690565b613093816001613d72565b600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6004805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815260009361189b93919290918301828280156135175780601f106134ec57610100808354040283529160200191613517565b820191906000526020600020905b8154815290600101906020018083116134fa57829003601f168201915b50505050506040518060400160405280600181526020017f320000000000000000000000000000000000000000000000000000000000000081525061355a613de1565b613de5565b6001600160a01b038084166000908152600a60209081526040808320938616835292905220546129fd9084908490613597908561359c565b61312a565b6000828201838110156135f6576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81111561365c5760405162461bcd60e51b815260040180806020018281038252602a815260200180614794602a913960400191505060405180910390fd5b61366582613221565b156136a15760405162461bcd60e51b81526004018080602001828103825260258152602001806146cb6025913960400191505060405180910390fd5b6001600160a01b03909116600090815260096020526040902055565b6122a98585848487604051602001808481526020018381526020018260ff1660f81b81526001019350505050604051602081830303815290604052613b2f565b6001600160a01b03861633146137445760405162461bcd60e51b81526004018080602001828103825260258152602001806148ae6025913960400191505060405180910390fd5b61375087838686613e59565b604080517fd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de86020808301919091526001600160a01b03808b1683850152891660608301526080820188905260a0820187905260c0820186905260e08083018690528351808403909101815261010090920190925280519101206137d590889083613ee5565b6137df878361403c565b612be3878787613242565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214806138185750428210155b613869576040805162461bcd60e51b815260206004820152601e60248201527f46696174546f6b656e56323a207065726d697420697320657870697265640000604482015290519081900360640190fd5b600061390461387661346a565b6001600160a01b0380891660008181526011602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98184015280840194909452938b166060840152608083018a905260a083019390935260c08083018990528151808403909101815260e090920190528051910120614096565b905073__$715109b5d747ea58b675c6ea3f0dba8c60$__636ccea6528783856040518463ffffffff1660e01b815260040180846001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561398457818101518382015260200161396c565b50505050905090810190601f1680156139b15780820380516001836020036101000a031916815260200191505b5094505050505060206040518083038186803b1580156139d057600080fd5b505af41580156139e4573d6000803e3d6000fd5b505050506040513d60208110156139fa57600080fd5b5051613a4d576040805162461bcd60e51b815260206004820152601a60248201527f454950323631323a20696e76616c6964207369676e6174757265000000000000604482015290519081900360640190fd5b613a5886868661312a565b505050505050565b6129fd838361359784604051806060016040528060258152602001614a92602591396001600160a01b03808a166000908152600a60209081526040808320938c168352929052205491906140d0565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790526129fd908490614167565b613b398383614218565b613ba6837f158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a159742960001b858560405160200180848152602001836001600160a01b0316815260200182815260200193505050506040516020818303038152906040528051906020012083613ee5565b6001600160a01b0383166000818152601060209081526040808320868452909152808220805460ff19166001179055518492917f1cdd46ff242716cdaa72d159d339a485b3438398348d68f09d7c8c0a59353d8191a3505050565b613c0d87838686613e59565b604080517f7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a22676020808301919091526001600160a01b03808b1683850152891660608301526080820188905260a0820187905260c0820186905260e08083018690528351808403909101815261010090920190925280519101206137d590889083613ee5565b612be387878787868689604051602001808481526020018381526020018260ff1660f81b815260010193505050506040516020818303038152906040526137ea565b600046613ce2848483613de5565b949350505050565b6124ac89898989898988888b604051602001808481526020018381526020018260ff1660f81b81526001019350505050604051602081830303815290604052613c01565b6124ac89898989898988888b604051602001808481526020018381526020018260ff1660f81b815260010193505050506040516020818303038152906040526136fd565b80613d8557613d80826133e8565b613dc1565b6001600160a01b0382166000908152600960205260409020547f8000000000000000000000000000000000000000000000000000000000000000175b6001600160a01b0390921660009081526009602052604090209190915550565b4690565b8251602093840120825192840192909220604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8187015280820194909452606084019190915260808301919091523060a0808401919091528151808403909101815260c09092019052805191012090565b814211613e975760405162461bcd60e51b815260040180806020018281038252602b8152602001806145b9602b913960400191505060405180910390fd5b804210613ed55760405162461bcd60e51b8152600401808060200182810382526025815260200180614a6d6025913960400191505060405180910390fd5b613edf8484614218565b50505050565b73__$715109b5d747ea58b675c6ea3f0dba8c60$__636ccea65284613f11613f0b61346a565b86614096565b846040518463ffffffff1660e01b815260040180846001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015613f73578181015183820152602001613f5b565b50505050905090810190601f168015613fa05780820380516001836020036101000a031916815260200191505b5094505050505060206040518083038186803b158015613fbf57600080fd5b505af4158015613fd3573d6000803e3d6000fd5b505050506040513d6020811015613fe957600080fd5b50516129fd576040805162461bcd60e51b815260206004820152601e60248201527f46696174546f6b656e56323a20696e76616c6964207369676e61747572650000604482015290519081900360640190fd5b6001600160a01b0382166000818152601060209081526040808320858452909152808220805460ff19166001179055518392917f98de503528ee59b575ef0c0a2576a82497bfc029a5685b209e9ec333479b10a591a35050565b6040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b6000818484111561415f5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561412457818101518382015260200161410c565b50505050905090810190601f1680156141515780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b60606141bc826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661427f9092919063ffffffff16565b8051909150156129fd578080602001905160208110156141db57600080fd5b50516129fd5760405162461bcd60e51b815260040180806020018281038252602a815260200180614996602a913960400191505060405180910390fd5b6001600160a01b038216600090815260106020908152604080832084845290915290205460ff161561427b5760405162461bcd60e51b815260040180806020018281038252602e8152602001806149e8602e913960400191505060405180910390fd5b5050565b6060613ce2848460008585614293856143c3565b6142e4576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b6020831061434157805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101614304565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d80600081146143a3576040519150601f19603f3d011682016040523d82523d6000602084013e6143a8565b606091505b50915091506143b88282866143c9565b979650505050505050565b3b151590565b606083156143d85750816135f6565b8251156143e85782518084602001fd5b60405162461bcd60e51b815260206004820181815284516024840152845185939192839260440191908501908083836000831561412457818101518382015260200161410c565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061447057805160ff191683800117855561449d565b8280016001018555821561449d579182015b8281111561449d578251825591602001919060010190614482565b506144a992915061451b565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106144ee5782800160ff1982351617855561449d565b8280016001018555821561449d579182015b8281111561449d578235825591602001919060010190614500565b5b808211156144a9576000815560010161451c56fe46696174546f6b656e56325f323a20426c61636b6c697374696e672070726576696f75736c7920756e626c61636b6c6973746564206163636f756e742145524332303a207472616e7366657220746f20746865207a65726f20616464726573735061757361626c653a206e65772070617573657220697320746865207a65726f206164647265737346696174546f6b656e56323a20617574686f72697a6174696f6e206973206e6f74207965742076616c696446696174546f6b656e3a206275726e20616d6f756e74206e6f742067726561746572207468616e203046696174546f6b656e3a206d696e7420746f20746865207a65726f20616464726573734f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737346696174546f6b656e3a206e65772070617573657220697320746865207a65726f2061646472657373526573637561626c653a206e6577207265736375657220697320746865207a65726f206164647265737346696174546f6b656e56325f323a204163636f756e7420697320626c61636b6c697374656446696174546f6b656e3a206d696e7420616d6f756e74206e6f742067726561746572207468616e203045524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636546696174546f6b656e3a2063616c6c6572206973206e6f7420746865206d61737465724d696e746572426c61636b6c69737461626c653a2063616c6c6572206973206e6f742074686520626c61636b6c697374657246696174546f6b656e56325f323a2042616c616e636520657863656564732028325e323535202d20312946696174546f6b656e3a206275726e20616d6f756e7420657863656564732062616c616e636546696174546f6b656e3a2063616c6c6572206973206e6f742061206d696e74657246696174546f6b656e3a206e6577206d61737465724d696e74657220697320746865207a65726f2061646472657373526573637561626c653a2063616c6c6572206973206e6f7420746865207265736375657245524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636546696174546f6b656e3a206e657720626c61636b6c697374657220697320746865207a65726f206164647265737346696174546f6b656e56323a2063616c6c6572206d7573742062652074686520706179656546696174546f6b656e3a20636f6e747261637420697320616c726561647920696e697469616c697a656445524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737346696174546f6b656e3a206d696e7420616d6f756e742065786365656473206d696e746572416c6c6f77616e63655061757361626c653a2063616c6c6572206973206e6f7420746865207061757365725361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656446696174546f6b656e3a206e6577206f776e657220697320746865207a65726f206164647265737346696174546f6b656e56323a20617574686f72697a6174696f6e2069732075736564206f722063616e63656c6564426c61636b6c69737461626c653a206e657720626c61636b6c697374657220697320746865207a65726f2061646472657373426c61636b6c69737461626c653a206163636f756e7420697320626c61636b6c697374656446696174546f6b656e56323a20617574686f72697a6174696f6e206973206578706972656445524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa26469706673582212206b5e166c9bb86d4031d11482d2bd231c0f948b4d47fe27594c561c1db6a6c61364736f6c634300060c0033' const placeholder = '__$715109b5d747ea58b675c6ea3f0dba8c60$__' const libAddressStripped = sigCheckerLib.address.replace(/^0x/, '') From 9a33cc09cf3b8c92c5f047c8143ea12288c097a1 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 20 Jun 2024 13:27:42 +0200 Subject: [PATCH 20/20] Update e2e test for fee token chains --- test-e2e/orbitTokenBridge.ts | 134 +++++++++++++++++++++++++---------- 1 file changed, 97 insertions(+), 37 deletions(-) diff --git a/test-e2e/orbitTokenBridge.ts b/test-e2e/orbitTokenBridge.ts index 7b683e30f7..c6cca14185 100644 --- a/test-e2e/orbitTokenBridge.ts +++ b/test-e2e/orbitTokenBridge.ts @@ -647,7 +647,7 @@ describe('orbitTokenBridge', () => { ).to.be.eq(tokenTotalFeeAmount) }) - it.only('can upgrade from bridged USDC to native USDC when eth is native token', async function () { + it('can upgrade from bridged USDC to native USDC when eth is native token', async function () { /// test applicable only for eth based chains if (nativeToken) { return @@ -998,19 +998,34 @@ describe('orbitTokenBridge', () => { console.log('L2USDCGateway address: ', l2USDCCustomGateway.address) /// create l1 usdc behind proxy - const l1UsdcFactory = await new MockL1Usdc__factory( - deployerL1Wallet - ).deploy() - const l1UsdcLogic = await l1UsdcFactory.deployed() + const l1UsdcLogic = await _deployBridgedUsdcToken(deployerL1Wallet) const tupL1UsdcFactory = await new TransparentUpgradeableProxy__factory( deployerL1Wallet ).deploy(l1UsdcLogic.address, proxyAdmin.address, '0x') const tupL1Usdc = await tupL1UsdcFactory.deployed() - const l1Usdc = MockL1Usdc__factory.connect( + const l1UsdcInit = IFiatToken__factory.connect( tupL1Usdc.address, deployerL1Wallet ) - await (await l1Usdc.initialize()).wait() + const masterMinterL1 = deployerL1Wallet + await ( + await l1UsdcInit.initialize( + 'USDC token', + 'USDC.e', + 'USD', + 6, + masterMinterL1.address, + ethers.Wallet.createRandom().address, + ethers.Wallet.createRandom().address, + deployerL2Wallet.address + ) + ).wait() + await (await l1UsdcInit.initializeV2('USDC')).wait() + await ( + await l1UsdcInit.initializeV2_1(ethers.Wallet.createRandom().address) + ).wait() + await (await l1UsdcInit.initializeV2_2([], 'USDC')).wait() + const l1Usdc = IERC20__factory.connect(l1UsdcInit.address, deployerL1Wallet) console.log('L1 USDC address: ', l1Usdc.address) /// create l2 usdc behind proxy @@ -1023,14 +1038,14 @@ describe('orbitTokenBridge', () => { tupL2Usdc.address, deployerL2Wallet ) - const masterMinter = deployerL2Wallet + const masterMinterL2 = deployerL2Wallet await ( await l2UsdcInit.initialize( 'USDC token', 'USDC.e', 'USD', 6, - masterMinter.address, + masterMinterL2.address, ethers.Wallet.createRandom().address, ethers.Wallet.createRandom().address, deployerL2Wallet.address @@ -1041,20 +1056,6 @@ describe('orbitTokenBridge', () => { await l2UsdcInit.initializeV2_1(ethers.Wallet.createRandom().address) ).wait() await (await l2UsdcInit.initializeV2_2([], 'USDC.e')).wait() - await ( - await l2UsdcInit.initializeArbitrumOrbit( - l2USDCCustomGateway.address, - l1Usdc.address - ) - ).wait() - await ( - await l2UsdcInit - .connect(masterMinter) - .configureMinter( - l2USDCCustomGateway.address, - ethers.constants.MaxUint256 - ) - ).wait() const l2Usdc = IERC20__factory.connect(l2UsdcInit.address, deployerL2Wallet) console.log('L2 USDC address: ', l2Usdc.address) @@ -1115,7 +1116,6 @@ describe('orbitTokenBridge', () => { ] ) const rollupOwner = new Wallet(LOCALHOST_L3_OWNER_KEY, parentProvider) - // approve fee amount console.log('Approving fee amount') await ( @@ -1148,9 +1148,38 @@ describe('orbitTokenBridge', () => { ) expect(await l2USDCCustomGateway.withdrawalsPaused()).to.be.eq(false) + /// add minter role with max allowance to L2 gateway + await ( + await l2UsdcInit + .connect(masterMinterL2) + .configureMinter( + l2USDCCustomGateway.address, + ethers.constants.MaxUint256 + ) + ).wait() + expect(await l2UsdcInit.isMinter(l2USDCCustomGateway.address)).to.be.eq( + true + ) + console.log('Minter role with max allowance granted to L2 USDC gateway') + + /// mint some USDC to user + await ( + await l1UsdcInit + .connect(masterMinterL1) + .configureMinter( + masterMinterL1.address, + ethers.utils.parseEther('1000') + ) + ).wait() + await ( + await l1UsdcInit + .connect(masterMinterL1) + .mint(userL1Wallet.address, ethers.utils.parseEther('10')) + ).wait() + console.log('Minted USDC to user') + /// do a deposit const depositAmount = ethers.utils.parseEther('2') - await (await l1Usdc.transfer(userL1Wallet.address, depositAmount)).wait() await ( await l1Usdc .connect(userL1Wallet) @@ -1183,17 +1212,37 @@ describe('orbitTokenBridge', () => { expect(await l1Usdc.balanceOf(l1USDCCustomGateway.address)).to.be.eq( depositAmount ) + expect(await l2Usdc.totalSupply()).to.be.eq(depositAmount) console.log('Deposited USDC') /// pause deposits await (await l1USDCCustomGateway.pauseDeposits()).wait() expect(await l1USDCCustomGateway.depositsPaused()).to.be.eq(true) + console.log('Deposits paused') + + /// chain owner/circle checks that all pending deposits (all retryables depositing usdc) are executed + + /// pause withdrawals and send L2 supply to L1 + const pauseReceipt = await ( + await l2USDCCustomGateway.pauseWithdrawals() + ).wait() + const l2PauseReceipt = new L2TransactionReceipt(pauseReceipt) + const messages = await l2PauseReceipt.getL2ToL1Messages(userL1Wallet) + const l2ToL1Msg = messages[0] + const timeToWaitMs = 60 * 1000 + await l2ToL1Msg.waitUntilReadyToExecute( + deployerL2Wallet.provider!, + timeToWaitMs + ) + // execute msg on L1 + await (await l2ToL1Msg.execute(deployerL2Wallet.provider!)).wait() - /// pause withdrawals - await (await l2USDCCustomGateway.pauseWithdrawals()).wait() + // check withdrawals are paused and l2 supply is set in l1 gateway expect(await l2USDCCustomGateway.withdrawalsPaused()).to.be.eq(true) + expect(await l1USDCCustomGateway.l2GatewaySupply()).to.be.gt(0) + console.log('Withdrawals paused and L2 supply set in L1 gateway') - /// transfer ownership to circle + /// make circle the burner const circleWallet = ethers.Wallet.createRandom().connect(parentProvider) await ( await deployerL1Wallet.sendTransaction({ @@ -1201,20 +1250,31 @@ describe('orbitTokenBridge', () => { value: ethers.utils.parseEther('1'), }) ).wait() - - await (await l1Usdc.setOwner(circleWallet.address)).wait() - await (await l1USDCCustomGateway.setOwner(circleWallet.address)).wait() - console.log('L1 USDC and L1 USDC gateway ownership transferred to circle') - - /// circle checks that deposits are paused, all in-flight deposits and withdrawals are processed + await (await l1USDCCustomGateway.setBurner(circleWallet.address)).wait() /// add minter rights to usdc gateway so it can burn USDC await ( - await l1Usdc.connect(circleWallet).addMinter(l1USDCCustomGateway.address) + await l1UsdcInit.configureMinter(l1USDCCustomGateway.address, 0) + ).wait() + console.log('Minter role with 0 allowance added to L1 USDC gateway') + + /// remove minter role from the L2 gateway + await ( + await l2UsdcInit + .connect(masterMinterL2) + .removeMinter(l2USDCCustomGateway.address) ).wait() - console.log('Minter rights added to USDC gateway') + expect(await l2UsdcInit.isMinter(l2USDCCustomGateway.address)).to.be.eq( + false + ) + console.log('Minter role removed from L2 USDC gateway') - /// burn USDC + /// transfer child chain USDC ownership to circle + await (await l2UsdcInit.transferOwnership(circleWallet.address)).wait() + expect(await l2UsdcInit.owner()).to.be.eq(circleWallet.address) + console.log('L2 USDC ownership transferred to circle') + + /// circle burns USDC on L1 await ( await l1USDCCustomGateway.connect(circleWallet).burnLockedUSDC() ).wait()