Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- NerveMultiSigWalletIII
- Optimization enabled
- true
- Compiler version
- v0.5.17+commit.d19bba13
- Optimization runs
- 200
- EVM Version
- default
- Verified at
- 2023-02-15T08:01:34.815796Z
Constructor Arguments
00000000000000000000000000000000000000000000000000000000000008ae00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000003000000000000000000000000d87f2ad3ef011817319fd25454fc186ca71b3b560000000000000000000000000eb9e4427a0af1fa457230bef3481d028488363e000000000000000000000000d6946039519bccc0b302f89493bec60f4f0b4610
Contract source code
/** *Submitted for verification at BscScan.com on 2021-12-17 */ pragma solidity ^0.5.5; /** * @dev Interface of the ERC20 standard as defined in the EIP. Does not include * the optional functions; to access them see {ERC20Detailed}. */ 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); } /** * @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 ERC20;` 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, mapping(address => uint8) storage bugERC20s) internal { callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value), bugERC20s); } function safeTransferFrom(IERC20 token, address from, address to, uint256 value, mapping(address => uint8) storage bugERC20s) internal { callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value), bugERC20s); } /** * @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, mapping(address => uint8) storage bugERC20s) 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. // A Solidity high level call has three parts: // 1. The target address is checked to verify it contains contract code // 2. The call itself is made, and success asserted // 3. The return value is decoded, which in turn checks the size of the returned data. // solhint-disable-next-line max-line-length require(address(token).isContract(), "SafeERC20: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = address(token).call(data); require(success, "SafeERC20: low-level call failed"); if (bugERC20s[address(token)] != 0) { return; } 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"); } } } // Part: ReentrancyGuard /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor () internal { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and make it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } } /** * @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, 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) { return sub(a, b, "SafeMath: subtraction overflow"); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. * * _Available since v2.4.0._ */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } /** * @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) { // 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 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts 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) { return div(a, b, "SafeMath: division by zero"); } /** * @dev Returns the integer division of two unsigned integers. Reverts with custom message 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. * * _Available since v2.4.0._ */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { // Solidity only automatically asserts when dividing by 0 require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts 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) { return mod(a, b, "SafeMath: modulo by zero"); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message 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. * * _Available since v2.4.0._ */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } } /** * @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) { // According to EIP-1052, 0x0 is the value returned for not-yet created accounts // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned // for accounts without code, i.e. `keccak256('')` bytes32 codehash; bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; // solhint-disable-next-line no-inline-assembly assembly { codehash := extcodehash(account) } return (codehash != accountHash && codehash != 0x0); } /** * @dev Converts an `address` into `address payable`. Note that this is * simply a type cast: the actual underlying value is not changed. * * _Available since v2.4.0._ */ function toPayable(address account) internal pure returns (address payable) { return address(uint160(account)); } /** * @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]. * * _Available since v2.4.0._ */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); // solhint-disable-next-line avoid-call-value (bool success, ) = recipient.call.value(amount)(""); require(success, "Address: unable to send value, recipient may have reverted"); } } library BytesLib { function concat( bytes memory _preBytes, bytes memory _postBytes ) internal pure returns (bytes memory) { bytes memory tempBytes; assembly { // Get a location of some free memory and store it in tempBytes as // Solidity does for memory variables. tempBytes := mload(0x40) // Store the length of the first bytes array at the beginning of // the memory for tempBytes. let length := mload(_preBytes) mstore(tempBytes, length) // Maintain a memory counter for the current write location in the // temp bytes array by adding the 32 bytes for the array length to // the starting location. let mc := add(tempBytes, 0x20) // Stop copying when the memory counter reaches the length of the // first bytes array. let end := add(mc, length) for { // Initialize a copy counter to the start of the _preBytes data, // 32 bytes into its memory. let cc := add(_preBytes, 0x20) } lt(mc, end) { // Increase both counters by 32 bytes each iteration. mc := add(mc, 0x20) cc := add(cc, 0x20) } { // Write the _preBytes data into the tempBytes memory 32 bytes // at a time. mstore(mc, mload(cc)) } // Add the length of _postBytes to the current length of tempBytes // and store it as the new length in the first 32 bytes of the // tempBytes memory. length := mload(_postBytes) mstore(tempBytes, add(length, mload(tempBytes))) // Move the memory counter back from a multiple of 0x20 to the // actual end of the _preBytes data. mc := end // Stop copying when the memory counter reaches the new combined // length of the arrays. end := add(mc, length) for { let cc := add(_postBytes, 0x20) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { mstore(mc, mload(cc)) } // Update the free-memory pointer by padding our last write location // to 32 bytes: add 31 bytes to the end of tempBytes to move to the // next 32 byte block, then round down to the nearest multiple of // 32. If the sum of the length of the two arrays is zero then add // one before rounding down to leave a blank 32 bytes (the length block with 0). mstore(0x40, and( add(add(end, iszero(add(length, mload(_preBytes)))), 31), not(31) // Round down to the nearest 32 bytes. )) } return tempBytes; } function concatStorage(bytes storage _preBytes, bytes memory _postBytes) internal { assembly { // Read the first 32 bytes of _preBytes storage, which is the length // of the array. (We don't need to use the offset into the slot // because arrays use the entire slot.) let fslot := sload(_preBytes_slot) // Arrays of 31 bytes or less have an even value in their slot, // while longer arrays have an odd value. The actual length is // the slot divided by two for odd values, and the lowest order // byte divided by two for even values. // If the slot is even, bitwise and the slot with 255 and divide by // two to get the length. If the slot is odd, bitwise and the slot // with -1 and divide by two. let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2) let mlength := mload(_postBytes) let newlength := add(slength, mlength) // slength can contain both the length and contents of the array // if length < 32 bytes so let's prepare for that // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage switch add(lt(slength, 32), lt(newlength, 32)) case 2 { // Since the new array still fits in the slot, we just need to // update the contents of the slot. // uint256(bytes_storage) = uint256(bytes_storage) + uint256(bytes_memory) + new_length sstore( _preBytes_slot, // all the modifications to the slot are inside this // next block add( // we can just add to the slot contents because the // bytes we want to change are the LSBs fslot, add( mul( div( // load the bytes from memory mload(add(_postBytes, 0x20)), // zero all bytes to the right exp(0x100, sub(32, mlength)) ), // and now shift left the number of bytes to // leave space for the length in the slot exp(0x100, sub(32, newlength)) ), // increase length by the double of the memory // bytes length mul(mlength, 2) ) ) ) } case 1 { // The stored value fits in the slot, but the combined value // will exceed it. // get the keccak hash to get the contents of the array mstore(0x0, _preBytes_slot) let sc := add(keccak256(0x0, 0x20), div(slength, 32)) // save new length sstore(_preBytes_slot, add(mul(newlength, 2), 1)) // The contents of the _postBytes array start 32 bytes into // the structure. Our first read should obtain the `submod` // bytes that can fit into the unused space in the last word // of the stored array. To get this, we read 32 bytes starting // from `submod`, so the data we read overlaps with the array // contents by `submod` bytes. Masking the lowest-order // `submod` bytes allows us to add that value directly to the // stored value. let submod := sub(32, slength) let mc := add(_postBytes, submod) let end := add(_postBytes, mlength) let mask := sub(exp(0x100, submod), 1) sstore( sc, add( and( fslot, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00 ), and(mload(mc), mask) ) ) for { mc := add(mc, 0x20) sc := add(sc, 1) } lt(mc, end) { sc := add(sc, 1) mc := add(mc, 0x20) } { sstore(sc, mload(mc)) } mask := exp(0x100, sub(mc, end)) sstore(sc, mul(div(mload(mc), mask), mask)) } default { // get the keccak hash to get the contents of the array mstore(0x0, _preBytes_slot) // Start copying to the last used word of the stored array. let sc := add(keccak256(0x0, 0x20), div(slength, 32)) // save new length sstore(_preBytes_slot, add(mul(newlength, 2), 1)) // Copy over the first `submod` bytes of the new data as in // case 1 above. let slengthmod := mod(slength, 32) let mlengthmod := mod(mlength, 32) let submod := sub(32, slengthmod) let mc := add(_postBytes, submod) let end := add(_postBytes, mlength) let mask := sub(exp(0x100, submod), 1) sstore(sc, add(sload(sc), and(mload(mc), mask))) for { sc := add(sc, 1) mc := add(mc, 0x20) } lt(mc, end) { sc := add(sc, 1) mc := add(mc, 0x20) } { sstore(sc, mload(mc)) } mask := exp(0x100, sub(mc, end)) sstore(sc, mul(div(mload(mc), mask), mask)) } } } function slice( bytes memory _bytes, uint _start, uint _length ) internal pure returns (bytes memory) { require(_bytes.length >= (_start + _length)); bytes memory tempBytes; assembly { switch iszero(_length) case 0 { // Get a location of some free memory and store it in tempBytes as // Solidity does for memory variables. tempBytes := mload(0x40) // The first word of the slice result is potentially a partial // word read from the original array. To read it, we calculate // the length of that partial word and start copying that many // bytes into the array. The first word we copy will start with // data we don't care about, but the last `lengthmod` bytes will // land at the beginning of the contents of the new array. When // we're done copying, we overwrite the full first word with // the actual length of the slice. let lengthmod := and(_length, 31) // The multiplication in the next line is necessary // because when slicing multiples of 32 bytes (lengthmod == 0) // the following copy loop was copying the origin's length // and then ending prematurely not copying everything it should. let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod))) let end := add(mc, _length) for { // The multiplication in the next line has the same exact purpose // as the one above. let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { mstore(mc, mload(cc)) } mstore(tempBytes, _length) //update free-memory pointer //allocating the array padded to 32 bytes like the compiler does now mstore(0x40, and(add(mc, 31), not(31))) } //if we want a zero-length slice let's just return a zero-length array default { tempBytes := mload(0x40) mstore(0x40, add(tempBytes, 0x20)) } } return tempBytes; } function toAddress(bytes memory _bytes, uint _start) internal pure returns (address) { require(_bytes.length >= (_start + 20)); address tempAddress; assembly { tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000) } return tempAddress; } function toUint8(bytes memory _bytes, uint _start) internal pure returns (uint8) { require(_bytes.length >= (_start + 1)); uint8 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x1), _start)) } return tempUint; } function toUint16(bytes memory _bytes, uint _start) internal pure returns (uint16) { require(_bytes.length >= (_start + 2)); uint16 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x2), _start)) } return tempUint; } function toUint32(bytes memory _bytes, uint _start) internal pure returns (uint32) { require(_bytes.length >= (_start + 4)); uint32 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x4), _start)) } return tempUint; } function toUint64(bytes memory _bytes, uint _start) internal pure returns (uint64) { require(_bytes.length >= (_start + 8)); uint64 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x8), _start)) } return tempUint; } function toUint96(bytes memory _bytes, uint _start) internal pure returns (uint96) { require(_bytes.length >= (_start + 12)); uint96 tempUint; assembly { tempUint := mload(add(add(_bytes, 0xc), _start)) } return tempUint; } function toUint128(bytes memory _bytes, uint _start) internal pure returns (uint128) { require(_bytes.length >= (_start + 16)); uint128 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x10), _start)) } return tempUint; } function toUint(bytes memory _bytes, uint _start) internal pure returns (uint256) { require(_bytes.length >= (_start + 32)); uint256 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x20), _start)) } return tempUint; } function toBytes32(bytes memory _bytes, uint _start) internal pure returns (bytes32) { require(_bytes.length >= (_start + 32)); bytes32 tempBytes32; assembly { tempBytes32 := mload(add(add(_bytes, 0x20), _start)) } return tempBytes32; } function equal(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) { bool success = true; assembly { let length := mload(_preBytes) // if lengths don't match the arrays are not equal switch eq(length, mload(_postBytes)) case 1 { // cb is a circuit breaker in the for loop since there's // no said feature for inline assembly loops // cb = 1 - don't breaker // cb = 0 - break let cb := 1 let mc := add(_preBytes, 0x20) let end := add(mc, length) for { let cc := add(_postBytes, 0x20) // the next line is the loop condition: // while(uint(mc < end) + cb == 2) } eq(add(lt(mc, end), cb), 2) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { // if any of these checks fails then arrays are not equal if iszero(eq(mload(mc), mload(cc))) { // unsuccess: success := 0 cb := 0 } } } default { // unsuccess: success := 0 } } return success; } function equalStorage( bytes storage _preBytes, bytes memory _postBytes ) internal view returns (bool) { bool success = true; assembly { // we know _preBytes_offset is 0 let fslot := sload(_preBytes_slot) // Decode the length of the stored array like in concatStorage(). let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2) let mlength := mload(_postBytes) // if lengths don't match the arrays are not equal switch eq(slength, mlength) case 1 { // slength can contain both the length and contents of the array // if length < 32 bytes so let's prepare for that // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage if iszero(iszero(slength)) { switch lt(slength, 32) case 1 { // blank the last byte which is the length fslot := mul(div(fslot, 0x100), 0x100) if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) { // unsuccess: success := 0 } } default { // cb is a circuit breaker in the for loop since there's // no said feature for inline assembly loops // cb = 1 - don't breaker // cb = 0 - break let cb := 1 // get the keccak hash to get the contents of the array mstore(0x0, _preBytes_slot) let sc := keccak256(0x0, 0x20) let mc := add(_postBytes, 0x20) let end := add(mc, mlength) // the next line is the loop condition: // while(uint(mc < end) + cb == 2) for {} eq(add(lt(mc, end), cb), 2) { sc := add(sc, 1) mc := add(mc, 0x20) } { if iszero(eq(sload(sc), mload(mc))) { // unsuccess: success := 0 cb := 0 } } } } } default { // unsuccess: success := 0 } } return success; } } interface IERC20Minter { function mint(address to, uint256 amount) external; function burn(uint256 amount) external; function replaceMinter(address newMinter) external; } contract NerveMultiSigWalletIII is ReentrancyGuard { using Address for address; using SafeERC20 for IERC20; using SafeMath for uint256; using BytesLib for bytes; modifier isOwner{ require(owner == msg.sender, "Only owner can execute it"); _; } modifier isManager{ require(managers[msg.sender] == 1, "Only manager can execute it"); _; } bool public upgrade = false; address public upgradeContractAddress = address(0); // 最大管理员数量 uint public max_managers = 15; // 最小管理员数量 uint public min_managers = 3; // 最小签名比例 66% uint public rate = 66; // 签名字节长度 uint public signatureLength = 65; // 比例分母 uint constant DENOMINATOR = 100; // 当前合约版本 uint8 constant VERSION = 3; // hash计算加盐 uint public hashSalt; // 当前交易的最小签名数量 uint8 public current_min_signatures; address public owner; mapping(address => uint8) private seedManagers; address[] private seedManagerArray; mapping(address => uint8) private managers; address[] private managerArray; mapping(bytes32 => uint8) private completedKeccak256s; mapping(string => uint8) private completedTxs; mapping(address => uint8) private minterERC20s; mapping(address => uint8) public bugERC20s; bool public openCrossOutII = false; constructor(uint256 _chainid, address[] memory _managers) public{ require(_managers.length <= max_managers, "Exceeded the maximum number of managers"); require(_managers.length >= min_managers, "Not reaching the min number of managers"); owner = msg.sender; managerArray = _managers; for (uint8 i = 0; i < managerArray.length; i++) { managers[managerArray[i]] = 1; seedManagers[managerArray[i]] = 1; seedManagerArray.push(managerArray[i]); } require(managers[owner] == 0, "Contract creator cannot act as manager"); // 设置当前交易的最小签名数量 current_min_signatures = calMinSignatures(managerArray.length); hashSalt = _chainid * 2 + VERSION; } function() external payable { emit DepositFunds(msg.sender, msg.value); } function createOrSignWithdraw(string memory txKey, address payable to, uint256 amount, bool isERC20, address ERC20, bytes memory signatures) public nonReentrant isManager { require(bytes(txKey).length == 64, "Fixed length of txKey: 64"); require(to != address(0), "Withdraw: transfer to the zero address"); require(amount > 0, "Withdrawal amount must be greater than 0"); // 校验已经完成的交易 require(completedTxs[txKey] == 0, "Transaction has been completed"); // 校验提现金额 if (isERC20) { validateTransferERC20(ERC20, to, amount); } else { require(address(this).balance >= amount, "This contract address does not have sufficient balance of ether"); } bytes32 vHash = keccak256(abi.encodePacked(txKey, to, amount, isERC20, ERC20, hashSalt)); // 校验请求重复性 require(completedKeccak256s[vHash] == 0, "Invalid signatures"); // 校验签名 require(validSignature(vHash, signatures), "Valid signatures fail"); // 执行转账 if (isERC20) { transferERC20(ERC20, to, amount); } else { // 实际到账 require(address(this).balance >= amount, "This contract address does not have sufficient balance of ether"); to.transfer(amount); emit TransferFunds(to, amount); } // 保存交易数据 completeTx(txKey, vHash, 1); emit TxWithdrawCompleted(txKey); } function createOrSignManagerChange(string memory txKey, address[] memory adds, address[] memory removes, uint8 count, bytes memory signatures) public isManager { require(bytes(txKey).length == 64, "Fixed length of txKey: 64"); require(adds.length > 0 || removes.length > 0, "There are no managers joining or exiting"); // 校验已经完成的交易 require(completedTxs[txKey] == 0, "Transaction has been completed"); preValidateAddsAndRemoves(adds, removes); bytes32 vHash = keccak256(abi.encodePacked(txKey, adds, count, removes, hashSalt)); // 校验请求重复性 require(completedKeccak256s[vHash] == 0, "Invalid signatures"); // 校验签名 require(validSignature(vHash, signatures), "Valid signatures fail"); // 变更管理员 removeManager(removes); addManager(adds); // 更新当前交易的最小签名数 current_min_signatures = calMinSignatures(managerArray.length); // 保存交易数据 completeTx(txKey, vHash, 1); // add event emit TxManagerChangeCompleted(txKey); } function createOrSignUpgrade(string memory txKey, address upgradeContract, bytes memory signatures) public isManager { require(bytes(txKey).length == 64, "Fixed length of txKey: 64"); // 校验已经完成的交易 require(completedTxs[txKey] == 0, "Transaction has been completed"); require(!upgrade, "It has been upgraded"); require(upgradeContract.isContract(), "The address is not a contract address"); // 校验 bytes32 vHash = keccak256(abi.encodePacked(txKey, upgradeContract, hashSalt)); // 校验请求重复性 require(completedKeccak256s[vHash] == 0, "Invalid signatures"); // 校验签名 require(validSignature(vHash, signatures), "Valid signatures fail"); // 变更可升级 upgrade = true; upgradeContractAddress = upgradeContract; // 保存交易数据 completeTx(txKey, vHash, 1); // add event emit TxUpgradeCompleted(txKey); } function validSignature(bytes32 hash, bytes memory signatures) internal view returns (bool) { require(signatures.length <= 975, "Max length of signatures: 975"); // 获取签名列表对应的有效管理员,如果存在错误的签名、或者不是管理员的签名,就失败 uint sManagersCount = getManagerFromSignatures(hash, signatures); // 判断最小签名数量 return sManagersCount >= current_min_signatures; } function getManagerFromSignatures(bytes32 hash, bytes memory signatures) internal view returns (uint){ uint signCount = 0; uint times = signatures.length.div(signatureLength); address[] memory result = new address[](times); uint k = 0; uint8 j = 0; for (uint i = 0; i < times; i++) { bytes memory sign = signatures.slice(k, signatureLength); address mAddress = ecrecovery(hash, sign); require(mAddress != address(0), "Signatures error"); // 管理计数 if (managers[mAddress] == 1) { signCount++; result[j++] = mAddress; } k += signatureLength; } // 验证地址重复性 bool suc = repeatability(result); delete result; require(suc, "Signatures duplicate"); return signCount; } function validateRepeatability(address currentAddress, address[] memory list) internal pure returns (bool) { address tempAddress; for (uint i = 0; i < list.length; i++) { tempAddress = list[i]; if (tempAddress == address(0)) { break; } if (tempAddress == currentAddress) { return false; } } return true; } function repeatability(address[] memory list) internal pure returns (bool) { for (uint i = 0; i < list.length; i++) { address address1 = list[i]; if (address1 == address(0)) { break; } for (uint j = i + 1; j < list.length; j++) { address address2 = list[j]; if (address2 == address(0)) { break; } if (address1 == address2) { return false; } } } return true; } function ecrecovery(bytes32 hash, bytes memory sig) internal view returns (address) { bytes32 r; bytes32 s; uint8 v; if (sig.length != signatureLength) { return address(0); } assembly { r := mload(add(sig, 32)) s := mload(add(sig, 64)) v := byte(0, mload(add(sig, 96))) } if(uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return address(0); } // https://github.com/ethereum/go-ethereum/issues/2053 if (v < 27) { v += 27; } if (v != 27 && v != 28) { return address(0); } return ecrecover(hash, v, r, s); } function preValidateAddsAndRemoves(address[] memory adds, address[] memory removes) internal view { // 校验adds uint addLen = adds.length; for (uint i = 0; i < addLen; i++) { address add = adds[i]; require(add != address(0), "ERROR: Detected zero address in adds"); require(managers[add] == 0, "The address list that is being added already exists as a manager"); } require(repeatability(adds), "Duplicate parameters for the address to join"); // 校验合约创建者不能被添加 require(validateRepeatability(owner, adds), "Contract creator cannot act as manager"); // 校验removes require(repeatability(removes), "Duplicate parameters for the address to exit"); uint removeLen = removes.length; for (uint i = 0; i < removeLen; i++) { address remove = removes[i]; require(seedManagers[remove] == 0, "Can't exit seed manager"); require(managers[remove] == 1, "There are addresses in the exiting address list that are not manager"); } require(managerArray.length + adds.length - removes.length <= max_managers, "Exceeded the maximum number of managers"); } /* 根据 `当前有效管理员数量` 和 `最小签名比例` 计算最小签名数量,向上取整 */ function calMinSignatures(uint managerCounts) internal view returns (uint8) { require(managerCounts > 0, "Manager Can't empty."); uint numerator = rate * managerCounts + DENOMINATOR - 1; return uint8(numerator / DENOMINATOR); } function removeManager(address[] memory removes) internal { if (removes.length == 0) { return; } for (uint i = 0; i < removes.length; i++) { delete managers[removes[i]]; } // 遍历修改前管理员列表 for (uint i = 0; i < managerArray.length; i++) { if (managers[managerArray[i]] == 0) { delete managerArray[i]; } } uint tempIndex = 0x10; for (uint i = 0; i<managerArray.length; i++) { address temp = managerArray[i]; if (temp == address(0)) { if (tempIndex == 0x10) tempIndex = i; continue; } else if (tempIndex != 0x10) { managerArray[tempIndex] = temp; tempIndex++; } } managerArray.length -= removes.length; } function addManager(address[] memory adds) internal { if (adds.length == 0) { return; } for (uint i = 0; i < adds.length; i++) { address add = adds[i]; if(managers[add] == 0) { managers[add] = 1; managerArray.push(add); } } } function completeTx(string memory txKey, bytes32 keccak256Hash, uint8 e) internal { completedTxs[txKey] = e; completedKeccak256s[keccak256Hash] = e; } function validateTransferERC20(address ERC20, address to, uint256 amount) internal view { require(to != address(0), "ERC20: transfer to the zero address"); require(address(this) != ERC20, "Do nothing by yourself"); require(ERC20.isContract(), "The address is not a contract address"); if (isMinterERC20(ERC20)) { // 定制ERC20验证结束 return; } IERC20 token = IERC20(ERC20); uint256 balance = token.balanceOf(address(this)); require(balance >= amount, "No enough balance of token"); } function transferERC20(address ERC20, address to, uint256 amount) internal { if (isMinterERC20(ERC20)) { // 定制的ERC20,跨链转入以太坊网络即增发 IERC20Minter minterToken = IERC20Minter(ERC20); minterToken.mint(to, amount); return; } IERC20 token = IERC20(ERC20); uint256 balance = token.balanceOf(address(this)); require(balance >= amount, "No enough balance of token"); token.safeTransfer(to, amount, bugERC20s); } function closeUpgrade() public isOwner { require(upgrade, "Denied"); upgrade = false; } function upgradeContractS1() public isOwner { require(upgrade, "Denied"); require(upgradeContractAddress != address(0), "ERROR: transfer to the zero address"); address(uint160(upgradeContractAddress)).transfer(address(this).balance); } function upgradeContractS2(address ERC20) public isOwner { require(upgrade, "Denied"); require(upgradeContractAddress != address(0), "ERROR: transfer to the zero address"); require(address(this) != ERC20, "Do nothing by yourself"); require(ERC20.isContract(), "The address is not a contract address"); IERC20 token = IERC20(ERC20); uint256 balance = token.balanceOf(address(this)); require(balance >= 0, "No enough balance of token"); token.safeTransfer(upgradeContractAddress, balance, bugERC20s); if (isMinterERC20(ERC20)) { // 定制的ERC20,转移增发销毁权限到新多签合约 IERC20Minter minterToken = IERC20Minter(ERC20); minterToken.replaceMinter(upgradeContractAddress); } } // 是否定制的ERC20 function isMinterERC20(address ERC20) public view returns (bool) { return minterERC20s[ERC20] > 0; } // 登记定制的ERC20 function registerMinterERC20(address ERC20) public isOwner { require(address(this) != ERC20, "Do nothing by yourself"); require(ERC20.isContract(), "The address is not a contract address"); require(!isMinterERC20(ERC20), "This address has already been registered"); minterERC20s[ERC20] = 1; } // 取消登记定制的ERC20 function unregisterMinterERC20(address ERC20) public isOwner { require(isMinterERC20(ERC20), "This address is not registered"); delete minterERC20s[ERC20]; } // 登记BUG的ERC20 function registerBugERC20(address bug) public isOwner { require(address(this) != bug, "Do nothing by yourself"); require(bug.isContract(), "The address is not a contract address"); bugERC20s[bug] = 1; } // 取消登记BUG的ERC20 function unregisterBugERC20(address bug) public isOwner { bugERC20s[bug] = 0; } // 从eth网络跨链转出资产(ETH or ERC20) function crossOut(string memory to, uint256 amount, address ERC20) public payable returns (bool) { address from = msg.sender; require(amount > 0, "ERROR: Zero amount"); if (ERC20 != address(0)) { require(msg.value == 0, "ERC20: Does not accept Ethereum Coin"); require(ERC20.isContract(), "The address is not a contract address"); IERC20 token = IERC20(ERC20); uint256 allowance = token.allowance(from, address(this)); require(allowance >= amount, "No enough amount for authorization"); uint256 fromBalance = token.balanceOf(from); require(fromBalance >= amount, "No enough balance of the token"); token.safeTransferFrom(from, address(this), amount, bugERC20s); if (isMinterERC20(ERC20)) { // 定制的ERC20,从以太坊网络跨链转出token即销毁 IERC20Minter minterToken = IERC20Minter(ERC20); minterToken.burn(amount); } } else { require(msg.value == amount, "Inconsistency Ethereum amount"); } emit CrossOutFunds(from, to, amount, ERC20); return true; } // 从eth网络跨链转出资产(ETH or ERC20) function crossOutII(string memory to, uint256 amount, address ERC20, bytes memory data) public payable returns (bool) { require(openCrossOutII, "CrossOutII: Not open"); address from = msg.sender; uint erc20Amount = 0; if (ERC20 != address(0)) { require(amount > 0, "ERROR: Zero amount"); require(ERC20.isContract(), "The address is not a contract address"); IERC20 token = IERC20(ERC20); uint256 allowance = token.allowance(from, address(this)); require(allowance >= amount, "No enough amount for authorization"); uint256 fromBalance = token.balanceOf(from); require(fromBalance >= amount, "No enough balance of the token"); token.safeTransferFrom(from, address(this), amount, bugERC20s); if (isMinterERC20(ERC20)) { // 定制的ERC20,从以太坊网络跨链转出token即销毁 IERC20Minter minterToken = IERC20Minter(ERC20); minterToken.burn(amount); } erc20Amount = amount; } else { require(msg.value > 0 && amount == 0, "CrossOutII: Illegal eth amount"); } emit CrossOutIIFunds(from, to, erc20Amount, ERC20, msg.value, data); return true; } function setCrossOutII(bool _open) public isOwner { openCrossOutII = _open; } function isCompletedTx(string memory txKey) public view returns (bool){ return completedTxs[txKey] > 0; } function ifManager(address _manager) public view returns (bool) { return managers[_manager] == 1; } function allManagers() public view returns (address[] memory) { return managerArray; } event DepositFunds(address from, uint amount); event CrossOutFunds(address from, string to, uint amount, address ERC20); event CrossOutIIFunds(address from, string to, uint amount, address ERC20, uint ethAmount, bytes data); event TransferFunds(address to, uint amount); event TxWithdrawCompleted(string txKey); event TxManagerChangeCompleted(string txKey); event TxUpgradeCompleted(string txKey); }
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","payable":false,"inputs":[{"type":"uint256","name":"_chainid","internalType":"uint256"},{"type":"address[]","name":"_managers","internalType":"address[]"}]},{"type":"event","name":"CrossOutFunds","inputs":[{"type":"address","name":"from","internalType":"address","indexed":false},{"type":"string","name":"to","internalType":"string","indexed":false},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false},{"type":"address","name":"ERC20","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"CrossOutIIFunds","inputs":[{"type":"address","name":"from","internalType":"address","indexed":false},{"type":"string","name":"to","internalType":"string","indexed":false},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false},{"type":"address","name":"ERC20","internalType":"address","indexed":false},{"type":"uint256","name":"ethAmount","internalType":"uint256","indexed":false},{"type":"bytes","name":"data","internalType":"bytes","indexed":false}],"anonymous":false},{"type":"event","name":"DepositFunds","inputs":[{"type":"address","name":"from","internalType":"address","indexed":false},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"TransferFunds","inputs":[{"type":"address","name":"to","internalType":"address","indexed":false},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"TxManagerChangeCompleted","inputs":[{"type":"string","name":"txKey","internalType":"string","indexed":false}],"anonymous":false},{"type":"event","name":"TxUpgradeCompleted","inputs":[{"type":"string","name":"txKey","internalType":"string","indexed":false}],"anonymous":false},{"type":"event","name":"TxWithdrawCompleted","inputs":[{"type":"string","name":"txKey","internalType":"string","indexed":false}],"anonymous":false},{"type":"fallback","stateMutability":"payable","payable":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address[]","name":"","internalType":"address[]"}],"name":"allManagers","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"bugERC20s","inputs":[{"type":"address","name":"","internalType":"address"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"closeUpgrade","inputs":[],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"createOrSignManagerChange","inputs":[{"type":"string","name":"txKey","internalType":"string"},{"type":"address[]","name":"adds","internalType":"address[]"},{"type":"address[]","name":"removes","internalType":"address[]"},{"type":"uint8","name":"count","internalType":"uint8"},{"type":"bytes","name":"signatures","internalType":"bytes"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"createOrSignUpgrade","inputs":[{"type":"string","name":"txKey","internalType":"string"},{"type":"address","name":"upgradeContract","internalType":"address"},{"type":"bytes","name":"signatures","internalType":"bytes"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"createOrSignWithdraw","inputs":[{"type":"string","name":"txKey","internalType":"string"},{"type":"address","name":"to","internalType":"address payable"},{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"bool","name":"isERC20","internalType":"bool"},{"type":"address","name":"ERC20","internalType":"address"},{"type":"bytes","name":"signatures","internalType":"bytes"}],"constant":false},{"type":"function","stateMutability":"payable","payable":true,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"crossOut","inputs":[{"type":"string","name":"to","internalType":"string"},{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"address","name":"ERC20","internalType":"address"}],"constant":false},{"type":"function","stateMutability":"payable","payable":true,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"crossOutII","inputs":[{"type":"string","name":"to","internalType":"string"},{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"address","name":"ERC20","internalType":"address"},{"type":"bytes","name":"data","internalType":"bytes"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"current_min_signatures","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"hashSalt","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"ifManager","inputs":[{"type":"address","name":"_manager","internalType":"address"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isCompletedTx","inputs":[{"type":"string","name":"txKey","internalType":"string"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isMinterERC20","inputs":[{"type":"address","name":"ERC20","internalType":"address"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"max_managers","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"min_managers","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"openCrossOutII","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"rate","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"registerBugERC20","inputs":[{"type":"address","name":"bug","internalType":"address"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"registerMinterERC20","inputs":[{"type":"address","name":"ERC20","internalType":"address"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setCrossOutII","inputs":[{"type":"bool","name":"_open","internalType":"bool"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"signatureLength","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"unregisterBugERC20","inputs":[{"type":"address","name":"bug","internalType":"address"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"unregisterMinterERC20","inputs":[{"type":"address","name":"ERC20","internalType":"address"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"upgrade","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"","internalType":"address"}],"name":"upgradeContractAddress","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"upgradeContractS1","inputs":[],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"upgradeContractS2","inputs":[{"type":"address","name":"ERC20","internalType":"address"}],"constant":false}]
Contract Creation Code
0x6080604052600180546001600160a81b0319169055600f60025560038055604260045560416005556010805460ff191690553480156200003e57600080fd5b50604051620048be380380620048be833981810160405260408110156200006457600080fd5b8151602083018051604051929492938301929190846401000000008211156200008c57600080fd5b908301906020820185811115620000a257600080fd5b8251866020820283011164010000000082111715620000c057600080fd5b82525081516020918201928201910280838360005b83811015620000ef578181015183820152602001620000d5565b505050509190910160405250506001600055505060025481511115620001475760405162461bcd60e51b8152600401808060200182810382526027815260200180620048716027913960400191505060405180910390fd5b600354815110156200018b5760405162461bcd60e51b81526004018080602001828103825260278152602001806200484a6027913960400191505060405180910390fd5b60078054610100600160a81b03191633610100021790558051620001b790600b906020840190620003be565b5060005b600b5460ff82161015620002b5576001600a6000600b8460ff1681548110620001e057fe5b6000918252602080832091909101546001600160a01b031683528201929092526040018120805460ff191660ff938416179055600b805460019360089392919086169081106200022c57fe5b6000918252602080832091909101546001600160a01b031683528201929092526040019020805460ff191660ff928316179055600b805460099284169081106200027257fe5b6000918252602080832090910154835460018181018655948452919092200180546001600160a01b0319166001600160a01b0390921691909117905501620001bb565b5060075461010090046001600160a01b03166000908152600a602052604090205460ff1615620003175760405162461bcd60e51b8152600401808060200182810382526026815260200180620048986026913960400191505060405180910390fd5b600b546200032e906001600160e01b036200035416565b6007805460ff9290921660ff199092169190911790555060020260030160065562000452565b6000808211620003ab576040805162461bcd60e51b815260206004820152601460248201527f4d616e616765722043616e277420656d7074792e000000000000000000000000604482015290519081900360640190fd5b6004548202606301606481049392505050565b82805482825590600052602060002090810192821562000416579160200282015b828111156200041657825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190620003df565b506200042492915062000428565b5090565b6200044f91905b80821115620004245780546001600160a01b03191681556001016200042f565b90565b6143e880620004626000396000f3fe6080604052600436106101b65760003560e01c80638da5cb5b116100ec578063b032531f1161008a578063d55ec69711610064578063d55ec69714610c8f578063dbaeca3114610ca4578063e079cee914610cd0578063f7f2ff7414610ce5576101b6565b8063b032531f14610c1c578063b91f4bec14610c31578063d4cacbaa14610c7a576101b6565b80639dcdc978116100c65780639dcdc978146109c7578063a5e399b3146109fa578063ab6c2b1014610aab578063ad4b61a814610c07576101b6565b80638da5cb5b1461091a5780639532d8f81461092f5780639c30b35e14610962576101b6565b806334774b7111610159578063408e8b7a11610133578063408e8b7a1461073a5780635bda3fcf146108815780636a7142e1146108b457806375173b70146108e7576101b6565b806334774b711461059657806338615bb0146105c957806339269eb014610707576101b6565b80631dda9c05116101955780631dda9c05146105265780632c4e722e1461053b5780632e44d8a81461055057806330b2d84d14610565576101b6565b8062719226146101f25780630889d1f0146104395780631b9a9323146104ff575b6040805133815234602082015281517fd241e73300212f6df233a8e6d3146b88a9d4964e06621d54b5ff6afeba7b1b88929181900390910190a1005b3480156101fe57600080fd5b50610437600480360360a081101561021557600080fd5b810190602081018135600160201b81111561022f57600080fd5b82018360208201111561024157600080fd5b803590602001918460018302840111600160201b8311171561026257600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b8111156102b457600080fd5b8201836020820111156102c657600080fd5b803590602001918460208302840111600160201b831117156102e757600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b81111561033657600080fd5b82018360208201111561034857600080fd5b803590602001918460208302840111600160201b8311171561036957600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929560ff853516959094909350604081019250602001359050600160201b8111156103c357600080fd5b8201836020820111156103d557600080fd5b803590602001918460018302840111600160201b831117156103f657600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610cfa945050505050565b005b6104eb6004803603606081101561044f57600080fd5b810190602081018135600160201b81111561046957600080fd5b82018360208201111561047b57600080fd5b803590602001918460018302840111600160201b8311171561049c57600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092955050823593505050602001356001600160a01b0316611134565b604080519115158252519081900360200190f35b34801561050b57600080fd5b50610514611580565b60408051918252519081900360200190f35b34801561053257600080fd5b50610437611586565b34801561054757600080fd5b506105146116a7565b34801561055c57600080fd5b506104eb6116ad565b34801561057157600080fd5b5061057a6116b6565b604080516001600160a01b039092168252519081900360200190f35b3480156105a257600080fd5b50610437600480360360208110156105b957600080fd5b50356001600160a01b03166116ca565b6104eb600480360360808110156105df57600080fd5b810190602081018135600160201b8111156105f957600080fd5b82018360208201111561060b57600080fd5b803590602001918460018302840111600160201b8311171561062c57600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092958435956001600160a01b0360208701351695919450925060608101915060400135600160201b81111561069357600080fd5b8201836020820111156106a557600080fd5b803590602001918460018302840111600160201b831117156106c657600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611829945050505050565b34801561071357600080fd5b506104376004803603602081101561072a57600080fd5b50356001600160a01b0316611d0b565b34801561074657600080fd5b506104376004803603606081101561075d57600080fd5b810190602081018135600160201b81111561077757600080fd5b82018360208201111561078957600080fd5b803590602001918460018302840111600160201b831117156107aa57600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092956001600160a01b03853516959094909350604081019250602001359050600160201b81111561080d57600080fd5b82018360208201111561081f57600080fd5b803590602001918460018302840111600160201b8311171561084057600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611e25945050505050565b34801561088d57600080fd5b50610437600480360360208110156108a457600080fd5b50356001600160a01b0316612249565b3480156108c057600080fd5b506104eb600480360360208110156108d757600080fd5b50356001600160a01b03166124eb565b3480156108f357600080fd5b506104eb6004803603602081101561090a57600080fd5b50356001600160a01b031661250f565b34801561092657600080fd5b5061057a612530565b34801561093b57600080fd5b506104376004803603602081101561095257600080fd5b50356001600160a01b0316612544565b34801561096e57600080fd5b506109776125b7565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156109b357818101518382015260200161099b565b505050509050019250505060405180910390f35b3480156109d357600080fd5b50610437600480360360208110156109ea57600080fd5b50356001600160a01b031661261a565b348015610a0657600080fd5b506104eb60048036036020811015610a1d57600080fd5b810190602081018135600160201b811115610a3757600080fd5b820183602082011115610a4957600080fd5b803590602001918460018302840111600160201b83111715610a6a57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506126e7945050505050565b348015610ab757600080fd5b50610437600480360360c0811015610ace57600080fd5b810190602081018135600160201b811115610ae857600080fd5b820183602082011115610afa57600080fd5b803590602001918460018302840111600160201b83111715610b1b57600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092956001600160a01b0385358116966020870135966040810135151596506060810135909216945091925060a081019060800135600160201b811115610b9357600080fd5b820183602082011115610ba557600080fd5b803590602001918460018302840111600160201b83111715610bc657600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612757945050505050565b348015610c1357600080fd5b50610514612ce6565b348015610c2857600080fd5b50610514612cec565b348015610c3d57600080fd5b50610c6460048036036020811015610c5457600080fd5b50356001600160a01b0316612cf2565b6040805160ff9092168252519081900360200190f35b348015610c8657600080fd5b50610437612d07565b348015610c9b57600080fd5b506104eb612da5565b348015610cb057600080fd5b5061043760048036036020811015610cc757600080fd5b50351515612dae565b348015610cdc57600080fd5b50610c64612e13565b348015610cf157600080fd5b50610514612e1c565b336000908152600a602052604090205460ff16600114610d61576040805162461bcd60e51b815260206004820152601b60248201527f4f6e6c79206d616e616765722063616e20657865637574652069740000000000604482015290519081900360640190fd5b8451604014610db3576040805162461bcd60e51b8152602060048201526019602482015278119a5e1959081b195b99dd1a081bd9881d1e12d95e4e880d8d603a1b604482015290519081900360640190fd5b600084511180610dc4575060008351115b610dff5760405162461bcd60e51b81526004018080602001828103825260288152602001806142cb6028913960400191505060405180910390fd5b600d856040518082805190602001908083835b60208310610e315780518252601f199092019160209182019101610e12565b51815160209384036101000a600019018019909216911617905292019485525060405193849003019092205460ff16159150610eb69050576040805162461bcd60e51b815260206004820152601e60248201527f5472616e73616374696f6e20686173206265656e20636f6d706c657465640000604482015290519081900360640190fd5b610ec08484612e22565b6000858584866006546040516020018086805190602001908083835b60208310610efb5780518252601f199092019160209182019101610edc565b51815160209384036101000a60001901801990921691161790528851919093019288810192500280838360005b83811015610f40578181015183820152602001610f28565b505050509050018460ff1660ff1660f81b8152600101838051906020019060200280838360005b83811015610f7f578181015183820152602001610f67565b50505050919091019283525050604080518083038152602092830182528051908301206000818152600c90935291205490955060ff1615935061100292505050576040805162461bcd60e51b8152602060048201526012602482015271496e76616c6964207369676e61747572657360701b604482015290519081900360640190fd5b61100c8183613125565b611055576040805162461bcd60e51b815260206004820152601560248201527415985b1a59081cda59db985d1d5c995cc819985a5b605a1b604482015290519081900360640190fd5b61105e8461319d565b61106785613326565b600b54611073906133ee565b6007805460ff191660ff929092169190911790556110938682600161344e565b7fac9b82db4e104d515319a481096bfd91a4f40ee10837d5a2c8d51b9a03dc48ae866040518080602001828103825283818151815260200191508051906020019080838360005b838110156110f25781810151838201526020016110da565b50505050905090810190601f16801561111f5780820380516001836020036101000a031916815260200191505b509250505060405180910390a1505050505050565b6000338361117e576040805162461bcd60e51b815260206004820152601260248201527111549493d48e8816995c9bc8185b5bdd5b9d60721b604482015290519081900360640190fd5b6001600160a01b0383161561144c5734156111ca5760405162461bcd60e51b815260040180806020018281038252602481526020018061412c6024913960400191505060405180910390fd5b6111dc836001600160a01b03166134e2565b6112175760405162461bcd60e51b815260040180806020018281038252602581526020018061438f6025913960400191505060405180910390fd5b60408051636eb1769f60e11b81526001600160a01b038381166004830152306024830152915185926000929084169163dd62ed3e91604480820192602092909190829003018186803b15801561126c57600080fd5b505afa158015611280573d6000803e3d6000fd5b505050506040513d602081101561129657600080fd5b50519050858110156112d95760405162461bcd60e51b81526004018080602001828103825260228152602001806142466022913960400191505060405180910390fd5b6000826001600160a01b03166370a08231856040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561133157600080fd5b505afa158015611345573d6000803e3d6000fd5b505050506040513d602081101561135b57600080fd5b50519050868110156113b4576040805162461bcd60e51b815260206004820152601e60248201527f4e6f20656e6f7567682062616c616e6365206f662074686520746f6b656e0000604482015290519081900360640190fd5b6113d16001600160a01b03841685308a600f63ffffffff61351e16565b6113da866124eb565b15611444576000869050806001600160a01b03166342966c68896040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561142a57600080fd5b505af115801561143e573d6000803e3d6000fd5b50505050505b5050506114a0565b8334146114a0576040805162461bcd60e51b815260206004820152601d60248201527f496e636f6e73697374656e637920457468657265756d20616d6f756e74000000604482015290519081900360640190fd5b7f5ddf9724d8fe5d9e12499be2867f93d41a582733dcd65f74a486ad7e306671468186868660405180856001600160a01b03166001600160a01b0316815260200180602001848152602001836001600160a01b03166001600160a01b03168152602001828103825285818151815260200191508051906020019080838360005b83811015611538578181015183820152602001611520565b50505050905090810190601f1680156115655780820380516001836020036101000a031916815260200191505b509550505050505060405180910390a1506001949350505050565b60055481565b60075461010090046001600160a01b031633146115d8576040805162461bcd60e51b8152602060048201526019602482015260008051602061431f833981519152604482015290519081900360640190fd5b60015460ff16611618576040805162461bcd60e51b815260206004820152600660248201526511195b9a595960d21b604482015290519081900360640190fd5b60015461010090046001600160a01b03166116645760405162461bcd60e51b81526004018080602001828103825260238152602001806142686023913960400191505060405180910390fd5b6001546040516001600160a01b0361010090920491909116904780156108fc02916000818181858888f193505050501580156116a4573d6000803e3d6000fd5b50565b60045481565b60105460ff1681565b60015461010090046001600160a01b031681565b60075461010090046001600160a01b0316331461171c576040805162461bcd60e51b8152602060048201526019602482015260008051602061431f833981519152604482015290519081900360640190fd5b306001600160a01b0382161415611773576040805162461bcd60e51b81526020600482015260166024820152752237903737ba3434b73390313c903cb7bab939b2b63360511b604482015290519081900360640190fd5b611785816001600160a01b03166134e2565b6117c05760405162461bcd60e51b815260040180806020018281038252602581526020018061438f6025913960400191505060405180910390fd5b6117c9816124eb565b156118055760405162461bcd60e51b81526004018080602001828103825260288152602001806140b26028913960400191505060405180910390fd5b6001600160a01b03166000908152600e60205260409020805460ff19166001179055565b60105460009060ff1661187a576040805162461bcd60e51b815260206004820152601460248201527321b937b9b9a7baba24a49d102737ba1037b832b760611b604482015290519081900360640190fd5b3360006001600160a01b03851615611b5b57600086116118d6576040805162461bcd60e51b815260206004820152601260248201527111549493d48e8816995c9bc8185b5bdd5b9d60721b604482015290519081900360640190fd5b6118e8856001600160a01b03166134e2565b6119235760405162461bcd60e51b815260040180806020018281038252602581526020018061438f6025913960400191505060405180910390fd5b60408051636eb1769f60e11b81526001600160a01b038481166004830152306024830152915187926000929084169163dd62ed3e91604480820192602092909190829003018186803b15801561197857600080fd5b505afa15801561198c573d6000803e3d6000fd5b505050506040513d60208110156119a257600080fd5b50519050878110156119e55760405162461bcd60e51b81526004018080602001828103825260228152602001806142466022913960400191505060405180910390fd5b6000826001600160a01b03166370a08231866040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015611a3d57600080fd5b505afa158015611a51573d6000803e3d6000fd5b505050506040513d6020811015611a6757600080fd5b5051905088811015611ac0576040805162461bcd60e51b815260206004820152601e60248201527f4e6f20656e6f7567682062616c616e6365206f662074686520746f6b656e0000604482015290519081900360640190fd5b611add6001600160a01b03841686308c600f63ffffffff61351e16565b611ae6886124eb565b15611b50576000889050806001600160a01b03166342966c688b6040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b158015611b3657600080fd5b505af1158015611b4a573d6000803e3d6000fd5b50505050505b889350505050611bba565b600034118015611b69575085155b611bba576040805162461bcd60e51b815260206004820152601e60248201527f43726f73734f757449493a20496c6c6567616c2065746820616d6f756e740000604482015290519081900360640190fd5b7f692e6a6e27573f2a2a757e34cb16ae101c5fca8834f9b8a6cdbcf64b8450d87082888388348960405180876001600160a01b03166001600160a01b0316815260200180602001868152602001856001600160a01b03166001600160a01b0316815260200184815260200180602001838103835288818151815260200191508051906020019080838360005b83811015611c5e578181015183820152602001611c46565b50505050905090810190601f168015611c8b5780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b83811015611cbe578181015183820152602001611ca6565b50505050905090810190601f168015611ceb5780820380516001836020036101000a031916815260200191505b509850505050505050505060405180910390a15060019695505050505050565b60075461010090046001600160a01b03163314611d5d576040805162461bcd60e51b8152602060048201526019602482015260008051602061431f833981519152604482015290519081900360640190fd5b306001600160a01b0382161415611db4576040805162461bcd60e51b81526020600482015260166024820152752237903737ba3434b73390313c903cb7bab939b2b63360511b604482015290519081900360640190fd5b611dc6816001600160a01b03166134e2565b611e015760405162461bcd60e51b815260040180806020018281038252602581526020018061438f6025913960400191505060405180910390fd5b6001600160a01b03166000908152600f60205260409020805460ff19166001179055565b336000908152600a602052604090205460ff16600114611e8c576040805162461bcd60e51b815260206004820152601b60248201527f4f6e6c79206d616e616765722063616e20657865637574652069740000000000604482015290519081900360640190fd5b8251604014611ede576040805162461bcd60e51b8152602060048201526019602482015278119a5e1959081b195b99dd1a081bd9881d1e12d95e4e880d8d603a1b604482015290519081900360640190fd5b600d836040518082805190602001908083835b60208310611f105780518252601f199092019160209182019101611ef1565b51815160209384036101000a600019018019909216911617905292019485525060405193849003019092205460ff16159150611f959050576040805162461bcd60e51b815260206004820152601e60248201527f5472616e73616374696f6e20686173206265656e20636f6d706c657465640000604482015290519081900360640190fd5b60015460ff1615611fe4576040805162461bcd60e51b8152602060048201526014602482015273125d081a185cc81899595b881d5c19dc9859195960621b604482015290519081900360640190fd5b611ff6826001600160a01b03166134e2565b6120315760405162461bcd60e51b815260040180806020018281038252602581526020018061438f6025913960400191505060405180910390fd5b600083836006546040516020018084805190602001908083835b6020831061206a5780518252601f19909201916020918201910161204b565b51815160209384036101000a600019018019909216911617905260609690961b6bffffffffffffffffffffffff1916920191825250601480820193909352604080518083039094018452603490910181528251928401929092206000818152600c909452919092205490935060ff161591506121249050576040805162461bcd60e51b8152602060048201526012602482015271496e76616c6964207369676e61747572657360701b604482015290519081900360640190fd5b61212e8183613125565b612177576040805162461bcd60e51b815260206004820152601560248201527415985b1a59081cda59db985d1d5c995cc819985a5b605a1b604482015290519081900360640190fd5b6001805460ff19168117610100600160a81b0319166101006001600160a01b038616021781556121aa908590839061344e565b7f5e06c4b22547d430736ce834764dbfee08f1c4cf7ae3d53178aa56effa593ed0846040518080602001828103825283818151815260200191508051906020019080838360005b838110156122095781810151838201526020016121f1565b50505050905090810190601f1680156122365780820380516001836020036101000a031916815260200191505b509250505060405180910390a150505050565b60075461010090046001600160a01b0316331461229b576040805162461bcd60e51b8152602060048201526019602482015260008051602061431f833981519152604482015290519081900360640190fd5b60015460ff166122db576040805162461bcd60e51b815260206004820152600660248201526511195b9a595960d21b604482015290519081900360640190fd5b60015461010090046001600160a01b03166123275760405162461bcd60e51b81526004018080602001828103825260238152602001806142686023913960400191505060405180910390fd5b306001600160a01b038216141561237e576040805162461bcd60e51b81526020600482015260166024820152752237903737ba3434b73390313c903cb7bab939b2b63360511b604482015290519081900360640190fd5b612390816001600160a01b03166134e2565b6123cb5760405162461bcd60e51b815260040180806020018281038252602581526020018061438f6025913960400191505060405180910390fd5b604080516370a0823160e01b8152306004820152905182916000916001600160a01b038416916370a08231916024808301926020929190829003018186803b15801561241657600080fd5b505afa15801561242a573d6000803e3d6000fd5b505050506040513d602081101561244057600080fd5b5051905060015461246b906001600160a01b038481169161010090041683600f63ffffffff61358016565b612474836124eb565b156124e657600154604080516301fc6bd160e21b81526001600160a01b0361010090930483166004820152905185928316916307f1af4491602480830192600092919082900301818387803b1580156124cc57600080fd5b505af11580156124e0573d6000803e3d6000fd5b50505050505b505050565b6001600160a01b0381166000908152600e602052604090205460ff1615155b919050565b6001600160a01b03166000908152600a602052604090205460ff1660011490565b60075461010090046001600160a01b031681565b60075461010090046001600160a01b03163314612596576040805162461bcd60e51b8152602060048201526019602482015260008051602061431f833981519152604482015290519081900360640190fd5b6001600160a01b03166000908152600f60205260409020805460ff19169055565b6060600b80548060200260200160405190810160405280929190818152602001828054801561260f57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116125f1575b505050505090505b90565b60075461010090046001600160a01b0316331461266c576040805162461bcd60e51b8152602060048201526019602482015260008051602061431f833981519152604482015290519081900360640190fd5b612675816124eb565b6126c6576040805162461bcd60e51b815260206004820152601e60248201527f546869732061646472657373206973206e6f7420726567697374657265640000604482015290519081900360640190fd5b6001600160a01b03166000908152600e60205260409020805460ff19169055565b600080600d836040518082805190602001908083835b6020831061271c5780518252601f1990920191602091820191016126fd565b51815160209384036101000a600019018019909216911617905292019485525060405193849003019092205460ff1692909211949350505050565b600260005414156127af576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026000908155338152600a602052604090205460ff1660011461281a576040805162461bcd60e51b815260206004820152601b60248201527f4f6e6c79206d616e616765722063616e20657865637574652069740000000000604482015290519081900360640190fd5b855160401461286c576040805162461bcd60e51b8152602060048201526019602482015278119a5e1959081b195b99dd1a081bd9881d1e12d95e4e880d8d603a1b604482015290519081900360640190fd5b6001600160a01b0385166128b15760405162461bcd60e51b81526004018080602001828103825260268152602001806140da6026913960400191505060405180910390fd5b600084116128f05760405162461bcd60e51b815260040180806020018281038252602881526020018061421e6028913960400191505060405180910390fd5b600d866040518082805190602001908083835b602083106129225780518252601f199092019160209182019101612903565b51815160209384036101000a600019018019909216911617905292019485525060405193849003019092205460ff161591506129a79050576040805162461bcd60e51b815260206004820152601e60248201527f5472616e73616374696f6e20686173206265656e20636f6d706c657465640000604482015290519081900360640190fd5b82156129bd576129b88286866135d3565b6129fc565b834710156129fc5760405162461bcd60e51b815260040180806020018281038252603f815260200180614150603f913960400191505060405180910390fd5b600086868686866006546040516020018087805190602001908083835b60208310612a385780518252601f199092019160209182019101612a19565b51815160209384036101000a60001901801990921691161790526060998a1b6bffffffffffffffffffffffff1990811692909401918252601482019890985295151560f81b6034870152509290951b9091166035830152604980830191909152604080518084039092018252606990920182528051908301206000818152600c90935291205490935060ff16159150612b0f9050576040805162461bcd60e51b8152602060048201526012602482015271496e76616c6964207369676e61747572657360701b604482015290519081900360640190fd5b612b198183613125565b612b62576040805162461bcd60e51b815260206004820152601560248201527415985b1a59081cda59db985d1d5c995cc819985a5b605a1b604482015290519081900360640190fd5b8315612b7857612b7383878761379d565b612c33565b84471015612bb75760405162461bcd60e51b815260040180806020018281038252603f815260200180614150603f913960400191505060405180910390fd5b6040516001600160a01b0387169086156108fc029087906000818181858888f19350505050158015612bed573d6000803e3d6000fd5b50604080516001600160a01b03881681526020810187905281517fc95f8b91b103304386b955ef73fadac189f8ad66b33369b6c34a17a60db7bd0a929181900390910190a15b612c3f8782600161344e565b7f8ed8b1f0dd3babfdf1477ba2b27a5b0d2f1c9148448fd22cf2c75e658293c7b1876040518080602001828103825283818151815260200191508051906020019080838360005b83811015612c9e578181015183820152602001612c86565b50505050905090810190601f168015612ccb5780820380516001836020036101000a031916815260200191505b509250505060405180910390a1505060016000555050505050565b60035481565b60065481565b600f6020526000908152604090205460ff1681565b60075461010090046001600160a01b03163314612d59576040805162461bcd60e51b8152602060048201526019602482015260008051602061431f833981519152604482015290519081900360640190fd5b60015460ff16612d99576040805162461bcd60e51b815260206004820152600660248201526511195b9a595960d21b604482015290519081900360640190fd5b6001805460ff19169055565b60015460ff1681565b60075461010090046001600160a01b03163314612e00576040805162461bcd60e51b8152602060048201526019602482015260008051602061431f833981519152604482015290519081900360640190fd5b6010805460ff1916911515919091179055565b60075460ff1681565b60025481565b815160005b81811015612efa576000848281518110612e3d57fe5b6020026020010151905060006001600160a01b0316816001600160a01b03161415612e995760405162461bcd60e51b815260040180806020018281038252602481526020018061418f6024913960400191505060405180910390fd5b6001600160a01b0381166000908152600a602052604090205460ff1615612ef15760405162461bcd60e51b815260040180806020018281038252604081526020018061428b6040913960400191505060405180910390fd5b50600101612e27565b50612f0483613905565b612f3f5760405162461bcd60e51b815260040180806020018281038252602c815260200180614100602c913960400191505060405180910390fd5b600754612f5a9061010090046001600160a01b0316846139d5565b612f955760405162461bcd60e51b81526004018080602001828103825260268152602001806143696026913960400191505060405180910390fd5b612f9e82613905565b612fd95760405162461bcd60e51b815260040180806020018281038252602c8152602001806142f3602c913960400191505060405180910390fd5b815160005b818110156130d5576000848281518110612ff457fe5b6020908102919091018101516001600160a01b0381166000908152600890925260409091205490915060ff1615613072576040805162461bcd60e51b815260206004820152601760248201527f43616e277420657869742073656564206d616e61676572000000000000000000604482015290519081900360640190fd5b6001600160a01b0381166000908152600a602052604090205460ff166001146130cc5760405162461bcd60e51b81526004018080602001828103825260448152602001806141da6044913960600191505060405180910390fd5b50600101612fde565b5060025483518551600b540103111561311f5760405162461bcd60e51b81526004018080602001828103825260278152602001806141b36027913960400191505060405180910390fd5b50505050565b60006103cf8251111561317f576040805162461bcd60e51b815260206004820152601d60248201527f4d6178206c656e677468206f66207369676e6174757265733a20393735000000604482015290519081900360640190fd5b600061318b8484613a51565b60075460ff1611159150505b92915050565b80516131a8576116a4565b60005b81518110156131f757600a60008383815181106131c457fe5b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191690556001016131ab565b5060005b600b5481101561327157600a6000600b838154811061321657fe5b60009182526020808320909101546001600160a01b0316835282019290925260400190205460ff1661326957600b818154811061324f57fe5b600091825260209091200180546001600160a01b03191690555b6001016131fb565b50601060005b600b54811015613310576000600b828154811061329057fe5b6000918252602090912001546001600160a01b03169050806132bf5782601014156132b9578192505b50613308565b826010146133065780600b84815481106132d557fe5b600091825260209091200180546001600160a01b0319166001600160a01b0392909216919091179055600192909201915b505b600101613277565b508151600b805491909103906124e69082614051565b8051613331576116a4565b60005b81518110156133ea57600082828151811061334b57fe5b6020908102919091018101516001600160a01b0381166000908152600a90925260409091205490915060ff166133e1576001600160a01b0381166000818152600a60205260408120805460ff19166001908117909155600b805491820181559091527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90180546001600160a01b03191690911790555b50600101613334565b5050565b600080821161343b576040805162461bcd60e51b815260206004820152601460248201527326b0b730b3b2b91021b0b713ba1032b6b83a3c9760611b604482015290519081900360640190fd5b6004548202606301606481049392505050565b80600d846040518082805190602001908083835b602083106134815780518252601f199092019160209182019101613462565b51815160209384036101000a600019018019909216911617905292019485525060408051948590038201909420805460ff1990811660ff978816179091556000978852600c9091529290952080549092169390921692909217909155505050565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081811480159061351657508115155b949350505050565b604080516001600160a01b0386811660248301528516604482015260648082018590528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b17905261357990869083613bfc565b5050505050565b604080516001600160a01b038516602482015260448082018590528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261311f90859083613bfc565b6001600160a01b0382166136185760405162461bcd60e51b815260040180806020018281038252602381526020018061408f6023913960400191505060405180910390fd5b306001600160a01b038416141561366f576040805162461bcd60e51b81526020600482015260166024820152752237903737ba3434b73390313c903cb7bab939b2b63360511b604482015290519081900360640190fd5b613681836001600160a01b03166134e2565b6136bc5760405162461bcd60e51b815260040180806020018281038252602581526020018061438f6025913960400191505060405180910390fd5b6136c5836124eb565b156136cf576124e6565b604080516370a0823160e01b8152306004820152905184916000916001600160a01b038416916370a08231916024808301926020929190829003018186803b15801561371a57600080fd5b505afa15801561372e573d6000803e3d6000fd5b505050506040513d602081101561374457600080fd5b5051905082811015613579576040805162461bcd60e51b815260206004820152601a60248201527f4e6f20656e6f7567682062616c616e6365206f6620746f6b656e000000000000604482015290519081900360640190fd5b6137a6836124eb565b1561381b57604080516340c10f1960e01b81526001600160a01b03848116600483015260248201849052915185928316916340c10f1991604480830192600092919082900301818387803b1580156137fd57600080fd5b505af1158015613811573d6000803e3d6000fd5b50505050506124e6565b604080516370a0823160e01b8152306004820152905184916000916001600160a01b038416916370a08231916024808301926020929190829003018186803b15801561386657600080fd5b505afa15801561387a573d6000803e3d6000fd5b505050506040513d602081101561389057600080fd5b50519050828110156138e9576040805162461bcd60e51b815260206004820152601a60248201527f4e6f20656e6f7567682062616c616e6365206f6620746f6b656e000000000000604482015290519081900360640190fd5b6135796001600160a01b0383168585600f63ffffffff61358016565b6000805b82518110156139cc57600083828151811061392057fe5b6020026020010151905060006001600160a01b0316816001600160a01b0316141561394b57506139cc565b600182015b84518110156139c257600085828151811061396757fe5b6020026020010151905060006001600160a01b0316816001600160a01b0316141561399257506139c2565b806001600160a01b0316836001600160a01b031614156139b957600094505050505061250a565b50600101613950565b5050600101613909565b50600192915050565b600080805b8351811015613a46578381815181106139ef57fe5b6020026020010151915060006001600160a01b0316826001600160a01b03161415613a1957613a46565b846001600160a01b0316826001600160a01b03161415613a3e57600092505050613197565b6001016139da565b506001949350505050565b600554815160009182918291613a6d919063ffffffff613ddc16565b9050606081604051908082528060200260200182016040528015613a9b578160200160208202803883390190505b509050600080805b84811015613b94576060613ac4846005548b613e259092919063ffffffff16565b90506000613ad28b83613ea5565b90506001600160a01b038116613b22576040805162461bcd60e51b815260206004820152601060248201526f29b4b3b730ba3ab932b99032b93937b960811b604482015290519081900360640190fd5b6001600160a01b0381166000908152600a602052604090205460ff1660011415613b825785516001988901988501948291889160ff16908110613b6157fe5b60200260200101906001600160a01b031690816001600160a01b0316815250505b50506005549290920191600101613aa3565b506000613ba084613905565b90506060935080613bef576040805162461bcd60e51b81526020600482015260146024820152735369676e617475726573206475706c696361746560601b604482015290519081900360640190fd5b5093979650505050505050565b613c0e836001600160a01b03166134e2565b613c5f576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060846001600160a01b0316846040518082805190602001908083835b60208310613c9d5780518252601f199092019160209182019101613c7e565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114613cff576040519150601f19603f3d011682016040523d82523d6000602084013e613d04565b606091505b509150915081613d5b576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b6001600160a01b03851660009081526020849052604090205460ff1615613d835750506124e6565b80511561357957808060200190516020811015613d9f57600080fd5b50516135795760405162461bcd60e51b815260040180806020018281038252602a81526020018061433f602a913960400191505060405180910390fd5b6000613e1e83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613faf565b9392505050565b606081830184511015613e3757600080fd5b606082158015613e5257604051915060208201604052613e9c565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015613e8b578051835260209283019201613e73565b5050858452601f01601f1916604052505b50949350505050565b600080600080600554855114613ec15760009350505050613197565b50505060208201516040830151606084015160001a7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115613f0a5760009350505050613197565b601b8160ff161015613f1a57601b015b8060ff16601b14158015613f3257508060ff16601c14155b15613f435760009350505050613197565b6040805160008152602080820180845289905260ff8416828401526060820186905260808201859052915160019260a0808401939192601f1981019281900390910190855afa158015613f9a573d6000803e3d6000fd5b5050604051601f190151979650505050505050565b6000818361403b5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015614000578181015183820152602001613fe8565b50505050905090810190601f16801561402d5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50600083858161404757fe5b0495945050505050565b8154818355818111156124e6576000838152602090206124e691810190830161261791905b8082111561408a5760008155600101614076565b509056fe45524332303a207472616e7366657220746f20746865207a65726f20616464726573735468697320616464726573732068617320616c7265616479206265656e207265676973746572656457697468647261773a207472616e7366657220746f20746865207a65726f20616464726573734475706c696361746520706172616d657465727320666f7220746865206164647265737320746f206a6f696e45524332303a20446f6573206e6f742061636365707420457468657265756d20436f696e5468697320636f6e7472616374206164647265737320646f6573206e6f7420686176652073756666696369656e742062616c616e6365206f662065746865724552524f523a204465746563746564207a65726f206164647265737320696e2061646473457863656564656420746865206d6178696d756d206e756d626572206f66206d616e61676572735468657265206172652061646472657373657320696e207468652065786974696e672061646472657373206c697374207468617420617265206e6f74206d616e616765725769746864726177616c20616d6f756e74206d7573742062652067726561746572207468616e20304e6f20656e6f75676820616d6f756e7420666f7220617574686f72697a6174696f6e4552524f523a207472616e7366657220746f20746865207a65726f20616464726573735468652061646472657373206c6973742074686174206973206265696e6720616464656420616c7265616479206578697374732061732061206d616e61676572546865726520617265206e6f206d616e6167657273206a6f696e696e67206f722065786974696e674475706c696361746520706172616d657465727320666f7220746865206164647265737320746f20657869744f6e6c79206f776e65722063616e2065786563757465206974000000000000005361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564436f6e74726163742063726561746f722063616e6e6f7420616374206173206d616e616765725468652061646472657373206973206e6f74206120636f6e74726163742061646472657373a265627a7a7231582086b5ef132f949ad96c9c48c21f211afdf94866fd5afc7771f740c66e4cec878264736f6c634300051100324e6f74207265616368696e6720746865206d696e206e756d626572206f66206d616e6167657273457863656564656420746865206d6178696d756d206e756d626572206f66206d616e6167657273436f6e74726163742063726561746f722063616e6e6f7420616374206173206d616e6167657200000000000000000000000000000000000000000000000000000000000008ae00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000003000000000000000000000000d87f2ad3ef011817319fd25454fc186ca71b3b560000000000000000000000000eb9e4427a0af1fa457230bef3481d028488363e000000000000000000000000d6946039519bccc0b302f89493bec60f4f0b4610
Deployed ByteCode
0x6080604052600436106101b65760003560e01c80638da5cb5b116100ec578063b032531f1161008a578063d55ec69711610064578063d55ec69714610c8f578063dbaeca3114610ca4578063e079cee914610cd0578063f7f2ff7414610ce5576101b6565b8063b032531f14610c1c578063b91f4bec14610c31578063d4cacbaa14610c7a576101b6565b80639dcdc978116100c65780639dcdc978146109c7578063a5e399b3146109fa578063ab6c2b1014610aab578063ad4b61a814610c07576101b6565b80638da5cb5b1461091a5780639532d8f81461092f5780639c30b35e14610962576101b6565b806334774b7111610159578063408e8b7a11610133578063408e8b7a1461073a5780635bda3fcf146108815780636a7142e1146108b457806375173b70146108e7576101b6565b806334774b711461059657806338615bb0146105c957806339269eb014610707576101b6565b80631dda9c05116101955780631dda9c05146105265780632c4e722e1461053b5780632e44d8a81461055057806330b2d84d14610565576101b6565b8062719226146101f25780630889d1f0146104395780631b9a9323146104ff575b6040805133815234602082015281517fd241e73300212f6df233a8e6d3146b88a9d4964e06621d54b5ff6afeba7b1b88929181900390910190a1005b3480156101fe57600080fd5b50610437600480360360a081101561021557600080fd5b810190602081018135600160201b81111561022f57600080fd5b82018360208201111561024157600080fd5b803590602001918460018302840111600160201b8311171561026257600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b8111156102b457600080fd5b8201836020820111156102c657600080fd5b803590602001918460208302840111600160201b831117156102e757600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b81111561033657600080fd5b82018360208201111561034857600080fd5b803590602001918460208302840111600160201b8311171561036957600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929560ff853516959094909350604081019250602001359050600160201b8111156103c357600080fd5b8201836020820111156103d557600080fd5b803590602001918460018302840111600160201b831117156103f657600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610cfa945050505050565b005b6104eb6004803603606081101561044f57600080fd5b810190602081018135600160201b81111561046957600080fd5b82018360208201111561047b57600080fd5b803590602001918460018302840111600160201b8311171561049c57600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092955050823593505050602001356001600160a01b0316611134565b604080519115158252519081900360200190f35b34801561050b57600080fd5b50610514611580565b60408051918252519081900360200190f35b34801561053257600080fd5b50610437611586565b34801561054757600080fd5b506105146116a7565b34801561055c57600080fd5b506104eb6116ad565b34801561057157600080fd5b5061057a6116b6565b604080516001600160a01b039092168252519081900360200190f35b3480156105a257600080fd5b50610437600480360360208110156105b957600080fd5b50356001600160a01b03166116ca565b6104eb600480360360808110156105df57600080fd5b810190602081018135600160201b8111156105f957600080fd5b82018360208201111561060b57600080fd5b803590602001918460018302840111600160201b8311171561062c57600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092958435956001600160a01b0360208701351695919450925060608101915060400135600160201b81111561069357600080fd5b8201836020820111156106a557600080fd5b803590602001918460018302840111600160201b831117156106c657600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611829945050505050565b34801561071357600080fd5b506104376004803603602081101561072a57600080fd5b50356001600160a01b0316611d0b565b34801561074657600080fd5b506104376004803603606081101561075d57600080fd5b810190602081018135600160201b81111561077757600080fd5b82018360208201111561078957600080fd5b803590602001918460018302840111600160201b831117156107aa57600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092956001600160a01b03853516959094909350604081019250602001359050600160201b81111561080d57600080fd5b82018360208201111561081f57600080fd5b803590602001918460018302840111600160201b8311171561084057600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611e25945050505050565b34801561088d57600080fd5b50610437600480360360208110156108a457600080fd5b50356001600160a01b0316612249565b3480156108c057600080fd5b506104eb600480360360208110156108d757600080fd5b50356001600160a01b03166124eb565b3480156108f357600080fd5b506104eb6004803603602081101561090a57600080fd5b50356001600160a01b031661250f565b34801561092657600080fd5b5061057a612530565b34801561093b57600080fd5b506104376004803603602081101561095257600080fd5b50356001600160a01b0316612544565b34801561096e57600080fd5b506109776125b7565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156109b357818101518382015260200161099b565b505050509050019250505060405180910390f35b3480156109d357600080fd5b50610437600480360360208110156109ea57600080fd5b50356001600160a01b031661261a565b348015610a0657600080fd5b506104eb60048036036020811015610a1d57600080fd5b810190602081018135600160201b811115610a3757600080fd5b820183602082011115610a4957600080fd5b803590602001918460018302840111600160201b83111715610a6a57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506126e7945050505050565b348015610ab757600080fd5b50610437600480360360c0811015610ace57600080fd5b810190602081018135600160201b811115610ae857600080fd5b820183602082011115610afa57600080fd5b803590602001918460018302840111600160201b83111715610b1b57600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092956001600160a01b0385358116966020870135966040810135151596506060810135909216945091925060a081019060800135600160201b811115610b9357600080fd5b820183602082011115610ba557600080fd5b803590602001918460018302840111600160201b83111715610bc657600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612757945050505050565b348015610c1357600080fd5b50610514612ce6565b348015610c2857600080fd5b50610514612cec565b348015610c3d57600080fd5b50610c6460048036036020811015610c5457600080fd5b50356001600160a01b0316612cf2565b6040805160ff9092168252519081900360200190f35b348015610c8657600080fd5b50610437612d07565b348015610c9b57600080fd5b506104eb612da5565b348015610cb057600080fd5b5061043760048036036020811015610cc757600080fd5b50351515612dae565b348015610cdc57600080fd5b50610c64612e13565b348015610cf157600080fd5b50610514612e1c565b336000908152600a602052604090205460ff16600114610d61576040805162461bcd60e51b815260206004820152601b60248201527f4f6e6c79206d616e616765722063616e20657865637574652069740000000000604482015290519081900360640190fd5b8451604014610db3576040805162461bcd60e51b8152602060048201526019602482015278119a5e1959081b195b99dd1a081bd9881d1e12d95e4e880d8d603a1b604482015290519081900360640190fd5b600084511180610dc4575060008351115b610dff5760405162461bcd60e51b81526004018080602001828103825260288152602001806142cb6028913960400191505060405180910390fd5b600d856040518082805190602001908083835b60208310610e315780518252601f199092019160209182019101610e12565b51815160209384036101000a600019018019909216911617905292019485525060405193849003019092205460ff16159150610eb69050576040805162461bcd60e51b815260206004820152601e60248201527f5472616e73616374696f6e20686173206265656e20636f6d706c657465640000604482015290519081900360640190fd5b610ec08484612e22565b6000858584866006546040516020018086805190602001908083835b60208310610efb5780518252601f199092019160209182019101610edc565b51815160209384036101000a60001901801990921691161790528851919093019288810192500280838360005b83811015610f40578181015183820152602001610f28565b505050509050018460ff1660ff1660f81b8152600101838051906020019060200280838360005b83811015610f7f578181015183820152602001610f67565b50505050919091019283525050604080518083038152602092830182528051908301206000818152600c90935291205490955060ff1615935061100292505050576040805162461bcd60e51b8152602060048201526012602482015271496e76616c6964207369676e61747572657360701b604482015290519081900360640190fd5b61100c8183613125565b611055576040805162461bcd60e51b815260206004820152601560248201527415985b1a59081cda59db985d1d5c995cc819985a5b605a1b604482015290519081900360640190fd5b61105e8461319d565b61106785613326565b600b54611073906133ee565b6007805460ff191660ff929092169190911790556110938682600161344e565b7fac9b82db4e104d515319a481096bfd91a4f40ee10837d5a2c8d51b9a03dc48ae866040518080602001828103825283818151815260200191508051906020019080838360005b838110156110f25781810151838201526020016110da565b50505050905090810190601f16801561111f5780820380516001836020036101000a031916815260200191505b509250505060405180910390a1505050505050565b6000338361117e576040805162461bcd60e51b815260206004820152601260248201527111549493d48e8816995c9bc8185b5bdd5b9d60721b604482015290519081900360640190fd5b6001600160a01b0383161561144c5734156111ca5760405162461bcd60e51b815260040180806020018281038252602481526020018061412c6024913960400191505060405180910390fd5b6111dc836001600160a01b03166134e2565b6112175760405162461bcd60e51b815260040180806020018281038252602581526020018061438f6025913960400191505060405180910390fd5b60408051636eb1769f60e11b81526001600160a01b038381166004830152306024830152915185926000929084169163dd62ed3e91604480820192602092909190829003018186803b15801561126c57600080fd5b505afa158015611280573d6000803e3d6000fd5b505050506040513d602081101561129657600080fd5b50519050858110156112d95760405162461bcd60e51b81526004018080602001828103825260228152602001806142466022913960400191505060405180910390fd5b6000826001600160a01b03166370a08231856040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561133157600080fd5b505afa158015611345573d6000803e3d6000fd5b505050506040513d602081101561135b57600080fd5b50519050868110156113b4576040805162461bcd60e51b815260206004820152601e60248201527f4e6f20656e6f7567682062616c616e6365206f662074686520746f6b656e0000604482015290519081900360640190fd5b6113d16001600160a01b03841685308a600f63ffffffff61351e16565b6113da866124eb565b15611444576000869050806001600160a01b03166342966c68896040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561142a57600080fd5b505af115801561143e573d6000803e3d6000fd5b50505050505b5050506114a0565b8334146114a0576040805162461bcd60e51b815260206004820152601d60248201527f496e636f6e73697374656e637920457468657265756d20616d6f756e74000000604482015290519081900360640190fd5b7f5ddf9724d8fe5d9e12499be2867f93d41a582733dcd65f74a486ad7e306671468186868660405180856001600160a01b03166001600160a01b0316815260200180602001848152602001836001600160a01b03166001600160a01b03168152602001828103825285818151815260200191508051906020019080838360005b83811015611538578181015183820152602001611520565b50505050905090810190601f1680156115655780820380516001836020036101000a031916815260200191505b509550505050505060405180910390a1506001949350505050565b60055481565b60075461010090046001600160a01b031633146115d8576040805162461bcd60e51b8152602060048201526019602482015260008051602061431f833981519152604482015290519081900360640190fd5b60015460ff16611618576040805162461bcd60e51b815260206004820152600660248201526511195b9a595960d21b604482015290519081900360640190fd5b60015461010090046001600160a01b03166116645760405162461bcd60e51b81526004018080602001828103825260238152602001806142686023913960400191505060405180910390fd5b6001546040516001600160a01b0361010090920491909116904780156108fc02916000818181858888f193505050501580156116a4573d6000803e3d6000fd5b50565b60045481565b60105460ff1681565b60015461010090046001600160a01b031681565b60075461010090046001600160a01b0316331461171c576040805162461bcd60e51b8152602060048201526019602482015260008051602061431f833981519152604482015290519081900360640190fd5b306001600160a01b0382161415611773576040805162461bcd60e51b81526020600482015260166024820152752237903737ba3434b73390313c903cb7bab939b2b63360511b604482015290519081900360640190fd5b611785816001600160a01b03166134e2565b6117c05760405162461bcd60e51b815260040180806020018281038252602581526020018061438f6025913960400191505060405180910390fd5b6117c9816124eb565b156118055760405162461bcd60e51b81526004018080602001828103825260288152602001806140b26028913960400191505060405180910390fd5b6001600160a01b03166000908152600e60205260409020805460ff19166001179055565b60105460009060ff1661187a576040805162461bcd60e51b815260206004820152601460248201527321b937b9b9a7baba24a49d102737ba1037b832b760611b604482015290519081900360640190fd5b3360006001600160a01b03851615611b5b57600086116118d6576040805162461bcd60e51b815260206004820152601260248201527111549493d48e8816995c9bc8185b5bdd5b9d60721b604482015290519081900360640190fd5b6118e8856001600160a01b03166134e2565b6119235760405162461bcd60e51b815260040180806020018281038252602581526020018061438f6025913960400191505060405180910390fd5b60408051636eb1769f60e11b81526001600160a01b038481166004830152306024830152915187926000929084169163dd62ed3e91604480820192602092909190829003018186803b15801561197857600080fd5b505afa15801561198c573d6000803e3d6000fd5b505050506040513d60208110156119a257600080fd5b50519050878110156119e55760405162461bcd60e51b81526004018080602001828103825260228152602001806142466022913960400191505060405180910390fd5b6000826001600160a01b03166370a08231866040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015611a3d57600080fd5b505afa158015611a51573d6000803e3d6000fd5b505050506040513d6020811015611a6757600080fd5b5051905088811015611ac0576040805162461bcd60e51b815260206004820152601e60248201527f4e6f20656e6f7567682062616c616e6365206f662074686520746f6b656e0000604482015290519081900360640190fd5b611add6001600160a01b03841686308c600f63ffffffff61351e16565b611ae6886124eb565b15611b50576000889050806001600160a01b03166342966c688b6040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b158015611b3657600080fd5b505af1158015611b4a573d6000803e3d6000fd5b50505050505b889350505050611bba565b600034118015611b69575085155b611bba576040805162461bcd60e51b815260206004820152601e60248201527f43726f73734f757449493a20496c6c6567616c2065746820616d6f756e740000604482015290519081900360640190fd5b7f692e6a6e27573f2a2a757e34cb16ae101c5fca8834f9b8a6cdbcf64b8450d87082888388348960405180876001600160a01b03166001600160a01b0316815260200180602001868152602001856001600160a01b03166001600160a01b0316815260200184815260200180602001838103835288818151815260200191508051906020019080838360005b83811015611c5e578181015183820152602001611c46565b50505050905090810190601f168015611c8b5780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b83811015611cbe578181015183820152602001611ca6565b50505050905090810190601f168015611ceb5780820380516001836020036101000a031916815260200191505b509850505050505050505060405180910390a15060019695505050505050565b60075461010090046001600160a01b03163314611d5d576040805162461bcd60e51b8152602060048201526019602482015260008051602061431f833981519152604482015290519081900360640190fd5b306001600160a01b0382161415611db4576040805162461bcd60e51b81526020600482015260166024820152752237903737ba3434b73390313c903cb7bab939b2b63360511b604482015290519081900360640190fd5b611dc6816001600160a01b03166134e2565b611e015760405162461bcd60e51b815260040180806020018281038252602581526020018061438f6025913960400191505060405180910390fd5b6001600160a01b03166000908152600f60205260409020805460ff19166001179055565b336000908152600a602052604090205460ff16600114611e8c576040805162461bcd60e51b815260206004820152601b60248201527f4f6e6c79206d616e616765722063616e20657865637574652069740000000000604482015290519081900360640190fd5b8251604014611ede576040805162461bcd60e51b8152602060048201526019602482015278119a5e1959081b195b99dd1a081bd9881d1e12d95e4e880d8d603a1b604482015290519081900360640190fd5b600d836040518082805190602001908083835b60208310611f105780518252601f199092019160209182019101611ef1565b51815160209384036101000a600019018019909216911617905292019485525060405193849003019092205460ff16159150611f959050576040805162461bcd60e51b815260206004820152601e60248201527f5472616e73616374696f6e20686173206265656e20636f6d706c657465640000604482015290519081900360640190fd5b60015460ff1615611fe4576040805162461bcd60e51b8152602060048201526014602482015273125d081a185cc81899595b881d5c19dc9859195960621b604482015290519081900360640190fd5b611ff6826001600160a01b03166134e2565b6120315760405162461bcd60e51b815260040180806020018281038252602581526020018061438f6025913960400191505060405180910390fd5b600083836006546040516020018084805190602001908083835b6020831061206a5780518252601f19909201916020918201910161204b565b51815160209384036101000a600019018019909216911617905260609690961b6bffffffffffffffffffffffff1916920191825250601480820193909352604080518083039094018452603490910181528251928401929092206000818152600c909452919092205490935060ff161591506121249050576040805162461bcd60e51b8152602060048201526012602482015271496e76616c6964207369676e61747572657360701b604482015290519081900360640190fd5b61212e8183613125565b612177576040805162461bcd60e51b815260206004820152601560248201527415985b1a59081cda59db985d1d5c995cc819985a5b605a1b604482015290519081900360640190fd5b6001805460ff19168117610100600160a81b0319166101006001600160a01b038616021781556121aa908590839061344e565b7f5e06c4b22547d430736ce834764dbfee08f1c4cf7ae3d53178aa56effa593ed0846040518080602001828103825283818151815260200191508051906020019080838360005b838110156122095781810151838201526020016121f1565b50505050905090810190601f1680156122365780820380516001836020036101000a031916815260200191505b509250505060405180910390a150505050565b60075461010090046001600160a01b0316331461229b576040805162461bcd60e51b8152602060048201526019602482015260008051602061431f833981519152604482015290519081900360640190fd5b60015460ff166122db576040805162461bcd60e51b815260206004820152600660248201526511195b9a595960d21b604482015290519081900360640190fd5b60015461010090046001600160a01b03166123275760405162461bcd60e51b81526004018080602001828103825260238152602001806142686023913960400191505060405180910390fd5b306001600160a01b038216141561237e576040805162461bcd60e51b81526020600482015260166024820152752237903737ba3434b73390313c903cb7bab939b2b63360511b604482015290519081900360640190fd5b612390816001600160a01b03166134e2565b6123cb5760405162461bcd60e51b815260040180806020018281038252602581526020018061438f6025913960400191505060405180910390fd5b604080516370a0823160e01b8152306004820152905182916000916001600160a01b038416916370a08231916024808301926020929190829003018186803b15801561241657600080fd5b505afa15801561242a573d6000803e3d6000fd5b505050506040513d602081101561244057600080fd5b5051905060015461246b906001600160a01b038481169161010090041683600f63ffffffff61358016565b612474836124eb565b156124e657600154604080516301fc6bd160e21b81526001600160a01b0361010090930483166004820152905185928316916307f1af4491602480830192600092919082900301818387803b1580156124cc57600080fd5b505af11580156124e0573d6000803e3d6000fd5b50505050505b505050565b6001600160a01b0381166000908152600e602052604090205460ff1615155b919050565b6001600160a01b03166000908152600a602052604090205460ff1660011490565b60075461010090046001600160a01b031681565b60075461010090046001600160a01b03163314612596576040805162461bcd60e51b8152602060048201526019602482015260008051602061431f833981519152604482015290519081900360640190fd5b6001600160a01b03166000908152600f60205260409020805460ff19169055565b6060600b80548060200260200160405190810160405280929190818152602001828054801561260f57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116125f1575b505050505090505b90565b60075461010090046001600160a01b0316331461266c576040805162461bcd60e51b8152602060048201526019602482015260008051602061431f833981519152604482015290519081900360640190fd5b612675816124eb565b6126c6576040805162461bcd60e51b815260206004820152601e60248201527f546869732061646472657373206973206e6f7420726567697374657265640000604482015290519081900360640190fd5b6001600160a01b03166000908152600e60205260409020805460ff19169055565b600080600d836040518082805190602001908083835b6020831061271c5780518252601f1990920191602091820191016126fd565b51815160209384036101000a600019018019909216911617905292019485525060405193849003019092205460ff1692909211949350505050565b600260005414156127af576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026000908155338152600a602052604090205460ff1660011461281a576040805162461bcd60e51b815260206004820152601b60248201527f4f6e6c79206d616e616765722063616e20657865637574652069740000000000604482015290519081900360640190fd5b855160401461286c576040805162461bcd60e51b8152602060048201526019602482015278119a5e1959081b195b99dd1a081bd9881d1e12d95e4e880d8d603a1b604482015290519081900360640190fd5b6001600160a01b0385166128b15760405162461bcd60e51b81526004018080602001828103825260268152602001806140da6026913960400191505060405180910390fd5b600084116128f05760405162461bcd60e51b815260040180806020018281038252602881526020018061421e6028913960400191505060405180910390fd5b600d866040518082805190602001908083835b602083106129225780518252601f199092019160209182019101612903565b51815160209384036101000a600019018019909216911617905292019485525060405193849003019092205460ff161591506129a79050576040805162461bcd60e51b815260206004820152601e60248201527f5472616e73616374696f6e20686173206265656e20636f6d706c657465640000604482015290519081900360640190fd5b82156129bd576129b88286866135d3565b6129fc565b834710156129fc5760405162461bcd60e51b815260040180806020018281038252603f815260200180614150603f913960400191505060405180910390fd5b600086868686866006546040516020018087805190602001908083835b60208310612a385780518252601f199092019160209182019101612a19565b51815160209384036101000a60001901801990921691161790526060998a1b6bffffffffffffffffffffffff1990811692909401918252601482019890985295151560f81b6034870152509290951b9091166035830152604980830191909152604080518084039092018252606990920182528051908301206000818152600c90935291205490935060ff16159150612b0f9050576040805162461bcd60e51b8152602060048201526012602482015271496e76616c6964207369676e61747572657360701b604482015290519081900360640190fd5b612b198183613125565b612b62576040805162461bcd60e51b815260206004820152601560248201527415985b1a59081cda59db985d1d5c995cc819985a5b605a1b604482015290519081900360640190fd5b8315612b7857612b7383878761379d565b612c33565b84471015612bb75760405162461bcd60e51b815260040180806020018281038252603f815260200180614150603f913960400191505060405180910390fd5b6040516001600160a01b0387169086156108fc029087906000818181858888f19350505050158015612bed573d6000803e3d6000fd5b50604080516001600160a01b03881681526020810187905281517fc95f8b91b103304386b955ef73fadac189f8ad66b33369b6c34a17a60db7bd0a929181900390910190a15b612c3f8782600161344e565b7f8ed8b1f0dd3babfdf1477ba2b27a5b0d2f1c9148448fd22cf2c75e658293c7b1876040518080602001828103825283818151815260200191508051906020019080838360005b83811015612c9e578181015183820152602001612c86565b50505050905090810190601f168015612ccb5780820380516001836020036101000a031916815260200191505b509250505060405180910390a1505060016000555050505050565b60035481565b60065481565b600f6020526000908152604090205460ff1681565b60075461010090046001600160a01b03163314612d59576040805162461bcd60e51b8152602060048201526019602482015260008051602061431f833981519152604482015290519081900360640190fd5b60015460ff16612d99576040805162461bcd60e51b815260206004820152600660248201526511195b9a595960d21b604482015290519081900360640190fd5b6001805460ff19169055565b60015460ff1681565b60075461010090046001600160a01b03163314612e00576040805162461bcd60e51b8152602060048201526019602482015260008051602061431f833981519152604482015290519081900360640190fd5b6010805460ff1916911515919091179055565b60075460ff1681565b60025481565b815160005b81811015612efa576000848281518110612e3d57fe5b6020026020010151905060006001600160a01b0316816001600160a01b03161415612e995760405162461bcd60e51b815260040180806020018281038252602481526020018061418f6024913960400191505060405180910390fd5b6001600160a01b0381166000908152600a602052604090205460ff1615612ef15760405162461bcd60e51b815260040180806020018281038252604081526020018061428b6040913960400191505060405180910390fd5b50600101612e27565b50612f0483613905565b612f3f5760405162461bcd60e51b815260040180806020018281038252602c815260200180614100602c913960400191505060405180910390fd5b600754612f5a9061010090046001600160a01b0316846139d5565b612f955760405162461bcd60e51b81526004018080602001828103825260268152602001806143696026913960400191505060405180910390fd5b612f9e82613905565b612fd95760405162461bcd60e51b815260040180806020018281038252602c8152602001806142f3602c913960400191505060405180910390fd5b815160005b818110156130d5576000848281518110612ff457fe5b6020908102919091018101516001600160a01b0381166000908152600890925260409091205490915060ff1615613072576040805162461bcd60e51b815260206004820152601760248201527f43616e277420657869742073656564206d616e61676572000000000000000000604482015290519081900360640190fd5b6001600160a01b0381166000908152600a602052604090205460ff166001146130cc5760405162461bcd60e51b81526004018080602001828103825260448152602001806141da6044913960600191505060405180910390fd5b50600101612fde565b5060025483518551600b540103111561311f5760405162461bcd60e51b81526004018080602001828103825260278152602001806141b36027913960400191505060405180910390fd5b50505050565b60006103cf8251111561317f576040805162461bcd60e51b815260206004820152601d60248201527f4d6178206c656e677468206f66207369676e6174757265733a20393735000000604482015290519081900360640190fd5b600061318b8484613a51565b60075460ff1611159150505b92915050565b80516131a8576116a4565b60005b81518110156131f757600a60008383815181106131c457fe5b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191690556001016131ab565b5060005b600b5481101561327157600a6000600b838154811061321657fe5b60009182526020808320909101546001600160a01b0316835282019290925260400190205460ff1661326957600b818154811061324f57fe5b600091825260209091200180546001600160a01b03191690555b6001016131fb565b50601060005b600b54811015613310576000600b828154811061329057fe5b6000918252602090912001546001600160a01b03169050806132bf5782601014156132b9578192505b50613308565b826010146133065780600b84815481106132d557fe5b600091825260209091200180546001600160a01b0319166001600160a01b0392909216919091179055600192909201915b505b600101613277565b508151600b805491909103906124e69082614051565b8051613331576116a4565b60005b81518110156133ea57600082828151811061334b57fe5b6020908102919091018101516001600160a01b0381166000908152600a90925260409091205490915060ff166133e1576001600160a01b0381166000818152600a60205260408120805460ff19166001908117909155600b805491820181559091527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90180546001600160a01b03191690911790555b50600101613334565b5050565b600080821161343b576040805162461bcd60e51b815260206004820152601460248201527326b0b730b3b2b91021b0b713ba1032b6b83a3c9760611b604482015290519081900360640190fd5b6004548202606301606481049392505050565b80600d846040518082805190602001908083835b602083106134815780518252601f199092019160209182019101613462565b51815160209384036101000a600019018019909216911617905292019485525060408051948590038201909420805460ff1990811660ff978816179091556000978852600c9091529290952080549092169390921692909217909155505050565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081811480159061351657508115155b949350505050565b604080516001600160a01b0386811660248301528516604482015260648082018590528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b17905261357990869083613bfc565b5050505050565b604080516001600160a01b038516602482015260448082018590528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261311f90859083613bfc565b6001600160a01b0382166136185760405162461bcd60e51b815260040180806020018281038252602381526020018061408f6023913960400191505060405180910390fd5b306001600160a01b038416141561366f576040805162461bcd60e51b81526020600482015260166024820152752237903737ba3434b73390313c903cb7bab939b2b63360511b604482015290519081900360640190fd5b613681836001600160a01b03166134e2565b6136bc5760405162461bcd60e51b815260040180806020018281038252602581526020018061438f6025913960400191505060405180910390fd5b6136c5836124eb565b156136cf576124e6565b604080516370a0823160e01b8152306004820152905184916000916001600160a01b038416916370a08231916024808301926020929190829003018186803b15801561371a57600080fd5b505afa15801561372e573d6000803e3d6000fd5b505050506040513d602081101561374457600080fd5b5051905082811015613579576040805162461bcd60e51b815260206004820152601a60248201527f4e6f20656e6f7567682062616c616e6365206f6620746f6b656e000000000000604482015290519081900360640190fd5b6137a6836124eb565b1561381b57604080516340c10f1960e01b81526001600160a01b03848116600483015260248201849052915185928316916340c10f1991604480830192600092919082900301818387803b1580156137fd57600080fd5b505af1158015613811573d6000803e3d6000fd5b50505050506124e6565b604080516370a0823160e01b8152306004820152905184916000916001600160a01b038416916370a08231916024808301926020929190829003018186803b15801561386657600080fd5b505afa15801561387a573d6000803e3d6000fd5b505050506040513d602081101561389057600080fd5b50519050828110156138e9576040805162461bcd60e51b815260206004820152601a60248201527f4e6f20656e6f7567682062616c616e6365206f6620746f6b656e000000000000604482015290519081900360640190fd5b6135796001600160a01b0383168585600f63ffffffff61358016565b6000805b82518110156139cc57600083828151811061392057fe5b6020026020010151905060006001600160a01b0316816001600160a01b0316141561394b57506139cc565b600182015b84518110156139c257600085828151811061396757fe5b6020026020010151905060006001600160a01b0316816001600160a01b0316141561399257506139c2565b806001600160a01b0316836001600160a01b031614156139b957600094505050505061250a565b50600101613950565b5050600101613909565b50600192915050565b600080805b8351811015613a46578381815181106139ef57fe5b6020026020010151915060006001600160a01b0316826001600160a01b03161415613a1957613a46565b846001600160a01b0316826001600160a01b03161415613a3e57600092505050613197565b6001016139da565b506001949350505050565b600554815160009182918291613a6d919063ffffffff613ddc16565b9050606081604051908082528060200260200182016040528015613a9b578160200160208202803883390190505b509050600080805b84811015613b94576060613ac4846005548b613e259092919063ffffffff16565b90506000613ad28b83613ea5565b90506001600160a01b038116613b22576040805162461bcd60e51b815260206004820152601060248201526f29b4b3b730ba3ab932b99032b93937b960811b604482015290519081900360640190fd5b6001600160a01b0381166000908152600a602052604090205460ff1660011415613b825785516001988901988501948291889160ff16908110613b6157fe5b60200260200101906001600160a01b031690816001600160a01b0316815250505b50506005549290920191600101613aa3565b506000613ba084613905565b90506060935080613bef576040805162461bcd60e51b81526020600482015260146024820152735369676e617475726573206475706c696361746560601b604482015290519081900360640190fd5b5093979650505050505050565b613c0e836001600160a01b03166134e2565b613c5f576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060846001600160a01b0316846040518082805190602001908083835b60208310613c9d5780518252601f199092019160209182019101613c7e565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114613cff576040519150601f19603f3d011682016040523d82523d6000602084013e613d04565b606091505b509150915081613d5b576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b6001600160a01b03851660009081526020849052604090205460ff1615613d835750506124e6565b80511561357957808060200190516020811015613d9f57600080fd5b50516135795760405162461bcd60e51b815260040180806020018281038252602a81526020018061433f602a913960400191505060405180910390fd5b6000613e1e83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613faf565b9392505050565b606081830184511015613e3757600080fd5b606082158015613e5257604051915060208201604052613e9c565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015613e8b578051835260209283019201613e73565b5050858452601f01601f1916604052505b50949350505050565b600080600080600554855114613ec15760009350505050613197565b50505060208201516040830151606084015160001a7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115613f0a5760009350505050613197565b601b8160ff161015613f1a57601b015b8060ff16601b14158015613f3257508060ff16601c14155b15613f435760009350505050613197565b6040805160008152602080820180845289905260ff8416828401526060820186905260808201859052915160019260a0808401939192601f1981019281900390910190855afa158015613f9a573d6000803e3d6000fd5b5050604051601f190151979650505050505050565b6000818361403b5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015614000578181015183820152602001613fe8565b50505050905090810190601f16801561402d5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50600083858161404757fe5b0495945050505050565b8154818355818111156124e6576000838152602090206124e691810190830161261791905b8082111561408a5760008155600101614076565b509056fe45524332303a207472616e7366657220746f20746865207a65726f20616464726573735468697320616464726573732068617320616c7265616479206265656e207265676973746572656457697468647261773a207472616e7366657220746f20746865207a65726f20616464726573734475706c696361746520706172616d657465727320666f7220746865206164647265737320746f206a6f696e45524332303a20446f6573206e6f742061636365707420457468657265756d20436f696e5468697320636f6e7472616374206164647265737320646f6573206e6f7420686176652073756666696369656e742062616c616e6365206f662065746865724552524f523a204465746563746564207a65726f206164647265737320696e2061646473457863656564656420746865206d6178696d756d206e756d626572206f66206d616e61676572735468657265206172652061646472657373657320696e207468652065786974696e672061646472657373206c697374207468617420617265206e6f74206d616e616765725769746864726177616c20616d6f756e74206d7573742062652067726561746572207468616e20304e6f20656e6f75676820616d6f756e7420666f7220617574686f72697a6174696f6e4552524f523a207472616e7366657220746f20746865207a65726f20616464726573735468652061646472657373206c6973742074686174206973206265696e6720616464656420616c7265616479206578697374732061732061206d616e61676572546865726520617265206e6f206d616e6167657273206a6f696e696e67206f722065786974696e674475706c696361746520706172616d657465727320666f7220746865206164647265737320746f20657869744f6e6c79206f776e65722063616e2065786563757465206974000000000000005361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564436f6e74726163742063726561746f722063616e6e6f7420616374206173206d616e616765725468652061646472657373206973206e6f74206120636f6e74726163742061646472657373a265627a7a7231582086b5ef132f949ad96c9c48c21f211afdf94866fd5afc7771f740c66e4cec878264736f6c63430005110032