Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
0x60806040 | 15588390 | 676 days ago | IN | 0 ETH | 0.02131359 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
Vault
Compiler Version
v0.6.12+commit.27d51765
Optimization Enabled:
Yes with 1000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.6.12; pragma experimental ABIEncoderV2; import "./IERC20.sol"; // import "hardhat/console.sol"; import { Address } from "@openzeppelin/contracts/utils/Address.sol"; import "./trade_utils.sol"; /** * Math operations with safety checks */ library SafeMath { string private constant ERROR_MESSAGE = "SafeMath exception"; function safeMul(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a * b; require(a == 0 || c / a == b, ERROR_MESSAGE); return c; } function safeDiv(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0, ERROR_MESSAGE); uint256 c = a / b; require(a == b * c + a % b, ERROR_MESSAGE); return c; } function safeSub(uint256 a, uint256 b) internal pure returns (uint256) { require(b <= a, ERROR_MESSAGE); return a - b; } function safeAdd(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c>=a && c>=b, ERROR_MESSAGE); return c; } } /** * @title Counters * @author Matt Condon (@shrugs) * @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number * of elements in a mapping, issuing ERC721 ids, or counting request ids. * * Include with `using Counters for Counters.Counter;` * Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the {SafeMath} * overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never * directly accessed. */ library Counters { using SafeMath for uint256; struct Counter { // This variable should never be directly accessed by users of the library: interactions must be restricted to // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add // this feature: see https://github.com/ethereum/solidity/issues/4637 uint256 _value; // default: 0 } function current(Counter storage counter) internal view returns (uint256) { return counter._value; } function increment(Counter storage counter) internal { // The {SafeMath} overflow check can be skipped here, see the comment at the top counter._value += 1; } function decrement(Counter storage counter) internal { counter._value = counter._value.safeSub(1); } } /** * @dev Interface of the contract capable of checking if an instruction is * confirmed over at Incognito Chain */ interface Incognito { function instructionApproved( bool, bytes32, uint, bytes32[] calldata, bool[] calldata, bytes32, bytes32, uint[] calldata, uint8[] calldata, bytes32[] calldata, bytes32[] calldata ) external view returns (bool); } /** * @dev Interface of the previous Vault contract to query burn proof status */ interface Withdrawable { function isWithdrawed(bytes32) external view returns (bool); function isSigDataUsed(bytes32) external view returns (bool); function getDepositedBalance(address, address) external view returns (uint); function updateAssets(address[] calldata, uint[] calldata) external returns (bool); function paused() external view returns (bool); } /** * @dev Responsible for holding the assets and issue minting instruction to * Incognito Chain. Also, when presented with a burn proof created over at * Incognito Chain, releases the tokens back to user */ contract Vault { using SafeMath for uint; using Counters for Counters.Counter; /** * @dev Storage slot with the incognito proxy. * This is the keccak-256 hash of "eip1967.proxy.incognito." subtracted by 1 */ bytes32 private constant _INCOGNITO_SLOT = 0x62135fc083646fdb4e1a9d700e351b886a4a5a39da980650269edd1ade91ffd2; address constant public ETH_TOKEN = 0x0000000000000000000000000000000000000000; /** * @dev Storage variables for Vault * This section is APPEND-ONLY, in order to preserve upgradeability * since we use Proxy Pattern */ mapping(bytes32 => bool) public withdrawed; mapping(bytes32 => bool) public sigDataUsed; // address => token => amount mapping(address => mapping(address => uint)) public withdrawRequests; mapping(address => mapping(address => bool)) public migration; mapping(address => uint) public totalDepositedToSCAmount; Withdrawable public prevVault; bool public notEntered; bool public isInitialized; /** * @dev Added in Storage Layout version : 2.0 */ uint8 constant public CURRENT_NETWORK_ID = 1; // Ethereum uint8 constant public BURN_REQUEST_METADATA_TYPE = 241; uint8 constant public BURN_TO_CONTRACT_REQUEST_METADATA_TYPE = 243; uint8 constant public BURN_CALL_REQUEST_METADATA_TYPE = 158; Counters.Counter private idCounter; address public regulator; uint256 public storageLayoutVersion; address public executor; /** * @dev END Storage variables version : 2.0 */ /** * @dev END Storage variables */ struct BurnInstData { uint8 meta; // type of the instruction uint8 shard; // ID of the Incognito shard containing the instruction, must be 1 address token; // ETH address of the token contract (0x0 for ETH) address payable to; // ETH address of the receiver of the token uint amount; // burned amount (on Incognito) bytes32 itx; // Incognito's burning tx } struct RedepositOptions { address redepositToken; bytes redepositIncAddress; address payable withdrawAddress; } struct ShieldInfo { address sender; // the guy shield request bytes32 tx; // txid which sent fund to core team's addresses } enum Prefix { ETHEREUM_EXECUTE_SIGNATURE, ETHEREUM_REQUEST_WITHDRAW_SIGNATURE, BSC_EXECUTE_SIGNATURE, BSC_REQUEST_WITHDRAW_SIGNATURE, PLG_EXECUTE_SIGNATURE, PLG_REQUEST_WITHDRAW_SIGNATURE, FTM_EXECUTE_SIGNATURE, FTM_REQUEST_WITHDRAW_SIGNATURE } // error code enum Errors { EMPTY, NO_REENTRANCE, MAX_UINT_REACHED, VALUE_OVER_FLOW, INTERNAL_TX_ERROR, ALREADY_USED, // 5 INVALID_DATA, TOKEN_NOT_ENOUGH, WITHDRAW_REQUEST_TOKEN_NOT_ENOUGH, INVALID_RETURN_DATA, NOT_EQUAL, // 10 NULL_VALUE, ONLY_PREVAULT, PREVAULT_NOT_PAUSED, SAFEMATH_EXCEPTION, ALREADY_INITIALIZED, // 15 INVALID_SIGNATURE, NOT_AUTHORISED, ALREADY_UPGRADED, INVALID_DATA_BURN_CALL_INST, ONLY_SELF_CALL } event Deposit(address token, string incognitoAddress, uint amount); event Withdraw(address token, address to, uint amount); event UpdateTokenTotal(address[] assets, uint[] amounts); event UpdateIncognitoProxy(address newIncognitoProxy); event Redeposit(address token, bytes redepositIncAddress, uint256 amount, bytes32 itx); event DepositV2(address token, string incognitoAddress, uint amount, uint256 depositID); event ExecuteFnLog(bytes32 id, uint256 phaseID, bytes errorData); /** * modifier for contract version */ modifier onlyPreVault(){ require(address(prevVault) != address(0x0) && msg.sender == address(prevVault), errorToString(Errors.ONLY_PREVAULT)); _; } /** * @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(notEntered, errorToString(Errors.NO_REENTRANCE)); // Any calls to nonReentrant after this point will fail notEntered = false; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) notEntered = true; } /** * @dev Creates new Vault to hold assets for Incognito Chain * @param _prevVault: previous version of the Vault to refer back if necessary * @param _regulator: ... * @param _executor: helper contract to perform external call from * After migrating all assets to a new Vault, we still need to refer * back to previous Vault to make sure old withdrawals aren't being reused */ function initialize(address _prevVault, address _regulator, address _executor) external { require(!isInitialized, errorToString(Errors.ALREADY_INITIALIZED)); prevVault = Withdrawable(_prevVault); isInitialized = true; notEntered = true; require(regulator == address(0x0), errorToString(Errors.NOT_AUTHORISED)); regulator = _regulator; executor = _executor; storageLayoutVersion = 2; } /** * @dev upgrade helper for storage layout version 2 * @param _regulator: ... * @param _executor: helper contract to perform external call from */ function upgradeVaultStorage(address _regulator, address _executor) external { // storageLayoutVersion is a new variable introduced in this storage layout version, then set to 2 to match the storage layout version itself require(storageLayoutVersion == 0, errorToString(Errors.ALREADY_UPGRADED)); // make sure the version increase can only happen once storageLayoutVersion = 2; require(regulator == address(0x0), errorToString(Errors.NOT_AUTHORISED)); regulator = _regulator; executor = _executor; } /** * @dev Returns the current incognito proxy. */ function _incognito() internal view returns (address icg) { bytes32 slot = _INCOGNITO_SLOT; // solhint-disable-next-line no-inline-assembly assembly { icg := sload(slot) } } /** * @dev Makes a ETH deposit to the vault to mint pETH over at Incognito Chain * @notice This only works when the contract is not Paused * @notice The maximum amount to deposit is capped since Incognito balance is stored as uint64 * @param incognitoAddress: Incognito Address to receive pETH * @param txId: move fund transaction hash * @param signData: regulator signature */ function deposit(string calldata incognitoAddress, bytes32 txId, bytes calldata signData) external payable nonReentrant { require(address(this).balance <= 10 ** 27, errorToString(Errors.MAX_UINT_REACHED)); verifyRegulator(txId, signData); emit Deposit(ETH_TOKEN, incognitoAddress, msg.value); } /** * @dev Makes a ERC20 deposit to the vault to mint pERC20 over at Incognito Chain * @notice This only works when the contract is not Paused * @notice The maximum amount to deposit is capped since Incognito balance is stored as uint64 * @notice Before calling this function, enough ERC20 must be allowed to * tranfer from msg.sender to this contract * @param token: address of the ERC20 token * @param amount: to deposit to the vault and mint on Incognito Chain * @param incognitoAddress: Incognito Address to receive pERC20 * @param txId: move fund transaction hash * @param signData: regulator signature */ function depositERC20(address token, uint amount, string calldata incognitoAddress, bytes32 txId, bytes calldata signData) external nonReentrant { verifyRegulator(txId, signData); IERC20 erc20Interface = IERC20(token); uint8 decimals = getDecimals(address(token)); uint tokenBalance = erc20Interface.balanceOf(address(this)); uint beforeTransfer = tokenBalance; uint emitAmount = amount; if (decimals > 9) { emitAmount = emitAmount / (10 ** (uint(decimals) - 9)); tokenBalance = tokenBalance / (10 ** (uint(decimals) - 9)); } require(emitAmount <= 10 ** 18 && tokenBalance <= 10 ** 18 && emitAmount.safeAdd(tokenBalance) <= 10 ** 18, errorToString(Errors.VALUE_OVER_FLOW)); erc20Interface.transferFrom(msg.sender, address(this), amount); require(checkSuccess(), errorToString(Errors.INTERNAL_TX_ERROR)); require(balanceOf(token).safeSub(beforeTransfer) == amount, errorToString(Errors.NOT_EQUAL)); emit Deposit(token, incognitoAddress, emitAmount); } /** * @dev Makes a ETH deposit to the vault to mint pETH over at Incognito Chain * @notice This only works when the contract is not Paused * @notice The maximum amount to deposit is capped since Incognito balance is stored as uint64 * @param incognitoAddress: Incognito Address to receive pETH */ function deposit_V2(string calldata incognitoAddress, bytes32 txId, bytes calldata signData) external payable nonReentrant { require(address(this).balance <= 10 ** 27, errorToString(Errors.MAX_UINT_REACHED)); verifyRegulator(txId, signData); emit DepositV2(ETH_TOKEN, incognitoAddress, msg.value, idCounter.current()); idCounter.increment(); } /** * @dev Makes a ERC20 deposit to the vault to mint pERC20 over at Incognito Chain * @notice This only works when the contract is not Paused * @notice The maximum amount to deposit is capped since Incognito balance is stored as uint64 * @notice Before calling this function, enough ERC20 must be allowed to * tranfer from msg.sender to this contract * @param token: address of the ERC20 token * @param amount: to deposit to the vault and mint on Incognito Chain * @param incognitoAddress: Incognito Address to receive pERC20 */ function depositERC20_V2(address token, uint amount, string calldata incognitoAddress, bytes32 txId, bytes calldata signData) external nonReentrant { verifyRegulator(txId, signData); IERC20 erc20Interface = IERC20(token); uint8 decimals = getDecimals(address(token)); uint tokenBalance = erc20Interface.balanceOf(address(this)); uint beforeTransfer = tokenBalance; uint emitAmount = amount; if (decimals > 9) { emitAmount = emitAmount / (10 ** (uint(decimals) - 9)); tokenBalance = tokenBalance / (10 ** (uint(decimals) - 9)); } require(emitAmount <= 10 ** 18 && tokenBalance <= 10 ** 18 && emitAmount.safeAdd(tokenBalance) <= 10 ** 18, errorToString(Errors.VALUE_OVER_FLOW)); erc20Interface.transferFrom(msg.sender, address(this), amount); require(checkSuccess(), errorToString(Errors.INTERNAL_TX_ERROR)); require(balanceOf(token).safeSub(beforeTransfer) == amount, errorToString(Errors.NOT_EQUAL)); emit DepositV2(token, incognitoAddress, emitAmount, idCounter.current()); idCounter.increment(); } /** * @dev Checks if a burn proof has been used before * @notice First, we check inside the storage of this contract itself. If the * hash has been used before, we return the result. Otherwise, we query * previous vault recursively until the first Vault (prevVault address is 0x0) * @param hash: of the burn proof * @return bool: whether the proof has been used or not */ function isWithdrawed(bytes32 hash) public view returns(bool) { if (withdrawed[hash]) { return true; } else if (address(prevVault) == address(0)) { return false; } return prevVault.isWithdrawed(hash); } /** * @dev Parses a burn instruction and returns the components * @param inst: the full instruction, containing both metadata and body */ function parseBurnInst(bytes memory inst) public pure returns (BurnInstData memory) { BurnInstData memory data; data.meta = uint8(inst[0]); data.shard = uint8(inst[1]); address token; address payable to; uint amount; bytes32 itx; assembly { // skip first 0x20 bytes (stored length of inst) token := mload(add(inst, 0x22)) // [3:34] to := mload(add(inst, 0x42)) // [34:66] amount := mload(add(inst, 0x62)) // [66:98] itx := mload(add(inst, 0x82)) // [98:130] } data.token = token; data.to = to; data.amount = amount; data.itx = itx; return data; } /** * @dev Parses an extended burn instruction and returns the components * @param inst: the full instruction, containing both metadata and body */ function parseCalldataFromBurnInst(bytes calldata inst) public pure returns (BurnInstData memory, RedepositOptions memory, bytes memory) { require(inst.length >= 296, errorToString(Errors.INVALID_DATA_BURN_CALL_INST)); BurnInstData memory bdata; // layout: meta(1), shard(1), network(1), extToken(32), extCallAddr(32), amount(32), txID(32), recvToken(32), withdrawAddr(32), redepositAddr(101), extCalldata(*) { bdata.meta = uint8(inst[0]); bdata.shard = uint8(inst[1]); uint8 networkID = uint8(inst[2]); require(bdata.meta == BURN_CALL_REQUEST_METADATA_TYPE && bdata.shard == 1 && networkID == CURRENT_NETWORK_ID, errorToString(Errors.INVALID_DATA_BURN_CALL_INST)); } RedepositOptions memory opt; { (bdata.token, bdata.to, bdata.amount, bdata.itx, opt.redepositToken, opt.withdrawAddress) = abi.decode(inst[3:195], (address, address, uint256, bytes32, address, address)); } opt.redepositIncAddress = bytes(inst[195:296]); return (bdata, opt, bytes(inst[296:])); } /** * @dev Verifies that a burn instruction is valid * @notice All params except inst are the list of 2 elements corresponding to * the proof on beacon and bridge * @notice All params are the same as in `withdraw` */ function verifyInst( bytes memory inst, uint heights, bytes32[] memory instPaths, bool[] memory instPathIsLefts, bytes32 instRoots, bytes32 blkData, uint[] memory sigIdxs, uint8[] memory sigVs, bytes32[] memory sigRs, bytes32[] memory sigSs ) view internal { // Each instruction can only by redeemed once bytes32 beaconInstHash = keccak256(abi.encodePacked(inst, heights)); // Verify instruction on beacon require(Incognito(_incognito()).instructionApproved( true, // Only check instruction on beacon beaconInstHash, heights, instPaths, instPathIsLefts, instRoots, blkData, sigIdxs, sigVs, sigRs, sigSs ), errorToString(Errors.INVALID_DATA)); } /** * @dev Withdraws pETH/pIERC20 by providing a burn proof over at Incognito Chain * @notice This function takes a burn instruction on Incognito Chain, checks * for its validity and returns the token back to ETH chain * @notice This only works when the contract is not Paused * @param inst: the decoded instruction as a list of bytes * @param heights: the blocks containing the instruction * @param instPaths: merkle path of the instruction * @param instPathIsLefts: whether each node on the path is the left or right child * @param instRoots: root of the merkle tree contains all instructions * @param blkData: merkle has of the block body * @param sigIdxs: indices of the validators who signed this block * @param sigVs: part of the signatures of the validators * @param sigRs: part of the signatures of the validators * @param sigSs: part of the signatures of the validators */ function withdraw( bytes memory inst, uint heights, bytes32[] memory instPaths, bool[] memory instPathIsLefts, bytes32 instRoots, bytes32 blkData, uint[] memory sigIdxs, uint8[] memory sigVs, bytes32[] memory sigRs, bytes32[] memory sigSs ) public nonReentrant { require(inst.length >= 130, errorToString(Errors.INVALID_DATA)); BurnInstData memory data = parseBurnInst(inst); require(data.meta == BURN_REQUEST_METADATA_TYPE && data.shard == 1, errorToString(Errors.INVALID_DATA)); // Check instruction type // Not withdrawed require(!isWithdrawed(data.itx), errorToString(Errors.ALREADY_USED)); withdrawed[data.itx] = true; // Check if balance is enough if (data.token == ETH_TOKEN) { require(address(this).balance >= data.amount.safeAdd(totalDepositedToSCAmount[data.token]), errorToString(Errors.TOKEN_NOT_ENOUGH)); } else { uint8 decimals = getDecimals(data.token); if (decimals > 9) { data.amount = data.amount.safeMul(10 ** (uint(decimals) - 9)); } require(IERC20(data.token).balanceOf(address(this)) >= data.amount.safeAdd(totalDepositedToSCAmount[data.token]), errorToString(Errors.TOKEN_NOT_ENOUGH)); } verifyInst( inst, heights, instPaths, instPathIsLefts, instRoots, blkData, sigIdxs, sigVs, sigRs, sigSs ); // Send and notify if (data.token == ETH_TOKEN) { (bool success, ) = data.to.call{value: data.amount}(""); require(success, errorToString(Errors.INTERNAL_TX_ERROR)); } else { IERC20(data.token).transfer(data.to, data.amount); require(checkSuccess(), errorToString(Errors.INTERNAL_TX_ERROR)); } emit Withdraw(data.token, data.to, data.amount); } function executeWithBurnProof( bytes calldata inst, uint heights, bytes32[] memory instPaths, bool[] memory instPathIsLefts, bytes32 instRoots, bytes32 blkData, uint[] memory sigIdxs, uint8[] memory sigVs, bytes32[] memory sigRs, bytes32[] memory sigSs ) external nonReentrant { (BurnInstData memory data, RedepositOptions memory rOptions, bytes memory externalCalldata) = parseCalldataFromBurnInst(inst); // parse function also does sanity checks require(!isWithdrawed(data.itx), errorToString(Errors.ALREADY_USED)); // check if txID has been used previously withdrawed[data.itx] = true; // check if vault balance is sufficient if (data.token == ETH_TOKEN) { require(address(this).balance >= data.amount.safeAdd(totalDepositedToSCAmount[data.token]), errorToString(Errors.TOKEN_NOT_ENOUGH)); } else { uint8 decimals = getDecimals(data.token); if (decimals > 9) { data.amount = data.amount.safeMul(10 ** (uint(decimals) - 9)); } require(IERC20(data.token).balanceOf(address(this)) >= data.amount.safeAdd(totalDepositedToSCAmount[data.token]), errorToString(Errors.TOKEN_NOT_ENOUGH)); } verifyInst( inst, heights, instPaths, instPathIsLefts, instRoots, blkData, sigIdxs, sigVs, sigRs, sigSs ); // perform external msgcall try this._callExternal(data.token, data.to, data.amount, externalCalldata, rOptions.redepositToken) returns (uint256 returnedAmount) { if (rOptions.withdrawAddress == address(0)) { // after executing, one can redeposit to Incognito Chain _redeposit(rOptions.redepositToken, rOptions.redepositIncAddress, returnedAmount, data.itx); } else { // alternatively, the received funds can be withdrawn try this._transferExternal(rOptions.redepositToken, rOptions.withdrawAddress, returnedAmount) { emit Withdraw(rOptions.redepositToken, rOptions.withdrawAddress, returnedAmount); } catch (bytes memory lowLevelData) { // upon revert, emit Redeposit event _redeposit(rOptions.redepositToken, rOptions.redepositIncAddress, returnedAmount, data.itx); emit ExecuteFnLog(data.itx, 1, lowLevelData); return; } } } catch (bytes memory lowLevelData) { _redeposit(data.token, rOptions.redepositIncAddress, data.amount, data.itx); emit ExecuteFnLog(data.itx, 0, lowLevelData); return; } } function _redeposit(address token, bytes memory redepositIncAddress, uint256 amount, bytes32 itx) internal { uint emitAmount = amount; if (token == ETH_TOKEN) { require(address(this).balance <= 10 ** 27, errorToString(Errors.MAX_UINT_REACHED)); } else { uint8 decimals = getDecimals(address(token)); if (decimals > 9) { emitAmount = emitAmount / (10 ** (uint(decimals) - 9)); } require(emitAmount <= 10 ** 18, errorToString(Errors.VALUE_OVER_FLOW)); } emit Redeposit(token, redepositIncAddress, emitAmount, itx); } function _transferExternal(address token, address payable to, uint256 amount) external onlySelf() { if (token == ETH_TOKEN) { Address.sendValue(to, amount); } else { IERC20(token).transfer(to, amount); require(checkSuccess(), errorToString(Errors.INTERNAL_TX_ERROR)); } } function _callExternal(address token, address to, uint256 amount, bytes memory externalCalldata, address redepositToken) external onlySelf() returns (uint256) { uint balanceBeforeTrade = balanceOf(redepositToken); bytes memory result; uint256 msgval = 0; if (token == ETH_TOKEN) { msgval = amount; } else { IERC20(token).transfer(executor, amount); require(checkSuccess(), errorToString(Errors.INTERNAL_TX_ERROR)); } result = Executor(executor).execute{value: msgval}(to, externalCalldata); require(result.length == 64, errorToString(Errors.INVALID_RETURN_DATA)); (address returnedTokenAddress, uint returnedAmount) = abi.decode(result, (address, uint)); require(returnedTokenAddress == redepositToken && balanceOf(redepositToken).safeSub(balanceBeforeTrade) == returnedAmount, errorToString(Errors.INVALID_RETURN_DATA)); return returnedAmount; } modifier onlySelf() { require(address(this) == msg.sender, errorToString(Errors.ONLY_SELF_CALL)); _; } /** * @dev Burnt Proof is submited to store burnt amount of p-token/p-ETH and receiver's address * Receiver then can call withdrawRequest to withdraw these token to he/she incognito address. * @notice This function takes a burn instruction on Incognito Chain, checks * for its validity and returns the token back to ETH chain * @notice This only works when the contract is not Paused * @param inst: the decoded instruction as a list of bytes * @param heights: the blocks containing the instruction * @param instPaths: merkle path of the instruction * @param instPathIsLefts: whether each node on the path is the left or right child * @param instRoots: root of the merkle tree contains all instructions * @param blkData: merkle has of the block body * @param sigIdxs: indices of the validators who signed this block * @param sigVs: part of the signatures of the validators * @param sigRs: part of the signatures of the validators * @param sigSs: part of the signatures of the validators */ function submitBurnProof( bytes memory inst, uint heights, bytes32[] memory instPaths, bool[] memory instPathIsLefts, bytes32 instRoots, bytes32 blkData, uint[] memory sigIdxs, uint8[] memory sigVs, bytes32[] memory sigRs, bytes32[] memory sigSs ) public nonReentrant { require(inst.length >= 130, errorToString(Errors.INVALID_DATA)); BurnInstData memory data = parseBurnInst(inst); require(data.meta == BURN_TO_CONTRACT_REQUEST_METADATA_TYPE && data.shard == 1, errorToString(Errors.INVALID_DATA)); // Check instruction type // Not withdrawed require(!isWithdrawed(data.itx), errorToString(Errors.ALREADY_USED)); withdrawed[data.itx] = true; // Check if balance is enough if (data.token == ETH_TOKEN) { require(address(this).balance >= data.amount.safeAdd(totalDepositedToSCAmount[data.token]), errorToString(Errors.TOKEN_NOT_ENOUGH)); } else { uint8 decimals = getDecimals(data.token); if (decimals > 9) { data.amount = data.amount.safeMul(10 ** (uint(decimals) - 9)); } require(IERC20(data.token).balanceOf(address(this)) >= data.amount.safeAdd(totalDepositedToSCAmount[data.token]), errorToString(Errors.TOKEN_NOT_ENOUGH)); } verifyInst( inst, heights, instPaths, instPathIsLefts, instRoots, blkData, sigIdxs, sigVs, sigRs, sigSs ); withdrawRequests[data.to][data.token] = withdrawRequests[data.to][data.token].safeAdd(data.amount); totalDepositedToSCAmount[data.token] = totalDepositedToSCAmount[data.token].safeAdd(data.amount); } /** * @dev generate address from signature data and hash. */ function sigToAddress(bytes memory signData, bytes32 hash) public pure returns (address) { bytes32 s; bytes32 r; uint8 v; assembly { r := mload(add(signData, 0x20)) s := mload(add(signData, 0x40)) } v = uint8(signData[64]) + 27; return ecrecover(hash, v, r, s); } /** * @dev Checks if a sig data has been used before * @notice First, we check inside the storage of this contract itself. If the * hash has been used before, we return the result. Otherwise, we query * previous vault recursively until the first Vault (prevVault address is 0x0) * @param hash: of the sig data * @return bool: whether the sig data has been used or not */ function isSigDataUsed(bytes32 hash) public view returns(bool) { if (sigDataUsed[hash]) { return true; } else if (address(prevVault) == address(0)) { return false; } return prevVault.isSigDataUsed(hash); } struct PreSignData { Prefix prefix; address token; bytes timestamp; uint amount; } function newPreSignData(Prefix prefix, address token, bytes calldata timestamp, uint amount) pure internal returns (PreSignData memory) { PreSignData memory psd = PreSignData(prefix, token, timestamp, amount); return psd; } /** * @dev User requests withdraw token contains in withdrawRequests. * Deposit event will be emitted to let incognito recognize and mint new p-tokens for the user. * @param incognitoAddress: incognito's address that will receive minted p-tokens. * @param token: ethereum's token address (eg., ETH, DAI, ...) * @param amount: amount of the token in ethereum's denomination * @param signData: signature of an unique data that is signed by an account which is generated from user's incognito privkey * @param timestamp: unique data generated from client (timestamp for example) * @param txId: move fund transaction hash * @param signData: regulator signature */ function requestWithdraw( string calldata incognitoAddress, address token, uint amount, bytes calldata signData, bytes calldata timestamp, bytes32 txId, bytes calldata regulatorSig ) external nonReentrant { verifyRegulator(txId, regulatorSig); // verify owner signs data address verifier = verifySignData(abi.encode(newPreSignData(Prefix.ETHEREUM_REQUEST_WITHDRAW_SIGNATURE, token, timestamp, amount), incognitoAddress), signData); // migrate from preVault migrateBalance(verifier, token); require(withdrawRequests[verifier][token] >= amount, errorToString(Errors.WITHDRAW_REQUEST_TOKEN_NOT_ENOUGH)); withdrawRequests[verifier][token] = withdrawRequests[verifier][token].safeSub(amount); totalDepositedToSCAmount[token] = totalDepositedToSCAmount[token].safeSub(amount); // convert denomination from ethereum's to incognito's (pcoin) uint emitAmount = amount; if (token != ETH_TOKEN) { uint8 decimals = getDecimals(token); if (decimals > 9) { emitAmount = amount / (10 ** (uint(decimals) - 9)); } } emit Deposit(token, incognitoAddress, emitAmount); } /** * @dev execute is a general function that plays a role as proxy to interact to other smart contracts. * @param token: ethereum's token address (eg., ETH, DAI, ...) * @param amount: amount of the token in ethereum's denomination * @param recipientToken: received token address. * @param exchangeAddress: address of targeting smart contract that actually executes the desired logics like trade, invest, borrow and so on. * @param callData: encoded with signature and params of function from targeting smart contract. * @param timestamp: unique data generated from client (timestamp for example) * @param signData: signature of an unique data that is signed by an account which is generated from user's incognito privkey */ function execute( address token, uint amount, address recipientToken, address exchangeAddress, bytes calldata callData, bytes calldata timestamp, bytes calldata signData ) external payable nonReentrant { //verify ower signs data from input address verifier = verifySignData(abi.encode(newPreSignData(Prefix.ETHEREUM_EXECUTE_SIGNATURE, token, timestamp, amount), recipientToken, exchangeAddress, callData), signData); // migrate from preVault migrateBalance(verifier, token); require(withdrawRequests[verifier][token] >= amount, errorToString(Errors.WITHDRAW_REQUEST_TOKEN_NOT_ENOUGH)); // update balance of verifier totalDepositedToSCAmount[token] = totalDepositedToSCAmount[token].safeSub(amount); withdrawRequests[verifier][token] = withdrawRequests[verifier][token].safeSub(amount); // define number of eth spent for forwarder. uint ethAmount = msg.value; if (token == ETH_TOKEN) { ethAmount = ethAmount.safeAdd(amount); } else { // transfer token to exchangeAddress. require(IERC20(token).balanceOf(address(this)) >= amount, errorToString(Errors.TOKEN_NOT_ENOUGH)); IERC20(token).transfer(executor, amount); require(checkSuccess(), errorToString(Errors.INTERNAL_TX_ERROR)); } uint returnedAmount = callExtFunc(recipientToken, ethAmount, callData, exchangeAddress); // update withdrawRequests withdrawRequests[verifier][recipientToken] = withdrawRequests[verifier][recipientToken].safeAdd(returnedAmount); totalDepositedToSCAmount[recipientToken] = totalDepositedToSCAmount[recipientToken].safeAdd(returnedAmount); } /** * @dev single trade */ function callExtFunc(address recipientToken, uint ethAmount, bytes memory callData, address exchangeAddress) internal returns (uint) { // get balance of recipient token before trade to compare after trade. uint balanceBeforeTrade = balanceOf(recipientToken); if (recipientToken == ETH_TOKEN) { balanceBeforeTrade = balanceBeforeTrade.safeSub(msg.value); } require(address(this).balance >= ethAmount, errorToString(Errors.TOKEN_NOT_ENOUGH)); bytes memory result = Executor(executor).execute{value: ethAmount}(exchangeAddress, callData); (address returnedTokenAddress, uint returnedAmount) = abi.decode(result, (address, uint)); require(returnedTokenAddress == recipientToken && balanceOf(recipientToken).safeSub(balanceBeforeTrade) == returnedAmount, errorToString(Errors.INVALID_RETURN_DATA)); return returnedAmount; } /** * @dev set regulator */ function setRegulator(address _regulator) external { require((regulator == address(0x0) || msg.sender == regulator) && _regulator != address(0x0), errorToString(Errors.NOT_AUTHORISED)); regulator = _regulator; } /** * @dev verify regulator */ function verifyRegulator(bytes32 txId, bytes memory signData) internal view { // verify regulator signs data address signer = sigToAddress(signData, keccak256(abi.encode(ShieldInfo(msg.sender, txId)))); require(signer == regulator, errorToString(Errors.INVALID_SIGNATURE)); } /** * @dev verify sign data */ function verifySignData(bytes memory data, bytes memory signData) internal returns(address){ bytes32 hash = keccak256(data); require(!isSigDataUsed(hash), errorToString(Errors.ALREADY_USED)); address verifier = sigToAddress(signData, hash); // reject when verifier equals zero require(verifier != address(0x0), errorToString(Errors.INVALID_SIGNATURE)); // mark data hash of sig as used sigDataUsed[hash] = true; return verifier; } /** * @dev migrate balance from previous vault * Note: uncomment for next version */ function migrateBalance(address owner, address token) internal { if (address(prevVault) != address(0x0) && !migration[owner][token]) { withdrawRequests[owner][token] = withdrawRequests[owner][token].safeAdd(prevVault.getDepositedBalance(token, owner)); migration[owner][token] = true; } } /** * @dev Get the amount of specific coin for specific wallet */ function getDepositedBalance( address token, address owner ) public view returns (uint) { if (address(prevVault) != address(0x0) && !migration[owner][token]) { return withdrawRequests[owner][token].safeAdd(prevVault.getDepositedBalance(token, owner)); } return withdrawRequests[owner][token]; } /** * @dev Move total number of assets to newVault * @notice This only works when the preVault is Paused * @notice This can only be called by preVault * @param assets: address of the ERC20 tokens to move, 0x0 for ETH * @param amounts: total number of the ERC20 tokens to move, 0x0 for ETH */ function updateAssets(address[] calldata assets, uint[] calldata amounts) external onlyPreVault returns(bool) { require(assets.length == amounts.length, errorToString(Errors.NOT_EQUAL)); require(Withdrawable(prevVault).paused(), errorToString(Errors.PREVAULT_NOT_PAUSED)); for (uint i = 0; i < assets.length; i++) { totalDepositedToSCAmount[assets[i]] = totalDepositedToSCAmount[assets[i]].safeAdd(amounts[i]); } emit UpdateTokenTotal(assets, amounts); return true; } /** * @dev Payable receive function to receive Ether from oldVault when migrating */ receive() external payable {} /** * @dev Check if transfer() and transferFrom() of ERC20 succeeded or not * This check is needed to fix https://github.com/ethereum/solidity/issues/4116 * This function is copied from https://github.com/AdExNetwork/adex-protocol-eth/blob/master/contracts/libs/SafeERC20.sol */ function checkSuccess() private pure returns (bool) { uint256 returnValue = 0; assembly { // check number of bytes returned from last function call switch returndatasize() // no bytes returned: assume success case 0x0 { returnValue := 1 } // 32 bytes returned: check if non-zero case 0x20 { // copy 32 bytes into scratch space returndatacopy(0x0, 0x0, 0x20) // load those bytes into returnValue returnValue := mload(0x0) } // not sure what was returned: don't mark as success default { } } return returnValue != 0; } /** * @dev convert enum to string value */ function errorToString(Errors error) internal pure returns(string memory) { uint8 erroNum = uint8(error); uint maxlength = 10; bytes memory reversed = new bytes(maxlength); uint i = 0; while (erroNum != 0) { uint8 remainder = erroNum % 10; erroNum = erroNum / 10; reversed[i++] = byte(48 + remainder); } bytes memory s = new bytes(i + 1); for (uint j = 0; j <= i; j++) { s[j] = reversed[i - j]; } return string(s); } /** * @dev Get the decimals of an ERC20 token, return 0 if it isn't defined * We check the returndatasize to covert both cases that the token has * and doesn't have the function decimals() */ function getDecimals(address token) public view returns (uint8) { require(Address.isContract(token), "getDecimals non-contract"); IERC20 erc20 = IERC20(token); try erc20.decimals() returns (uint256 d) { return uint8(d); } catch { revert("get ERC20 decimal failed"); } } /** * @dev Get the amount of coin deposited to this smartcontract */ function balanceOf(address token) public view returns (uint) { if (token == ETH_TOKEN) { return address(this).balance; } require(Address.isContract(token), "balanceOf non-contract"); try IERC20(token).balanceOf(address(this)) returns (uint256 b) { return b; } catch { revert("get ERC20 balance failed"); } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.5.0 <0.8.0; /** * @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 (uint); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint); /** * @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, uint amount) external; /** * @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. * * > 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, uint amount) external; /** * @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, uint amount) external; /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5,05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() external view returns (uint); /** * @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, uint 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, uint value); }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2 <0.8.0; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; // solhint-disable-next-line no-inline-assembly assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (bool success, ) = recipient.call{ value: amount }(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain`call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.call{ value: value }(data); return _verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.staticcall(data); return _verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.delegatecall(data); return _verifyCallResult(success, returndata, errorMessage); } function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly // solhint-disable-next-line no-inline-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
pragma solidity >=0.6.12 <=0.8.9; import './IERC20.sol'; import '@openzeppelin/contracts/access/Ownable.sol'; contract TradeUtils { IERC20 constant public ETH_CONTRACT_ADDRESS = IERC20(0x0000000000000000000000000000000000000000); function balanceOf(IERC20 token) internal view returns (uint256) { if (token == ETH_CONTRACT_ADDRESS) { return address(this).balance; } return token.balanceOf(address(this)); } function transfer(IERC20 token, uint amount) internal { if (token == ETH_CONTRACT_ADDRESS) { require(address(this).balance >= amount); (bool success, ) = msg.sender.call{value: amount}(""); require(success); } else { token.transfer(msg.sender, amount); require(checkSuccess()); } } function approve(IERC20 token, address proxy, uint amount) internal { if (token != ETH_CONTRACT_ADDRESS) { token.approve(proxy, 0); require(checkSuccess()); token.approve(proxy, amount); require(checkSuccess()); } } /** * @dev Check if transfer() and transferFrom() of ERC20 succeeded or not * This check is needed to fix https://github.com/ethereum/solidity/issues/4116 * This function is copied from https://github.com/AdExNetwork/adex-protocol-eth/blob/master/contracts/libs/SafeERC20.sol */ function checkSuccess() internal pure returns (bool) { uint256 returnValue = 0; assembly { // check number of bytes returned from last function call switch returndatasize() // no bytes returned: assume success case 0x0 { returnValue := 1 } // 32 bytes returned: check if non-zero case 0x20 { // copy 32 bytes into scratch space returndatacopy(0x0, 0x0, 0x20) // load those bytes into returnValue returnValue := mload(0x0) } // not sure what was returned: don't mark as success default { } } return returnValue != 0; } } abstract contract Executor is Ownable { mapping (address => bool) public dappAddresses; constructor() internal { dappAddresses[address(this)] = true; } function addDappAddress(address addr) external onlyOwner { require(addr != address(0x0), "Executor:A0"); // address is zero dappAddresses[addr] = true; } function removeDappAddress(address addr) external onlyOwner { require(addr != address(0x0), "Executor:A0"); // address is zero dappAddresses[addr] = false; } function dappExists(address addr) public view returns (bool) { return dappAddresses[addr]; } function execute(address fns, bytes calldata data) external payable returns (bytes memory) { require(dappExists(fns), "Executor:DNE"); // dapp does not exist (bool success, bytes memory result) = fns.delegatecall(data); if (!success) { // Next 5 lines from https://ethereum.stackexchange.com/a/83577 if (result.length < 68) revert(); assembly { result := add(result, 0x04) } revert(abi.decode(result, (string))); } return result; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor () internal { address msgSender = _msgSender(); _owner = msgSender; emit OwnershipTransferred(address(0), msgSender); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(owner() == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { emit OwnershipTransferred(_owner, address(0)); _owner = address(0); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /* * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with GSN meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address payable) { return msg.sender; } function _msgData() internal view virtual returns (bytes memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } }
{ "optimizer": { "enabled": true, "runs": 1000 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"string","name":"incognitoAddress","type":"string"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"string","name":"incognitoAddress","type":"string"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"depositID","type":"uint256"}],"name":"DepositV2","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"id","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"phaseID","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"errorData","type":"bytes"}],"name":"ExecuteFnLog","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"bytes","name":"redepositIncAddress","type":"bytes"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"itx","type":"bytes32"}],"name":"Redeposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newIncognitoProxy","type":"address"}],"name":"UpdateIncognitoProxy","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"assets","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"UpdateTokenTotal","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"BURN_CALL_REQUEST_METADATA_TYPE","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BURN_REQUEST_METADATA_TYPE","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BURN_TO_CONTRACT_REQUEST_METADATA_TYPE","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CURRENT_NETWORK_ID","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ETH_TOKEN","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"externalCalldata","type":"bytes"},{"internalType":"address","name":"redepositToken","type":"address"}],"name":"_callExternal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address payable","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"_transferExternal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"incognitoAddress","type":"string"},{"internalType":"bytes32","name":"txId","type":"bytes32"},{"internalType":"bytes","name":"signData","type":"bytes"}],"name":"deposit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"string","name":"incognitoAddress","type":"string"},{"internalType":"bytes32","name":"txId","type":"bytes32"},{"internalType":"bytes","name":"signData","type":"bytes"}],"name":"depositERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"string","name":"incognitoAddress","type":"string"},{"internalType":"bytes32","name":"txId","type":"bytes32"},{"internalType":"bytes","name":"signData","type":"bytes"}],"name":"depositERC20_V2","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"incognitoAddress","type":"string"},{"internalType":"bytes32","name":"txId","type":"bytes32"},{"internalType":"bytes","name":"signData","type":"bytes"}],"name":"deposit_V2","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"recipientToken","type":"address"},{"internalType":"address","name":"exchangeAddress","type":"address"},{"internalType":"bytes","name":"callData","type":"bytes"},{"internalType":"bytes","name":"timestamp","type":"bytes"},{"internalType":"bytes","name":"signData","type":"bytes"}],"name":"execute","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes","name":"inst","type":"bytes"},{"internalType":"uint256","name":"heights","type":"uint256"},{"internalType":"bytes32[]","name":"instPaths","type":"bytes32[]"},{"internalType":"bool[]","name":"instPathIsLefts","type":"bool[]"},{"internalType":"bytes32","name":"instRoots","type":"bytes32"},{"internalType":"bytes32","name":"blkData","type":"bytes32"},{"internalType":"uint256[]","name":"sigIdxs","type":"uint256[]"},{"internalType":"uint8[]","name":"sigVs","type":"uint8[]"},{"internalType":"bytes32[]","name":"sigRs","type":"bytes32[]"},{"internalType":"bytes32[]","name":"sigSs","type":"bytes32[]"}],"name":"executeWithBurnProof","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"executor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"getDecimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"getDepositedBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_prevVault","type":"address"},{"internalType":"address","name":"_regulator","type":"address"},{"internalType":"address","name":"_executor","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isInitialized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"}],"name":"isSigDataUsed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"}],"name":"isWithdrawed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"migration","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"notEntered","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"inst","type":"bytes"}],"name":"parseBurnInst","outputs":[{"components":[{"internalType":"uint8","name":"meta","type":"uint8"},{"internalType":"uint8","name":"shard","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"address payable","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes32","name":"itx","type":"bytes32"}],"internalType":"struct Vault.BurnInstData","name":"","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"inst","type":"bytes"}],"name":"parseCalldataFromBurnInst","outputs":[{"components":[{"internalType":"uint8","name":"meta","type":"uint8"},{"internalType":"uint8","name":"shard","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"address payable","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes32","name":"itx","type":"bytes32"}],"internalType":"struct Vault.BurnInstData","name":"","type":"tuple"},{"components":[{"internalType":"address","name":"redepositToken","type":"address"},{"internalType":"bytes","name":"redepositIncAddress","type":"bytes"},{"internalType":"address payable","name":"withdrawAddress","type":"address"}],"internalType":"struct Vault.RedepositOptions","name":"","type":"tuple"},{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"prevVault","outputs":[{"internalType":"contract Withdrawable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"regulator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"incognitoAddress","type":"string"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"signData","type":"bytes"},{"internalType":"bytes","name":"timestamp","type":"bytes"},{"internalType":"bytes32","name":"txId","type":"bytes32"},{"internalType":"bytes","name":"regulatorSig","type":"bytes"}],"name":"requestWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_regulator","type":"address"}],"name":"setRegulator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"sigDataUsed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"signData","type":"bytes"},{"internalType":"bytes32","name":"hash","type":"bytes32"}],"name":"sigToAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"storageLayoutVersion","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"inst","type":"bytes"},{"internalType":"uint256","name":"heights","type":"uint256"},{"internalType":"bytes32[]","name":"instPaths","type":"bytes32[]"},{"internalType":"bool[]","name":"instPathIsLefts","type":"bool[]"},{"internalType":"bytes32","name":"instRoots","type":"bytes32"},{"internalType":"bytes32","name":"blkData","type":"bytes32"},{"internalType":"uint256[]","name":"sigIdxs","type":"uint256[]"},{"internalType":"uint8[]","name":"sigVs","type":"uint8[]"},{"internalType":"bytes32[]","name":"sigRs","type":"bytes32[]"},{"internalType":"bytes32[]","name":"sigSs","type":"bytes32[]"}],"name":"submitBurnProof","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"totalDepositedToSCAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"assets","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"updateAssets","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_regulator","type":"address"},{"internalType":"address","name":"_executor","type":"address"}],"name":"upgradeVaultStorage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"inst","type":"bytes"},{"internalType":"uint256","name":"heights","type":"uint256"},{"internalType":"bytes32[]","name":"instPaths","type":"bytes32[]"},{"internalType":"bool[]","name":"instPathIsLefts","type":"bool[]"},{"internalType":"bytes32","name":"instRoots","type":"bytes32"},{"internalType":"bytes32","name":"blkData","type":"bytes32"},{"internalType":"uint256[]","name":"sigIdxs","type":"uint256[]"},{"internalType":"uint8[]","name":"sigVs","type":"uint8[]"},{"internalType":"bytes32[]","name":"sigRs","type":"bytes32[]"},{"internalType":"bytes32[]","name":"sigSs","type":"bytes32[]"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"withdrawRequests","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"withdrawed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
608060405234801561001057600080fd5b506150ee806100206000396000f3fe6080604052600436106102a45760003560e01c8063995fac111161016e578063cde0a4f8116100cb578063dd8fee141161007f578063f75b98ce11610064578063f75b98ce146106f6578063fa84702e14610716578063fee8efda1461072b576102ab565b8063dd8fee14146106c1578063e4bd7074146106d6576102ab565b8063d6a1fe3b116100b0578063d6a1fe3b14610677578063d7200eb11461068c578063dca40d9e146106a1576102ab565b8063cde0a4f814610637578063cf54aaa014610657576102ab565b8063bd835c4211610122578063c0c53b8b11610107578063c0c53b8b146105ef578063c34c08e51461060f578063c791d70514610624576102ab565b8063bd835c42146105ba578063bda9b509146105cf576102ab565b8063a73b153211610153578063a73b15321461055a578063a807b5bb1461057a578063b8237dbb1461059a576102ab565b8063995fac1114610525578063a3f5d8cc14610545576102ab565b80636304541c1161021c57806373bf9651116101d05780637e16e6e1116101b55780637e16e6e1146104d257806384b3ac03146104ff5780638588ccd614610512576102ab565b806373bf965114610492578063749c5f86146104b2576102ab565b806366945b311161020157806366945b311461042e5780636f2cbc481461045d57806370a0823114610472576102ab565b80636304541c146103e157806365b5a00f1461040e576102ab565b8063392e53cd116102735780633fec6b40116102585780633fec6b401461037d578063568c04fd146103aa57806358bc8337146103cc576102ab565b8063392e53cd146103485780633ed1b3761461035d576102ab565b8063145e2a6b146102b05780631beb7de2146102d25780631ea1940e146102f25780631ed4276d14610328576102ab565b366102ab57005b600080fd5b3480156102bc57600080fd5b506102d06102cb36600461404a565b61074b565b005b3480156102de57600080fd5b506102d06102ed3660046145cc565b610834565b3480156102fe57600080fd5b5061031261030d366004614344565b610c91565b60405161031f9190614c39565b60405180910390f35b34801561033457600080fd5b506103126103433660046142bf565b610ca6565b34801561035457600080fd5b50610312610ec7565b34801561036957600080fd5b506102d061037836600461439c565b610ed7565b34801561038957600080fd5b5061039d610398366004614589565b611437565b60405161031f9190614a2e565b3480156103b657600080fd5b506103bf6114c6565b60405161031f9190614fc5565b3480156103d857600080fd5b5061039d6114cb565b3480156103ed57600080fd5b506104016103fc366004613f53565b6114d0565b60405161031f9190614cf1565b34801561041a57600080fd5b50610401610429366004614012565b6114e2565b34801561043a57600080fd5b5061044e61044936600461435c565b6114ff565b60405161031f93929190614ec8565b34801561046957600080fd5b506103bf6116e2565b34801561047e57600080fd5b5061040161048d366004613f53565b6116e7565b34801561049e57600080fd5b506102d06104ad3660046145cc565b6117bb565b3480156104be57600080fd5b506103126104cd366004614344565b611b33565b3480156104de57600080fd5b506104f26104ed3660046144db565b611c03565b60405161031f9190614eba565b6102d061050d3660046147e6565b611c85565b6102d0610520366004614153565b611dae565b34801561053157600080fd5b50610312610540366004614012565b61224c565b34801561055157600080fd5b5061031261226c565b34801561056657600080fd5b506102d0610575366004614012565b61227c565b34801561058657600080fd5b506102d061059536600461422c565b61231f565b3480156105a657600080fd5b506102d06105b536600461422c565b6125fe565b3480156105c657600080fd5b506103bf6128ec565b3480156105db57600080fd5b506104016105ea3660046140d4565b6128f1565b3480156105fb57600080fd5b506102d061060a36600461408a565b612b15565b34801561061b57600080fd5b5061039d612c1f565b6102d06106323660046147e6565b612c2e565b34801561064357600080fd5b506102d0610652366004613f53565b612d42565b34801561066357600080fd5b506103bf610672366004613f53565b612dd0565b34801561068357600080fd5b50610401612e8a565b34801561069857600080fd5b506103bf612e90565b3480156106ad57600080fd5b506103126106bc366004614344565b612e95565b3480156106cd57600080fd5b5061039d612eaa565b3480156106e257600080fd5b506103126106f1366004614344565b612eb9565b34801561070257600080fd5b50610401610711366004614012565b612f39565b34801561072257600080fd5b5061039d613065565b34801561073757600080fd5b506102d06107463660046146fe565b613074565b30331461075860146132e0565b9061077f5760405162461bcd60e51b81526004016107769190614d37565b60405180910390fd5b506001600160a01b03831661079d57610798828261343a565b61082f565b60405163a9059cbb60e01b81526001600160a01b0384169063a9059cbb906107cb9085908590600401614a66565b600060405180830381600087803b1580156107e557600080fd5b505af11580156107f9573d6000803e3d6000fd5b505050506108056134d6565b61080f60046132e0565b9061082d5760405162461bcd60e51b81526004016107769190614d37565b505b505050565b600554600160a01b900460ff1661084b60016132e0565b906108695760405162461bcd60e51b81526004016107769190614d37565b506005805460ff60a01b1916905589516082111561088760066132e0565b906108a55760405162461bcd60e51b81526004016107769190614d37565b506108ae613c89565b6108b78b611c03565b805190915060ff1660f11480156108d55750806020015160ff166001145b6108df60066132e0565b906108fd5760405162461bcd60e51b81526004016107769190614d37565b5061090b8160a00151611b33565b1561091660056132e0565b906109345760405162461bcd60e51b81526004016107769190614d37565b5060a081015160009081526020819052604090819020805460ff191660011790558101516001600160a01b03166109bf576040808201516001600160a01b0316600090815260046020522054608082015161098e9161350a565b47101561099b60076132e0565b906109b95760405162461bcd60e51b81526004016107769190614d37565b50610ad1565b60006109ce8260400151612dd0565b905060098160ff1611156109fb5760808201516109f59060081960ff841601600a0a613570565b60808301525b6040808301516001600160a01b03166000908152600460205220546080830151610a249161350a565b82604001516001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401610a549190614a2e565b60206040518083038186803b158015610a6c57600080fd5b505afa158015610a80573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aa4919061485d565b1015610ab060076132e0565b90610ace5760405162461bcd60e51b81526004016107769190614d37565b50505b610ae38b8b8b8b8b8b8b8b8b8b6135d2565b60408101516001600160a01b0316610b8c57600081606001516001600160a01b03168260800151604051610b1690614a2b565b60006040518083038185875af1925050503d8060008114610b53576040519150601f19603f3d011682016040523d82523d6000602084013e610b58565b606091505b5050905080610b6760046132e0565b90610b855760405162461bcd60e51b81526004016107769190614d37565b5050610c2a565b80604001516001600160a01b031663a9059cbb826060015183608001516040518363ffffffff1660e01b8152600401610bc6929190614a66565b600060405180830381600087803b158015610be057600080fd5b505af1158015610bf4573d6000803e3d6000fd5b50505050610c006134d6565b610c0a60046132e0565b90610c285760405162461bcd60e51b81526004016107769190614d37565b505b7f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb816040015182606001518360800151604051610c6993929190614a42565b60405180910390a150506005805460ff60a01b1916600160a01b179055505050505050505050565b60016020526000908152604090205460ff1681565b6005546000906001600160a01b031615801590610ccd57506005546001600160a01b031633145b610cd7600c6132e0565b90610cf55760405162461bcd60e51b81526004016107769190614d37565b50838214610d03600a6132e0565b90610d215760405162461bcd60e51b81526004016107769190614d37565b50600560009054906101000a90046001600160a01b03166001600160a01b0316635c975abb6040518163ffffffff1660e01b815260040160206040518083038186803b158015610d7057600080fd5b505afa158015610d84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610da89190614328565b610db2600d6132e0565b90610dd05760405162461bcd60e51b81526004016107769190614d37565b5060005b84811015610e7e57610e37848483818110610deb57fe5b9050602002013560046000898986818110610e0257fe5b9050602002016020810190610e179190613f53565b6001600160a01b031681526020810191909152604001600020549061350a565b60046000888885818110610e4757fe5b9050602002016020810190610e5c9190613f53565b6001600160a01b03168152602081019190915260400160002055600101610dd4565b507f6a7fbbcddfd518bb8c56b28ac6c7acb0f7ca093ed232eb3306e53d14e469895f85858585604051610eb49493929190614ba1565b60405180910390a1506001949350505050565b600554600160a81b900460ff1681565b600554600160a01b900460ff16610eee60016132e0565b90610f0c5760405162461bcd60e51b81526004016107769190614d37565b506005805460ff60a01b19169055610f22613c89565b610f2a613cbe565b6060610f368e8e6114ff565b925092509250610f498360a00151611b33565b15610f5460056132e0565b90610f725760405162461bcd60e51b81526004016107769190614d37565b5060a083015160009081526020819052604090819020805460ff191660011790558301516001600160a01b0316610ffd576040808401516001600160a01b03166000908152600460205220546080840151610fcc9161350a565b471015610fd960076132e0565b90610ff75760405162461bcd60e51b81526004016107769190614d37565b5061110f565b600061100c8460400151612dd0565b905060098160ff1611156110395760808401516110339060081960ff841601600a0a613570565b60808501525b6040808501516001600160a01b031660009081526004602052205460808501516110629161350a565b84604001516001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016110929190614a2e565b60206040518083038186803b1580156110aa57600080fd5b505afa1580156110be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110e2919061485d565b10156110ee60076132e0565b9061110c5760405162461bcd60e51b81526004016107769190614d37565b50505b6111658e8e8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508d8d8d8d8d8d8d8d8d6135d2565b60408084015160608501516080860151855193517fbda9b509000000000000000000000000000000000000000000000000000000008152309463bda9b509946111b8949093909290918891600401614a99565b602060405180830381600087803b1580156111d257600080fd5b505af1925050508015611202575060408051601f3d908101601f191682019092526111ff9181019061485d565b60015b61129b573d808015611230576040519150601f19603f3d011682016040523d82523d6000602084013e611235565b606091505b506112528460400151846020015186608001518760a001516136cd565b7fdbbb883f24557adf486292429863dcfd4ac5d4db168ae94921da8e3d9a95d4168460a0015160008360405161128a93929190614cfa565b60405180910390a150505050611417565b60408301516001600160a01b03166112ca576112c583600001518460200151838760a001516136cd565b611412565b825160408085015190517f145e2a6b000000000000000000000000000000000000000000000000000000008152309263145e2a6b9261130d928690600401614a42565b600060405180830381600087803b15801561132757600080fd5b505af1925050508015611338575060015b6113ce573d808015611366576040519150601f19603f3d011682016040523d82523d6000602084013e61136b565b606091505b5061138484600001518560200151848860a001516136cd565b7fdbbb883f24557adf486292429863dcfd4ac5d4db168ae94921da8e3d9a95d4168560a001516001836040516113bc93929190614cfa565b60405180910390a15050505050611417565b7f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb836000015184604001518360405161140993929190614a42565b60405180910390a15b505050505b50506005805460ff60a01b1916600160a01b179055505050505050505050565b60008060008060208601519150604086015192508560408151811061145857fe5b602001015160f81c60f81b60f81c601b0190506001858284866040516000815260200160405260405161148e9493929190614d19565b6020604051602081039080840390855afa1580156114b0573d6000803e3d6000fd5b5050506020604051035193505050505b92915050565b60f181565b600081565b60046020526000908152604090205481565b600260209081526000928352604080842090915290825290205481565b611507613c89565b61150f613cbe565b606061012884101561152160136132e0565b9061153f5760405162461bcd60e51b81526004016107769190614d37565b50611548613c89565b8585600081811061155557fe5b919091013560f81c8252508585600181811061156d57fe5b919091013560f81c60208301525060008686600281811061158a57fe5b845192013560f81c92505060ff16609e1480156115ae5750816020015160ff166001145b80156115bd575060ff81166001145b6115c760136132e0565b906115e55760405162461bcd60e51b81526004016107769190614d37565b50506115ef613cbe565b6115fd60c36003888a61503e565b81019061160a9190613f76565b6001600160a01b03908116604088810191909152918116875260a08801929092526080870192909252918216606086015291169083015261165061012860c3888a61503e565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050506020820152818161169988610128818c61503e565b81818080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250969e959d50919b50939950505050505050505050565b60f381565b60006001600160a01b0382166116fe5750476117b6565b611707826137c3565b6117235760405162461bcd60e51b815260040161077690614e15565b6040516370a0823160e01b81526001600160a01b038316906370a082319061174f903090600401614a2e565b60206040518083038186803b15801561176757600080fd5b505afa925050508015611797575060408051601f3d908101601f191682019092526117949181019061485d565b60015b6117b35760405162461bcd60e51b815260040161077690614e83565b90505b919050565b600554600160a01b900460ff166117d260016132e0565b906117f05760405162461bcd60e51b81526004016107769190614d37565b506005805460ff60a01b1916905589516082111561180e60066132e0565b9061182c5760405162461bcd60e51b81526004016107769190614d37565b50611835613c89565b61183e8b611c03565b805190915060ff1660f314801561185c5750806020015160ff166001145b61186660066132e0565b906118845760405162461bcd60e51b81526004016107769190614d37565b506118928160a00151611b33565b1561189d60056132e0565b906118bb5760405162461bcd60e51b81526004016107769190614d37565b5060a081015160009081526020819052604090819020805460ff191660011790558101516001600160a01b0316611946576040808201516001600160a01b031660009081526004602052205460808201516119159161350a565b47101561192260076132e0565b906119405760405162461bcd60e51b81526004016107769190614d37565b50611a58565b60006119558260400151612dd0565b905060098160ff16111561198257608082015161197c9060081960ff841601600a0a613570565b60808301525b6040808301516001600160a01b031660009081526004602052205460808301516119ab9161350a565b82604001516001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016119db9190614a2e565b60206040518083038186803b1580156119f357600080fd5b505afa158015611a07573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a2b919061485d565b1015611a3760076132e0565b90611a555760405162461bcd60e51b81526004016107769190614d37565b50505b611a6a8b8b8b8b8b8b8b8b8b8b6135d2565b608081015160608201516001600160a01b0390811660009081526002602090815260408083208187015190941683529290522054611aa79161350a565b60608201516001600160a01b03908116600090815260026020908152604080832081870180518616855290835281842095909555608086015194519093168252600490522054611af69161350a565b6040918201516001600160a01b031660009081526004602052919091205550506005805460ff60a01b1916600160a01b1790555050505050505050565b60008181526020819052604081205460ff1615611b52575060016117b6565b6005546001600160a01b0316611b6a575060006117b6565b6005546040517f749c5f860000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063749c5f8690611bb3908590600401614cf1565b60206040518083038186803b158015611bcb57600080fd5b505afa158015611bdf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117b39190614328565b611c0b613c89565b611c13613c89565b82600081518110611c2057fe5b016020015160f81c8152825183906001908110611c3957fe5b0160209081015160f81c9082015260228301516042840151606285015160828601516001600160a01b039384166040860152929091166060840152608083015260a08201529050919050565b600554600160a01b900460ff16611c9c60016132e0565b90611cba5760405162461bcd60e51b81526004016107769190614d37565b506005805460ff60a01b191690556b033b2e3c9fd0803ce8000000471115611ce260026132e0565b90611d005760405162461bcd60e51b81526004016107769190614d37565b50611d418383838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506137c992505050565b7fd30df8040a1092415b49422a02dbd8cdd5915a596abcba02cd0f65dd86ab38516000868634611d716006613836565b604051611d82959493929190614b6a565b60405180910390a1611d94600661383a565b50506005805460ff60a01b1916600160a01b179055505050565b600554600160a01b900460ff16611dc560016132e0565b90611de35760405162461bcd60e51b81526004016107769190614d37565b506005805460ff60a01b191690556000611e5f611e03828d88888f613843565b8a8a8a8a604051602001611e1b959493929190614f36565b60408051601f198184030181526020601f8701819004810284018101909252858352919086908690819084018382808284376000920191909152506138c992505050565b9050611e6b818c61396d565b6001600160a01b038082166000908152600260209081526040808320938f16835292905220548a1115611e9e60086132e0565b90611ebc5760405162461bcd60e51b81526004016107769190614d37565b506001600160a01b038b16600090815260046020526040902054611ee0908b613aaf565b6001600160a01b03808d1660008181526004602090815260408083209590955592851681526002835283812091815291522054611f1d908b613aaf565b60026000836001600160a01b03166001600160a01b0316815260200190815260200160002060008d6001600160a01b03166001600160a01b0316815260200190815260200160002081905550600034905060006001600160a01b03168c6001600160a01b03161415611f9a57611f93818c61350a565b90506120db565b6040516370a0823160e01b81528b906001600160a01b038e16906370a0823190611fc8903090600401614a2e565b60206040518083038186803b158015611fe057600080fd5b505afa158015611ff4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612018919061485d565b101561202460076132e0565b906120425760405162461bcd60e51b81526004016107769190614d37565b5060095460405163a9059cbb60e01b81526001600160a01b038e81169263a9059cbb9261207792909116908f90600401614a66565b600060405180830381600087803b15801561209157600080fd5b505af11580156120a5573d6000803e3d6000fd5b505050506120b16134d6565b6120bb60046132e0565b906120d95760405162461bcd60e51b81526004016107769190614d37565b505b600061212d8b838b8b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508d613b05565b905061218a8160026000866001600160a01b03166001600160a01b0316815260200190815260200160002060008e6001600160a01b03166001600160a01b031681526020019081526020016000205461350a90919063ffffffff16565b60026000856001600160a01b03166001600160a01b0316815260200190815260200160002060008d6001600160a01b03166001600160a01b031681526020019081526020016000208190555061220e81600460008e6001600160a01b03166001600160a01b031681526020019081526020016000205461350a90919063ffffffff16565b6001600160a01b03909b1660009081526004602052604090209a909a5550506005805460ff60a01b1916600160a01b17905550505050505050505050565b600360209081526000928352604080842090915290825290205460ff1681565b600554600160a01b900460ff1681565b6008541561228a60126132e0565b906122a85760405162461bcd60e51b81526004016107769190614d37565b5060026008556007546001600160a01b0316156122c560116132e0565b906122e35760405162461bcd60e51b81526004016107769190614d37565b50600780546001600160a01b0393841673ffffffffffffffffffffffffffffffffffffffff199182161790915560098054929093169116179055565b600554600160a01b900460ff1661233660016132e0565b906123545760405162461bcd60e51b81526004016107769190614d37565b506005805460ff60a01b19169055604080516020601f84018190048102820181019092528281526123a29185919085908590819084018382808284376000920191909152506137c992505050565b8660006123ae82612dd0565b90506000826001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016123de9190614a2e565b60206040518083038186803b1580156123f657600080fd5b505afa15801561240a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061242e919061485d565b90508089600960ff851611156124695760098460ff1603600a0a818161245057fe5b04905060098460ff1603600a0a838161246557fe5b0492505b670de0b6b3a764000081111580156124895750670de0b6b3a76400008311155b80156124a65750670de0b6b3a76400006124a3828561350a565b11155b6124b060036132e0565b906124ce5760405162461bcd60e51b81526004016107769190614d37565b50846001600160a01b03166323b872dd33308e6040518463ffffffff1660e01b81526004016124ff93929190614a42565b600060405180830381600087803b15801561251957600080fd5b505af115801561252d573d6000803e3d6000fd5b505050506125396134d6565b61254360046132e0565b906125615760405162461bcd60e51b81526004016107769190614d37565b508a612576836125708f6116e7565b90613aaf565b14612581600a6132e0565b9061259f5760405162461bcd60e51b81526004016107769190614d37565b507f2d4b597935f3cd67fb2eebf1db4debc934cee5c7baa7153f980fdbeb2e74084e8c8b8b846040516125d59493929190614b36565b60405180910390a150506005805460ff60a01b1916600160a01b17905550505050505050505050565b600554600160a01b900460ff1661261560016132e0565b906126335760405162461bcd60e51b81526004016107769190614d37565b506005805460ff60a01b19169055604080516020601f84018190048102820181019092528281526126819185919085908590819084018382808284376000920191909152506137c992505050565b86600061268d82612dd0565b90506000826001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016126bd9190614a2e565b60206040518083038186803b1580156126d557600080fd5b505afa1580156126e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061270d919061485d565b90508089600960ff851611156127485760098460ff1603600a0a818161272f57fe5b04905060098460ff1603600a0a838161274457fe5b0492505b670de0b6b3a764000081111580156127685750670de0b6b3a76400008311155b80156127855750670de0b6b3a7640000612782828561350a565b11155b61278f60036132e0565b906127ad5760405162461bcd60e51b81526004016107769190614d37565b50846001600160a01b03166323b872dd33308e6040518463ffffffff1660e01b81526004016127de93929190614a42565b600060405180830381600087803b1580156127f857600080fd5b505af115801561280c573d6000803e3d6000fd5b505050506128186134d6565b61282260046132e0565b906128405760405162461bcd60e51b81526004016107769190614d37565b508a61284f836125708f6116e7565b1461285a600a6132e0565b906128785760405162461bcd60e51b81526004016107769190614d37565b507fd30df8040a1092415b49422a02dbd8cdd5915a596abcba02cd0f65dd86ab38518c8b8b846128a86006613836565b6040516128b9959493929190614b6a565b60405180910390a16128cb600661383a565b50506005805460ff60a01b1916600160a01b17905550505050505050505050565b609e81565b600030331461290060146132e0565b9061291e5760405162461bcd60e51b81526004016107769190614d37565b50600061292a836116e7565b9050606060006001600160a01b0389166129455750856129dd565b60095460405163a9059cbb60e01b81526001600160a01b038b81169263a9059cbb9261297992909116908b90600401614a66565b600060405180830381600087803b15801561299357600080fd5b505af11580156129a7573d6000803e3d6000fd5b505050506129b36134d6565b6129bd60046132e0565b906129db5760405162461bcd60e51b81526004016107769190614d37565b505b600954604051631cff79cd60e01b81526001600160a01b0390911690631cff79cd908390612a11908c908b90600401614adf565b6000604051808303818588803b158015612a2a57600080fd5b505af1158015612a3e573d6000803e3d6000fd5b50505050506040513d6000823e601f3d908101601f19168201604052612a679190810190614516565b91508151604014612a7860096132e0565b90612a965760405162461bcd60e51b81526004016107769190614d37565b5060008083806020019051810190612aae9190613fe5565b91509150866001600160a01b0316826001600160a01b0316148015612ade575080612adc866125708a6116e7565b145b612ae860096132e0565b90612b065760405162461bcd60e51b81526004016107769190614d37565b509a9950505050505050505050565b600554600160a81b900460ff1615612b2d600f6132e0565b90612b4b5760405162461bcd60e51b81526004016107769190614d37565b506005805460ff60a01b197fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff6001600160a01b0380881673ffffffffffffffffffffffffffffffffffffffff199094169390931716600160a81b1716600160a01b179091556007541615612bbf60116132e0565b90612bdd5760405162461bcd60e51b81526004016107769190614d37565b50600780546001600160a01b0393841673ffffffffffffffffffffffffffffffffffffffff199182161790915560098054929093169116179055506002600855565b6009546001600160a01b031681565b600554600160a01b900460ff16612c4560016132e0565b90612c635760405162461bcd60e51b81526004016107769190614d37565b506005805460ff60a01b191690556b033b2e3c9fd0803ce8000000471115612c8b60026132e0565b90612ca95760405162461bcd60e51b81526004016107769190614d37565b50612cea8383838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506137c992505050565b7f2d4b597935f3cd67fb2eebf1db4debc934cee5c7baa7153f980fdbeb2e74084e6000868634604051612d209493929190614b36565b60405180910390a150506005805460ff60a01b1916600160a01b179055505050565b6007546001600160a01b03161580612d6457506007546001600160a01b031633145b8015612d7857506001600160a01b03811615155b612d8260116132e0565b90612da05760405162461bcd60e51b81526004016107769190614d37565b506007805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b6000612ddb826137c3565b612df75760405162461bcd60e51b815260040161077690614e4c565b6000829050806001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015612e3557600080fd5b505afa925050508015612e65575060408051601f3d908101601f19168201909252612e629181019061485d565b60015b612e815760405162461bcd60e51b815260040161077690614d4a565b91506117b69050565b60085481565b600181565b60006020819052908152604090205460ff1681565b6007546001600160a01b031681565b60008181526001602052604081205460ff1615612ed8575060016117b6565b6005546001600160a01b0316612ef0575060006117b6565b6005546040517fe4bd70740000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063e4bd707490611bb3908590600401614cf1565b6005546000906001600160a01b031615801590612f7c57506001600160a01b0380831660009081526003602090815260408083209387168352929052205460ff16155b1561303857600554604051637badcc6760e11b8152613031916001600160a01b03169063f75b98ce90612fb59087908790600401614a7f565b60206040518083038186803b158015612fcd57600080fd5b505afa158015612fe1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613005919061485d565b6001600160a01b038085166000908152600260209081526040808320938916835292905220549061350a565b90506114c0565b506001600160a01b0380821660009081526002602090815260408083209386168352929052205492915050565b6005546001600160a01b031681565b600554600160a01b900460ff1661308b60016132e0565b906130a95760405162461bcd60e51b81526004016107769190614d37565b506005805460ff60a01b19169055604080516020601f84018190048102820181019092528281526130f79185919085908590819084018382808284376000920191909152506137c992505050565b600061316261310a60018c89898e613843565b8d8d60405160200161311e93929190614f7f565b60408051601f198184030181526020601f8c018190048102840181019092528a835291908b908b90819084018382808284376000920191909152506138c992505050565b905061316e818b61396d565b6001600160a01b038082166000908152600260209081526040808320938e16835292905220548911156131a160086132e0565b906131bf5760405162461bcd60e51b81526004016107769190614d37565b506001600160a01b038082166000908152600260209081526040808320938e16835292905220546131f0908a613aaf565b6001600160a01b038083166000908152600260209081526040808320938f16835292815282822093909355600490925290205461322d908a613aaf565b6001600160a01b038b1660008181526004602052604090209190915589901561328157600061325b8c612dd0565b905060098160ff16111561327f5760098160ff1603600a0a8b8161327b57fe5b0491505b505b7f2d4b597935f3cd67fb2eebf1db4debc934cee5c7baa7153f980fdbeb2e74084e8b8e8e846040516132b69493929190614b36565b60405180910390a150506005805460ff60a01b1916600160a01b1790555050505050505050505050565b606060008260148111156132f057fe5b60408051600a808252818301909252919250906060908260208201818036833701905050905060005b60ff84161561337f578151600a60ff959095168581049560018401939106916030830160f81b918591811061334a57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535050613319565b60608160010167ffffffffffffffff8111801561339b57600080fd5b506040519080825280601f01601f1916602001820160405280156133c6576020820181803683370190505b50905060005b82811161342f5783818403815181106133e157fe5b602001015160f81c60f81b8282815181106133f857fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506001016133cc565b509695505050505050565b8047101561345a5760405162461bcd60e51b815260040161077690614dde565b6000826001600160a01b03168260405161347390614a2b565b60006040518083038185875af1925050503d80600081146134b0576040519150601f19603f3d011682016040523d82523d6000602084013e6134b5565b606091505b505090508061082f5760405162461bcd60e51b815260040161077690614d81565b6000803d80156134ed57602081146134f657613502565b60019150613502565b60206000803e60005191505b501515905090565b600082820183811080159061351f5750828110155b6040518060400160405280601281526020017129b0b332a6b0ba341032bc31b2b83a34b7b760711b815250906135685760405162461bcd60e51b81526004016107769190614d37565b509392505050565b600082820283158061351f57508284828161358757fe5b04146040518060400160405280601281526020017129b0b332a6b0ba341032bc31b2b83a34b7b760711b815250906135685760405162461bcd60e51b81526004016107769190614d37565b60008a8a6040516020016135e7929190614a09565b604051602081830303815290604052805190602001209050613607613c64565b6001600160a01b031663f65d21166001838d8d8d8d8d8d8d8d8d6040518c63ffffffff1660e01b81526004016136479b9a99989796959493929190614c44565b60206040518083038186803b15801561365f57600080fd5b505afa158015613673573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136979190614328565b6136a160066132e0565b906136bf5760405162461bcd60e51b81526004016107769190614d37565b505050505050505050505050565b816001600160a01b03851661371a576b033b2e3c9fd0803ce80000004711156136f660026132e0565b906137145760405162461bcd60e51b81526004016107769190614d37565b50613780565b600061372586612dd0565b905060098160ff1611156137495760098160ff1603600a0a828161374557fe5b0491505b670de0b6b3a764000082111561375f60036132e0565b9061377d5760405162461bcd60e51b81526004016107769190614d37565b50505b7eb45d95b5117447e2fafe7f34def913ff3ba220e4b8688acf37ae2328af7a3d858583856040516137b49493929190614b01565b60405180910390a15050505050565b3b151590565b6000613818826040518060400160405280336001600160a01b03168152602001868152506040516020016137fd9190614fa5565b60405160208183030381529060405280519060200120611437565b6007549091506001600160a01b0380831691161461080f60106132e0565b5490565b80546001019055565b61384b613cf1565b613853613cf1565b604051806080016040528088600781111561386a57fe5b8152602001876001600160a01b0316815260200186868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525060200184905291505095945050505050565b815160208301206000906138dc81612eb9565b156138e760056132e0565b906139055760405162461bcd60e51b81526004016107769190614d37565b5060006139128483611437565b90506001600160a01b038116151561392a60106132e0565b906139485760405162461bcd60e51b81526004016107769190614d37565b506000918252600160208190526040909220805460ff19169092179091559392505050565b6005546001600160a01b0316158015906139ad57506001600160a01b0380831660009081526003602090815260408083209385168352929052205460ff16155b15613aab57600554604051637badcc6760e11b8152613a62916001600160a01b03169063f75b98ce906139e69085908790600401614a7f565b60206040518083038186803b1580156139fe57600080fd5b505afa158015613a12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a36919061485d565b6001600160a01b038085166000908152600260209081526040808320938716835292905220549061350a565b6001600160a01b038084166000818152600260209081526040808320948716808452948252808320959095559181526003825283812092815291905220805460ff191660011790555b5050565b6000828211156040518060400160405280601281526020017129b0b332a6b0ba341032bc31b2b83a34b7b760711b81525090613afe5760405162461bcd60e51b81526004016107769190614d37565b5050900390565b600080613b11866116e7565b90506001600160a01b038616613b2e57613b2b8134613aaf565b90505b84471015613b3c60076132e0565b90613b5a5760405162461bcd60e51b81526004016107769190614d37565b50600954604051631cff79cd60e01b81526060916001600160a01b031690631cff79cd908890613b909088908a90600401614adf565b6000604051808303818588803b158015613ba957600080fd5b505af1158015613bbd573d6000803e3d6000fd5b50505050506040513d6000823e601f3d908101601f19168201604052613be69190810190614516565b905060008082806020019051810190613bff9190613fe5565b91509150886001600160a01b0316826001600160a01b0316148015613c2f575080613c2d856125708c6116e7565b145b613c3960096132e0565b90613c575760405162461bcd60e51b81526004016107769190614d37565b5098975050505050505050565b7f62135fc083646fdb4e1a9d700e351b886a4a5a39da980650269edd1ade91ffd25490565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b604051806060016040528060006001600160a01b031681526020016060815260200160006001600160a01b031681525090565b6040805160808101909152806000815260200160006001600160a01b0316815260200160608152602001600081525090565b80356114c081615092565b60008083601f840112613d3f578182fd5b50813567ffffffffffffffff811115613d56578182fd5b6020830191508360208083028501011115613d7057600080fd5b9250929050565b600082601f830112613d87578081fd5b8135613d9a613d9582614ffa565b614fd3565b818152915060208083019084810181840286018201871015613dbb57600080fd5b60005b84811015613de3578135613dd1816150aa565b84529282019290820190600101613dbe565b505050505092915050565b600082601f830112613dfe578081fd5b8135613e0c613d9582614ffa565b818152915060208083019084810181840286018201871015613e2d57600080fd5b60005b84811015613de357813584529282019290820190600101613e30565b600082601f830112613e5c578081fd5b8135613e6a613d9582614ffa565b818152915060208083019084810181840286018201871015613e8b57600080fd5b6000805b85811015613eb957823560ff81168114613ea7578283fd5b85529383019391830191600101613e8f565b50505050505092915050565b60008083601f840112613ed6578182fd5b50813567ffffffffffffffff811115613eed578182fd5b602083019150836020828501011115613d7057600080fd5b600082601f830112613f15578081fd5b8135613f23613d958261501a565b9150808252836020828501011115613f3a57600080fd5b8060208401602084013760009082016020015292915050565b600060208284031215613f64578081fd5b8135613f6f81615092565b9392505050565b60008060008060008060c08789031215613f8e578182fd5b8635613f9981615092565b95506020870135613fa981615092565b945060408701359350606087013592506080870135613fc781615092565b915060a0870135613fd781615092565b809150509295509295509295565b60008060408385031215613ff7578182fd5b825161400281615092565b6020939093015192949293505050565b60008060408385031215614024578182fd5b823561402f81615092565b9150602083013561403f81615092565b809150509250929050565b60008060006060848603121561405e578081fd5b833561406981615092565b9250602084013561407981615092565b929592945050506040919091013590565b60008060006060848603121561409e578081fd5b83356140a981615092565b925060208401356140b981615092565b915060408401356140c981615092565b809150509250925092565b600080600080600060a086880312156140eb578283fd5b85356140f681615092565b9450602086013561410681615092565b935060408601359250606086013567ffffffffffffffff811115614128578182fd5b61413488828901613f05565b925050608086013561414581615092565b809150509295509295909350565b60008060008060008060008060008060e08b8d031215614171578788fd5b8a3561417c81615092565b995060208b0135985060408b013561419381615092565b97506141a28c60608d01613d23565b965060808b013567ffffffffffffffff808211156141be578586fd5b6141ca8e838f01613ec5565b909850965060a08d01359150808211156141e2578586fd5b6141ee8e838f01613ec5565b909650945060c08d0135915080821115614206578384fd5b506142138d828e01613ec5565b915080935050809150509295989b9194979a5092959850565b600080600080600080600060a0888a031215614246578081fd5b873561425181615092565b965060208801359550604088013567ffffffffffffffff80821115614274578283fd5b6142808b838c01613ec5565b909750955060608a0135945060808a013591508082111561429f578283fd5b506142ac8a828b01613ec5565b989b979a50959850939692959293505050565b600080600080604085870312156142d4578182fd5b843567ffffffffffffffff808211156142eb578384fd5b6142f788838901613d2e565b9096509450602087013591508082111561430f578384fd5b5061431c87828801613d2e565b95989497509550505050565b600060208284031215614339578081fd5b8151613f6f816150aa565b600060208284031215614355578081fd5b5035919050565b6000806020838503121561436e578182fd5b823567ffffffffffffffff811115614384578283fd5b61439085828601613ec5565b90969095509350505050565b60008060008060008060008060008060006101408c8e0312156143bd578485fd5b67ffffffffffffffff808d3511156143d3578586fd5b6143e08e8e358f01613ec5565b909c509a5060208d0135995060408d01358110156143fc578586fd5b61440c8e60408f01358f01613dee565b98508060608e0135111561441e578586fd5b61442e8e60608f01358f01613d77565b975060808d0135965060a08d013595508060c08e0135111561444e578182fd5b61445e8e60c08f01358f01613dee565b94508060e08e01351115614470578182fd5b6144808e60e08f01358f01613e4c565b9350806101008e01351115614493578182fd5b6144a48e6101008f01358f01613dee565b9250806101208e013511156144b7578182fd5b506144c98d6101208e01358e01613dee565b90509295989b509295989b9093969950565b6000602082840312156144ec578081fd5b813567ffffffffffffffff811115614502578182fd5b61450e84828501613f05565b949350505050565b600060208284031215614527578081fd5b815167ffffffffffffffff81111561453d578182fd5b8201601f8101841361454d578182fd5b805161455b613d958261501a565b81815285602083850101111561456f578384fd5b614580826020830160208601615066565b95945050505050565b6000806040838503121561459b578182fd5b823567ffffffffffffffff8111156145b1578283fd5b6145bd85828601613f05565b95602094909401359450505050565b6000806000806000806000806000806101408b8d0312156145eb578384fd5b8a3567ffffffffffffffff80821115614602578586fd5b61460e8e838f01613f05565b9b5060208d01359a5060408d013591508082111561462a578586fd5b6146368e838f01613dee565b995060608d013591508082111561464b578586fd5b6146578e838f01613d77565b985060808d0135975060a08d0135965060c08d013591508082111561467a578586fd5b6146868e838f01613dee565b955060e08d013591508082111561469b578485fd5b6146a78e838f01613e4c565b94506101008d01359150808211156146bd578384fd5b6146c98e838f01613dee565b93506101208d01359150808211156146df578283fd5b506146ec8d828e01613dee565b9150509295989b9194979a5092959850565b600080600080600080600080600080600060e08c8e03121561471e578485fd5b67ffffffffffffffff808d351115614734578586fd5b6147418e8e358f01613ec5565b909c509a506147538e60208f01613d23565b995060408d013598508060608e0135111561476c578586fd5b61477c8e60608f01358f01613ec5565b909850965060808d0135811015614791578586fd5b6147a18e60808f01358f01613ec5565b909650945060a08d0135935060c08d01358110156147bd578182fd5b506147ce8d60c08e01358e01613ec5565b81935080925050509295989b509295989b9093969950565b6000806000806000606086880312156147fd578283fd5b853567ffffffffffffffff80821115614814578485fd5b61482089838a01613ec5565b909750955060208801359450604088013591508082111561483f578283fd5b5061484c88828901613ec5565b969995985093965092949392505050565b60006020828403121561486e578081fd5b5051919050565b6000815180845260208085019450808401835b838110156148a6578151151587529582019590820190600101614888565b509495945050505050565b6000815180845260208085019450808401835b838110156148a6578151875295820195908201906001016148c4565b6000815180845260208085019450808401835b838110156148a657815160ff16875295820195908201906001016148f3565b60008284528282602086013780602084860101526020601f19601f85011685010190509392505050565b60008151808452614954816020860160208601615066565b601f01601f19169290920160200192915050565b60ff815116825260ff602082015116602083015260408101516001600160a01b03808216604085015280606084015116606085015250506080810151608083015260a081015160a08301525050565b60008151600881106149c557fe5b808452506001600160a01b0360208301511660208401526040820151608060408501526149f5608085018261493c565b606093840151949093019390935250919050565b60008351614a1b818460208801615066565b9190910191825250602001919050565b90565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0392831681529116602082015260400190565b60006001600160a01b038088168352808716602084015285604084015260a06060840152614aca60a084018661493c565b91508084166080840152509695505050505050565b60006001600160a01b03841682526040602083015261450e604083018461493c565b60006001600160a01b038616825260806020830152614b23608083018661493c565b6040830194909452506060015292915050565b60006001600160a01b038616825260606020830152614b59606083018587614912565b905082604083015295945050505050565b60006001600160a01b038716825260806020830152614b8d608083018688614912565b604083019490945250606001529392505050565b6040808252810184905260008560608301825b87811015614be45760208335614bc981615092565b6001600160a01b031683529283019290910190600101614bb4565b5083810360208501528481527f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff851115614c1c578283fd5b602085029150818660208301370160200190815295945050505050565b901515815260200190565b60006101608d151583528c60208401528b6040840152806060840152614c6c8184018c6148b1565b90508281036080840152614c80818b614875565b90508860a08401528760c084015282810360e0840152614ca081886148b1565b9050828103610100840152614cb581876148e0565b9050828103610120840152614cca81866148b1565b9050828103610140840152614cdf81856148b1565b9e9d5050505050505050505050505050565b90815260200190565b600084825283602083015260606040830152614580606083018461493c565b93845260ff9290921660208401526040830152606082015260800190565b600060208252613f6f602083018461493c565b60208082526018908201527f67657420455243323020646563696d616c206661696c65640000000000000000604082015260600190565b6020808252603a908201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260408201527f6563697069656e74206d61792068617665207265766572746564000000000000606082015260800190565b6020808252601d908201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604082015260600190565b60208082526016908201527f62616c616e63654f66206e6f6e2d636f6e747261637400000000000000000000604082015260600190565b60208082526018908201527f676574446563696d616c73206e6f6e2d636f6e74726163740000000000000000604082015260600190565b60208082526018908201527f6765742045524332302062616c616e6365206661696c65640000000000000000604082015260600190565b60c081016114c08284614968565b6000610100614ed78387614968565b8060c08401526001600160a01b038086511682850152602086015191506060610120850152614f0a61016085018361493c565b9150806040870151166101408501525082810360e0840152614f2c818561493c565b9695505050505050565b600060808252614f4960808301886149b7565b6001600160a01b038781166020850152861660408401528281036060840152614f73818587614912565b98975050505050505050565b600060408252614f9260408301866149b7565b8281036020840152614f2c818587614912565b81516001600160a01b031681526020918201519181019190915260400190565b60ff91909116815260200190565b60405181810167ffffffffffffffff81118282101715614ff257600080fd5b604052919050565b600067ffffffffffffffff821115615010578081fd5b5060209081020190565b600067ffffffffffffffff821115615030578081fd5b50601f01601f191660200190565b6000808585111561504d578182fd5b83861115615059578182fd5b5050820193919092039150565b60005b83811015615081578181015183820152602001615069565b8381111561082d5750506000910152565b6001600160a01b03811681146150a757600080fd5b50565b80151581146150a757600080fdfea264697066735822122099ad7207700f19c214687c5501da9eb61c9c1fba2a2d9dd954462f4e3c6de73364736f6c634300060c0033
Deployed Bytecode
0x6080604052600436106102a45760003560e01c8063995fac111161016e578063cde0a4f8116100cb578063dd8fee141161007f578063f75b98ce11610064578063f75b98ce146106f6578063fa84702e14610716578063fee8efda1461072b576102ab565b8063dd8fee14146106c1578063e4bd7074146106d6576102ab565b8063d6a1fe3b116100b0578063d6a1fe3b14610677578063d7200eb11461068c578063dca40d9e146106a1576102ab565b8063cde0a4f814610637578063cf54aaa014610657576102ab565b8063bd835c4211610122578063c0c53b8b11610107578063c0c53b8b146105ef578063c34c08e51461060f578063c791d70514610624576102ab565b8063bd835c42146105ba578063bda9b509146105cf576102ab565b8063a73b153211610153578063a73b15321461055a578063a807b5bb1461057a578063b8237dbb1461059a576102ab565b8063995fac1114610525578063a3f5d8cc14610545576102ab565b80636304541c1161021c57806373bf9651116101d05780637e16e6e1116101b55780637e16e6e1146104d257806384b3ac03146104ff5780638588ccd614610512576102ab565b806373bf965114610492578063749c5f86146104b2576102ab565b806366945b311161020157806366945b311461042e5780636f2cbc481461045d57806370a0823114610472576102ab565b80636304541c146103e157806365b5a00f1461040e576102ab565b8063392e53cd116102735780633fec6b40116102585780633fec6b401461037d578063568c04fd146103aa57806358bc8337146103cc576102ab565b8063392e53cd146103485780633ed1b3761461035d576102ab565b8063145e2a6b146102b05780631beb7de2146102d25780631ea1940e146102f25780631ed4276d14610328576102ab565b366102ab57005b600080fd5b3480156102bc57600080fd5b506102d06102cb36600461404a565b61074b565b005b3480156102de57600080fd5b506102d06102ed3660046145cc565b610834565b3480156102fe57600080fd5b5061031261030d366004614344565b610c91565b60405161031f9190614c39565b60405180910390f35b34801561033457600080fd5b506103126103433660046142bf565b610ca6565b34801561035457600080fd5b50610312610ec7565b34801561036957600080fd5b506102d061037836600461439c565b610ed7565b34801561038957600080fd5b5061039d610398366004614589565b611437565b60405161031f9190614a2e565b3480156103b657600080fd5b506103bf6114c6565b60405161031f9190614fc5565b3480156103d857600080fd5b5061039d6114cb565b3480156103ed57600080fd5b506104016103fc366004613f53565b6114d0565b60405161031f9190614cf1565b34801561041a57600080fd5b50610401610429366004614012565b6114e2565b34801561043a57600080fd5b5061044e61044936600461435c565b6114ff565b60405161031f93929190614ec8565b34801561046957600080fd5b506103bf6116e2565b34801561047e57600080fd5b5061040161048d366004613f53565b6116e7565b34801561049e57600080fd5b506102d06104ad3660046145cc565b6117bb565b3480156104be57600080fd5b506103126104cd366004614344565b611b33565b3480156104de57600080fd5b506104f26104ed3660046144db565b611c03565b60405161031f9190614eba565b6102d061050d3660046147e6565b611c85565b6102d0610520366004614153565b611dae565b34801561053157600080fd5b50610312610540366004614012565b61224c565b34801561055157600080fd5b5061031261226c565b34801561056657600080fd5b506102d0610575366004614012565b61227c565b34801561058657600080fd5b506102d061059536600461422c565b61231f565b3480156105a657600080fd5b506102d06105b536600461422c565b6125fe565b3480156105c657600080fd5b506103bf6128ec565b3480156105db57600080fd5b506104016105ea3660046140d4565b6128f1565b3480156105fb57600080fd5b506102d061060a36600461408a565b612b15565b34801561061b57600080fd5b5061039d612c1f565b6102d06106323660046147e6565b612c2e565b34801561064357600080fd5b506102d0610652366004613f53565b612d42565b34801561066357600080fd5b506103bf610672366004613f53565b612dd0565b34801561068357600080fd5b50610401612e8a565b34801561069857600080fd5b506103bf612e90565b3480156106ad57600080fd5b506103126106bc366004614344565b612e95565b3480156106cd57600080fd5b5061039d612eaa565b3480156106e257600080fd5b506103126106f1366004614344565b612eb9565b34801561070257600080fd5b50610401610711366004614012565b612f39565b34801561072257600080fd5b5061039d613065565b34801561073757600080fd5b506102d06107463660046146fe565b613074565b30331461075860146132e0565b9061077f5760405162461bcd60e51b81526004016107769190614d37565b60405180910390fd5b506001600160a01b03831661079d57610798828261343a565b61082f565b60405163a9059cbb60e01b81526001600160a01b0384169063a9059cbb906107cb9085908590600401614a66565b600060405180830381600087803b1580156107e557600080fd5b505af11580156107f9573d6000803e3d6000fd5b505050506108056134d6565b61080f60046132e0565b9061082d5760405162461bcd60e51b81526004016107769190614d37565b505b505050565b600554600160a01b900460ff1661084b60016132e0565b906108695760405162461bcd60e51b81526004016107769190614d37565b506005805460ff60a01b1916905589516082111561088760066132e0565b906108a55760405162461bcd60e51b81526004016107769190614d37565b506108ae613c89565b6108b78b611c03565b805190915060ff1660f11480156108d55750806020015160ff166001145b6108df60066132e0565b906108fd5760405162461bcd60e51b81526004016107769190614d37565b5061090b8160a00151611b33565b1561091660056132e0565b906109345760405162461bcd60e51b81526004016107769190614d37565b5060a081015160009081526020819052604090819020805460ff191660011790558101516001600160a01b03166109bf576040808201516001600160a01b0316600090815260046020522054608082015161098e9161350a565b47101561099b60076132e0565b906109b95760405162461bcd60e51b81526004016107769190614d37565b50610ad1565b60006109ce8260400151612dd0565b905060098160ff1611156109fb5760808201516109f59060081960ff841601600a0a613570565b60808301525b6040808301516001600160a01b03166000908152600460205220546080830151610a249161350a565b82604001516001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401610a549190614a2e565b60206040518083038186803b158015610a6c57600080fd5b505afa158015610a80573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aa4919061485d565b1015610ab060076132e0565b90610ace5760405162461bcd60e51b81526004016107769190614d37565b50505b610ae38b8b8b8b8b8b8b8b8b8b6135d2565b60408101516001600160a01b0316610b8c57600081606001516001600160a01b03168260800151604051610b1690614a2b565b60006040518083038185875af1925050503d8060008114610b53576040519150601f19603f3d011682016040523d82523d6000602084013e610b58565b606091505b5050905080610b6760046132e0565b90610b855760405162461bcd60e51b81526004016107769190614d37565b5050610c2a565b80604001516001600160a01b031663a9059cbb826060015183608001516040518363ffffffff1660e01b8152600401610bc6929190614a66565b600060405180830381600087803b158015610be057600080fd5b505af1158015610bf4573d6000803e3d6000fd5b50505050610c006134d6565b610c0a60046132e0565b90610c285760405162461bcd60e51b81526004016107769190614d37565b505b7f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb816040015182606001518360800151604051610c6993929190614a42565b60405180910390a150506005805460ff60a01b1916600160a01b179055505050505050505050565b60016020526000908152604090205460ff1681565b6005546000906001600160a01b031615801590610ccd57506005546001600160a01b031633145b610cd7600c6132e0565b90610cf55760405162461bcd60e51b81526004016107769190614d37565b50838214610d03600a6132e0565b90610d215760405162461bcd60e51b81526004016107769190614d37565b50600560009054906101000a90046001600160a01b03166001600160a01b0316635c975abb6040518163ffffffff1660e01b815260040160206040518083038186803b158015610d7057600080fd5b505afa158015610d84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610da89190614328565b610db2600d6132e0565b90610dd05760405162461bcd60e51b81526004016107769190614d37565b5060005b84811015610e7e57610e37848483818110610deb57fe5b9050602002013560046000898986818110610e0257fe5b9050602002016020810190610e179190613f53565b6001600160a01b031681526020810191909152604001600020549061350a565b60046000888885818110610e4757fe5b9050602002016020810190610e5c9190613f53565b6001600160a01b03168152602081019190915260400160002055600101610dd4565b507f6a7fbbcddfd518bb8c56b28ac6c7acb0f7ca093ed232eb3306e53d14e469895f85858585604051610eb49493929190614ba1565b60405180910390a1506001949350505050565b600554600160a81b900460ff1681565b600554600160a01b900460ff16610eee60016132e0565b90610f0c5760405162461bcd60e51b81526004016107769190614d37565b506005805460ff60a01b19169055610f22613c89565b610f2a613cbe565b6060610f368e8e6114ff565b925092509250610f498360a00151611b33565b15610f5460056132e0565b90610f725760405162461bcd60e51b81526004016107769190614d37565b5060a083015160009081526020819052604090819020805460ff191660011790558301516001600160a01b0316610ffd576040808401516001600160a01b03166000908152600460205220546080840151610fcc9161350a565b471015610fd960076132e0565b90610ff75760405162461bcd60e51b81526004016107769190614d37565b5061110f565b600061100c8460400151612dd0565b905060098160ff1611156110395760808401516110339060081960ff841601600a0a613570565b60808501525b6040808501516001600160a01b031660009081526004602052205460808501516110629161350a565b84604001516001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016110929190614a2e565b60206040518083038186803b1580156110aa57600080fd5b505afa1580156110be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110e2919061485d565b10156110ee60076132e0565b9061110c5760405162461bcd60e51b81526004016107769190614d37565b50505b6111658e8e8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508d8d8d8d8d8d8d8d8d6135d2565b60408084015160608501516080860151855193517fbda9b509000000000000000000000000000000000000000000000000000000008152309463bda9b509946111b8949093909290918891600401614a99565b602060405180830381600087803b1580156111d257600080fd5b505af1925050508015611202575060408051601f3d908101601f191682019092526111ff9181019061485d565b60015b61129b573d808015611230576040519150601f19603f3d011682016040523d82523d6000602084013e611235565b606091505b506112528460400151846020015186608001518760a001516136cd565b7fdbbb883f24557adf486292429863dcfd4ac5d4db168ae94921da8e3d9a95d4168460a0015160008360405161128a93929190614cfa565b60405180910390a150505050611417565b60408301516001600160a01b03166112ca576112c583600001518460200151838760a001516136cd565b611412565b825160408085015190517f145e2a6b000000000000000000000000000000000000000000000000000000008152309263145e2a6b9261130d928690600401614a42565b600060405180830381600087803b15801561132757600080fd5b505af1925050508015611338575060015b6113ce573d808015611366576040519150601f19603f3d011682016040523d82523d6000602084013e61136b565b606091505b5061138484600001518560200151848860a001516136cd565b7fdbbb883f24557adf486292429863dcfd4ac5d4db168ae94921da8e3d9a95d4168560a001516001836040516113bc93929190614cfa565b60405180910390a15050505050611417565b7f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb836000015184604001518360405161140993929190614a42565b60405180910390a15b505050505b50506005805460ff60a01b1916600160a01b179055505050505050505050565b60008060008060208601519150604086015192508560408151811061145857fe5b602001015160f81c60f81b60f81c601b0190506001858284866040516000815260200160405260405161148e9493929190614d19565b6020604051602081039080840390855afa1580156114b0573d6000803e3d6000fd5b5050506020604051035193505050505b92915050565b60f181565b600081565b60046020526000908152604090205481565b600260209081526000928352604080842090915290825290205481565b611507613c89565b61150f613cbe565b606061012884101561152160136132e0565b9061153f5760405162461bcd60e51b81526004016107769190614d37565b50611548613c89565b8585600081811061155557fe5b919091013560f81c8252508585600181811061156d57fe5b919091013560f81c60208301525060008686600281811061158a57fe5b845192013560f81c92505060ff16609e1480156115ae5750816020015160ff166001145b80156115bd575060ff81166001145b6115c760136132e0565b906115e55760405162461bcd60e51b81526004016107769190614d37565b50506115ef613cbe565b6115fd60c36003888a61503e565b81019061160a9190613f76565b6001600160a01b03908116604088810191909152918116875260a08801929092526080870192909252918216606086015291169083015261165061012860c3888a61503e565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050506020820152818161169988610128818c61503e565b81818080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250969e959d50919b50939950505050505050505050565b60f381565b60006001600160a01b0382166116fe5750476117b6565b611707826137c3565b6117235760405162461bcd60e51b815260040161077690614e15565b6040516370a0823160e01b81526001600160a01b038316906370a082319061174f903090600401614a2e565b60206040518083038186803b15801561176757600080fd5b505afa925050508015611797575060408051601f3d908101601f191682019092526117949181019061485d565b60015b6117b35760405162461bcd60e51b815260040161077690614e83565b90505b919050565b600554600160a01b900460ff166117d260016132e0565b906117f05760405162461bcd60e51b81526004016107769190614d37565b506005805460ff60a01b1916905589516082111561180e60066132e0565b9061182c5760405162461bcd60e51b81526004016107769190614d37565b50611835613c89565b61183e8b611c03565b805190915060ff1660f314801561185c5750806020015160ff166001145b61186660066132e0565b906118845760405162461bcd60e51b81526004016107769190614d37565b506118928160a00151611b33565b1561189d60056132e0565b906118bb5760405162461bcd60e51b81526004016107769190614d37565b5060a081015160009081526020819052604090819020805460ff191660011790558101516001600160a01b0316611946576040808201516001600160a01b031660009081526004602052205460808201516119159161350a565b47101561192260076132e0565b906119405760405162461bcd60e51b81526004016107769190614d37565b50611a58565b60006119558260400151612dd0565b905060098160ff16111561198257608082015161197c9060081960ff841601600a0a613570565b60808301525b6040808301516001600160a01b031660009081526004602052205460808301516119ab9161350a565b82604001516001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016119db9190614a2e565b60206040518083038186803b1580156119f357600080fd5b505afa158015611a07573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a2b919061485d565b1015611a3760076132e0565b90611a555760405162461bcd60e51b81526004016107769190614d37565b50505b611a6a8b8b8b8b8b8b8b8b8b8b6135d2565b608081015160608201516001600160a01b0390811660009081526002602090815260408083208187015190941683529290522054611aa79161350a565b60608201516001600160a01b03908116600090815260026020908152604080832081870180518616855290835281842095909555608086015194519093168252600490522054611af69161350a565b6040918201516001600160a01b031660009081526004602052919091205550506005805460ff60a01b1916600160a01b1790555050505050505050565b60008181526020819052604081205460ff1615611b52575060016117b6565b6005546001600160a01b0316611b6a575060006117b6565b6005546040517f749c5f860000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063749c5f8690611bb3908590600401614cf1565b60206040518083038186803b158015611bcb57600080fd5b505afa158015611bdf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117b39190614328565b611c0b613c89565b611c13613c89565b82600081518110611c2057fe5b016020015160f81c8152825183906001908110611c3957fe5b0160209081015160f81c9082015260228301516042840151606285015160828601516001600160a01b039384166040860152929091166060840152608083015260a08201529050919050565b600554600160a01b900460ff16611c9c60016132e0565b90611cba5760405162461bcd60e51b81526004016107769190614d37565b506005805460ff60a01b191690556b033b2e3c9fd0803ce8000000471115611ce260026132e0565b90611d005760405162461bcd60e51b81526004016107769190614d37565b50611d418383838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506137c992505050565b7fd30df8040a1092415b49422a02dbd8cdd5915a596abcba02cd0f65dd86ab38516000868634611d716006613836565b604051611d82959493929190614b6a565b60405180910390a1611d94600661383a565b50506005805460ff60a01b1916600160a01b179055505050565b600554600160a01b900460ff16611dc560016132e0565b90611de35760405162461bcd60e51b81526004016107769190614d37565b506005805460ff60a01b191690556000611e5f611e03828d88888f613843565b8a8a8a8a604051602001611e1b959493929190614f36565b60408051601f198184030181526020601f8701819004810284018101909252858352919086908690819084018382808284376000920191909152506138c992505050565b9050611e6b818c61396d565b6001600160a01b038082166000908152600260209081526040808320938f16835292905220548a1115611e9e60086132e0565b90611ebc5760405162461bcd60e51b81526004016107769190614d37565b506001600160a01b038b16600090815260046020526040902054611ee0908b613aaf565b6001600160a01b03808d1660008181526004602090815260408083209590955592851681526002835283812091815291522054611f1d908b613aaf565b60026000836001600160a01b03166001600160a01b0316815260200190815260200160002060008d6001600160a01b03166001600160a01b0316815260200190815260200160002081905550600034905060006001600160a01b03168c6001600160a01b03161415611f9a57611f93818c61350a565b90506120db565b6040516370a0823160e01b81528b906001600160a01b038e16906370a0823190611fc8903090600401614a2e565b60206040518083038186803b158015611fe057600080fd5b505afa158015611ff4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612018919061485d565b101561202460076132e0565b906120425760405162461bcd60e51b81526004016107769190614d37565b5060095460405163a9059cbb60e01b81526001600160a01b038e81169263a9059cbb9261207792909116908f90600401614a66565b600060405180830381600087803b15801561209157600080fd5b505af11580156120a5573d6000803e3d6000fd5b505050506120b16134d6565b6120bb60046132e0565b906120d95760405162461bcd60e51b81526004016107769190614d37565b505b600061212d8b838b8b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508d613b05565b905061218a8160026000866001600160a01b03166001600160a01b0316815260200190815260200160002060008e6001600160a01b03166001600160a01b031681526020019081526020016000205461350a90919063ffffffff16565b60026000856001600160a01b03166001600160a01b0316815260200190815260200160002060008d6001600160a01b03166001600160a01b031681526020019081526020016000208190555061220e81600460008e6001600160a01b03166001600160a01b031681526020019081526020016000205461350a90919063ffffffff16565b6001600160a01b03909b1660009081526004602052604090209a909a5550506005805460ff60a01b1916600160a01b17905550505050505050505050565b600360209081526000928352604080842090915290825290205460ff1681565b600554600160a01b900460ff1681565b6008541561228a60126132e0565b906122a85760405162461bcd60e51b81526004016107769190614d37565b5060026008556007546001600160a01b0316156122c560116132e0565b906122e35760405162461bcd60e51b81526004016107769190614d37565b50600780546001600160a01b0393841673ffffffffffffffffffffffffffffffffffffffff199182161790915560098054929093169116179055565b600554600160a01b900460ff1661233660016132e0565b906123545760405162461bcd60e51b81526004016107769190614d37565b506005805460ff60a01b19169055604080516020601f84018190048102820181019092528281526123a29185919085908590819084018382808284376000920191909152506137c992505050565b8660006123ae82612dd0565b90506000826001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016123de9190614a2e565b60206040518083038186803b1580156123f657600080fd5b505afa15801561240a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061242e919061485d565b90508089600960ff851611156124695760098460ff1603600a0a818161245057fe5b04905060098460ff1603600a0a838161246557fe5b0492505b670de0b6b3a764000081111580156124895750670de0b6b3a76400008311155b80156124a65750670de0b6b3a76400006124a3828561350a565b11155b6124b060036132e0565b906124ce5760405162461bcd60e51b81526004016107769190614d37565b50846001600160a01b03166323b872dd33308e6040518463ffffffff1660e01b81526004016124ff93929190614a42565b600060405180830381600087803b15801561251957600080fd5b505af115801561252d573d6000803e3d6000fd5b505050506125396134d6565b61254360046132e0565b906125615760405162461bcd60e51b81526004016107769190614d37565b508a612576836125708f6116e7565b90613aaf565b14612581600a6132e0565b9061259f5760405162461bcd60e51b81526004016107769190614d37565b507f2d4b597935f3cd67fb2eebf1db4debc934cee5c7baa7153f980fdbeb2e74084e8c8b8b846040516125d59493929190614b36565b60405180910390a150506005805460ff60a01b1916600160a01b17905550505050505050505050565b600554600160a01b900460ff1661261560016132e0565b906126335760405162461bcd60e51b81526004016107769190614d37565b506005805460ff60a01b19169055604080516020601f84018190048102820181019092528281526126819185919085908590819084018382808284376000920191909152506137c992505050565b86600061268d82612dd0565b90506000826001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016126bd9190614a2e565b60206040518083038186803b1580156126d557600080fd5b505afa1580156126e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061270d919061485d565b90508089600960ff851611156127485760098460ff1603600a0a818161272f57fe5b04905060098460ff1603600a0a838161274457fe5b0492505b670de0b6b3a764000081111580156127685750670de0b6b3a76400008311155b80156127855750670de0b6b3a7640000612782828561350a565b11155b61278f60036132e0565b906127ad5760405162461bcd60e51b81526004016107769190614d37565b50846001600160a01b03166323b872dd33308e6040518463ffffffff1660e01b81526004016127de93929190614a42565b600060405180830381600087803b1580156127f857600080fd5b505af115801561280c573d6000803e3d6000fd5b505050506128186134d6565b61282260046132e0565b906128405760405162461bcd60e51b81526004016107769190614d37565b508a61284f836125708f6116e7565b1461285a600a6132e0565b906128785760405162461bcd60e51b81526004016107769190614d37565b507fd30df8040a1092415b49422a02dbd8cdd5915a596abcba02cd0f65dd86ab38518c8b8b846128a86006613836565b6040516128b9959493929190614b6a565b60405180910390a16128cb600661383a565b50506005805460ff60a01b1916600160a01b17905550505050505050505050565b609e81565b600030331461290060146132e0565b9061291e5760405162461bcd60e51b81526004016107769190614d37565b50600061292a836116e7565b9050606060006001600160a01b0389166129455750856129dd565b60095460405163a9059cbb60e01b81526001600160a01b038b81169263a9059cbb9261297992909116908b90600401614a66565b600060405180830381600087803b15801561299357600080fd5b505af11580156129a7573d6000803e3d6000fd5b505050506129b36134d6565b6129bd60046132e0565b906129db5760405162461bcd60e51b81526004016107769190614d37565b505b600954604051631cff79cd60e01b81526001600160a01b0390911690631cff79cd908390612a11908c908b90600401614adf565b6000604051808303818588803b158015612a2a57600080fd5b505af1158015612a3e573d6000803e3d6000fd5b50505050506040513d6000823e601f3d908101601f19168201604052612a679190810190614516565b91508151604014612a7860096132e0565b90612a965760405162461bcd60e51b81526004016107769190614d37565b5060008083806020019051810190612aae9190613fe5565b91509150866001600160a01b0316826001600160a01b0316148015612ade575080612adc866125708a6116e7565b145b612ae860096132e0565b90612b065760405162461bcd60e51b81526004016107769190614d37565b509a9950505050505050505050565b600554600160a81b900460ff1615612b2d600f6132e0565b90612b4b5760405162461bcd60e51b81526004016107769190614d37565b506005805460ff60a01b197fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff6001600160a01b0380881673ffffffffffffffffffffffffffffffffffffffff199094169390931716600160a81b1716600160a01b179091556007541615612bbf60116132e0565b90612bdd5760405162461bcd60e51b81526004016107769190614d37565b50600780546001600160a01b0393841673ffffffffffffffffffffffffffffffffffffffff199182161790915560098054929093169116179055506002600855565b6009546001600160a01b031681565b600554600160a01b900460ff16612c4560016132e0565b90612c635760405162461bcd60e51b81526004016107769190614d37565b506005805460ff60a01b191690556b033b2e3c9fd0803ce8000000471115612c8b60026132e0565b90612ca95760405162461bcd60e51b81526004016107769190614d37565b50612cea8383838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506137c992505050565b7f2d4b597935f3cd67fb2eebf1db4debc934cee5c7baa7153f980fdbeb2e74084e6000868634604051612d209493929190614b36565b60405180910390a150506005805460ff60a01b1916600160a01b179055505050565b6007546001600160a01b03161580612d6457506007546001600160a01b031633145b8015612d7857506001600160a01b03811615155b612d8260116132e0565b90612da05760405162461bcd60e51b81526004016107769190614d37565b506007805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b6000612ddb826137c3565b612df75760405162461bcd60e51b815260040161077690614e4c565b6000829050806001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015612e3557600080fd5b505afa925050508015612e65575060408051601f3d908101601f19168201909252612e629181019061485d565b60015b612e815760405162461bcd60e51b815260040161077690614d4a565b91506117b69050565b60085481565b600181565b60006020819052908152604090205460ff1681565b6007546001600160a01b031681565b60008181526001602052604081205460ff1615612ed8575060016117b6565b6005546001600160a01b0316612ef0575060006117b6565b6005546040517fe4bd70740000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063e4bd707490611bb3908590600401614cf1565b6005546000906001600160a01b031615801590612f7c57506001600160a01b0380831660009081526003602090815260408083209387168352929052205460ff16155b1561303857600554604051637badcc6760e11b8152613031916001600160a01b03169063f75b98ce90612fb59087908790600401614a7f565b60206040518083038186803b158015612fcd57600080fd5b505afa158015612fe1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613005919061485d565b6001600160a01b038085166000908152600260209081526040808320938916835292905220549061350a565b90506114c0565b506001600160a01b0380821660009081526002602090815260408083209386168352929052205492915050565b6005546001600160a01b031681565b600554600160a01b900460ff1661308b60016132e0565b906130a95760405162461bcd60e51b81526004016107769190614d37565b506005805460ff60a01b19169055604080516020601f84018190048102820181019092528281526130f79185919085908590819084018382808284376000920191909152506137c992505050565b600061316261310a60018c89898e613843565b8d8d60405160200161311e93929190614f7f565b60408051601f198184030181526020601f8c018190048102840181019092528a835291908b908b90819084018382808284376000920191909152506138c992505050565b905061316e818b61396d565b6001600160a01b038082166000908152600260209081526040808320938e16835292905220548911156131a160086132e0565b906131bf5760405162461bcd60e51b81526004016107769190614d37565b506001600160a01b038082166000908152600260209081526040808320938e16835292905220546131f0908a613aaf565b6001600160a01b038083166000908152600260209081526040808320938f16835292815282822093909355600490925290205461322d908a613aaf565b6001600160a01b038b1660008181526004602052604090209190915589901561328157600061325b8c612dd0565b905060098160ff16111561327f5760098160ff1603600a0a8b8161327b57fe5b0491505b505b7f2d4b597935f3cd67fb2eebf1db4debc934cee5c7baa7153f980fdbeb2e74084e8b8e8e846040516132b69493929190614b36565b60405180910390a150506005805460ff60a01b1916600160a01b1790555050505050505050505050565b606060008260148111156132f057fe5b60408051600a808252818301909252919250906060908260208201818036833701905050905060005b60ff84161561337f578151600a60ff959095168581049560018401939106916030830160f81b918591811061334a57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535050613319565b60608160010167ffffffffffffffff8111801561339b57600080fd5b506040519080825280601f01601f1916602001820160405280156133c6576020820181803683370190505b50905060005b82811161342f5783818403815181106133e157fe5b602001015160f81c60f81b8282815181106133f857fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506001016133cc565b509695505050505050565b8047101561345a5760405162461bcd60e51b815260040161077690614dde565b6000826001600160a01b03168260405161347390614a2b565b60006040518083038185875af1925050503d80600081146134b0576040519150601f19603f3d011682016040523d82523d6000602084013e6134b5565b606091505b505090508061082f5760405162461bcd60e51b815260040161077690614d81565b6000803d80156134ed57602081146134f657613502565b60019150613502565b60206000803e60005191505b501515905090565b600082820183811080159061351f5750828110155b6040518060400160405280601281526020017129b0b332a6b0ba341032bc31b2b83a34b7b760711b815250906135685760405162461bcd60e51b81526004016107769190614d37565b509392505050565b600082820283158061351f57508284828161358757fe5b04146040518060400160405280601281526020017129b0b332a6b0ba341032bc31b2b83a34b7b760711b815250906135685760405162461bcd60e51b81526004016107769190614d37565b60008a8a6040516020016135e7929190614a09565b604051602081830303815290604052805190602001209050613607613c64565b6001600160a01b031663f65d21166001838d8d8d8d8d8d8d8d8d6040518c63ffffffff1660e01b81526004016136479b9a99989796959493929190614c44565b60206040518083038186803b15801561365f57600080fd5b505afa158015613673573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136979190614328565b6136a160066132e0565b906136bf5760405162461bcd60e51b81526004016107769190614d37565b505050505050505050505050565b816001600160a01b03851661371a576b033b2e3c9fd0803ce80000004711156136f660026132e0565b906137145760405162461bcd60e51b81526004016107769190614d37565b50613780565b600061372586612dd0565b905060098160ff1611156137495760098160ff1603600a0a828161374557fe5b0491505b670de0b6b3a764000082111561375f60036132e0565b9061377d5760405162461bcd60e51b81526004016107769190614d37565b50505b7eb45d95b5117447e2fafe7f34def913ff3ba220e4b8688acf37ae2328af7a3d858583856040516137b49493929190614b01565b60405180910390a15050505050565b3b151590565b6000613818826040518060400160405280336001600160a01b03168152602001868152506040516020016137fd9190614fa5565b60405160208183030381529060405280519060200120611437565b6007549091506001600160a01b0380831691161461080f60106132e0565b5490565b80546001019055565b61384b613cf1565b613853613cf1565b604051806080016040528088600781111561386a57fe5b8152602001876001600160a01b0316815260200186868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525060200184905291505095945050505050565b815160208301206000906138dc81612eb9565b156138e760056132e0565b906139055760405162461bcd60e51b81526004016107769190614d37565b5060006139128483611437565b90506001600160a01b038116151561392a60106132e0565b906139485760405162461bcd60e51b81526004016107769190614d37565b506000918252600160208190526040909220805460ff19169092179091559392505050565b6005546001600160a01b0316158015906139ad57506001600160a01b0380831660009081526003602090815260408083209385168352929052205460ff16155b15613aab57600554604051637badcc6760e11b8152613a62916001600160a01b03169063f75b98ce906139e69085908790600401614a7f565b60206040518083038186803b1580156139fe57600080fd5b505afa158015613a12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a36919061485d565b6001600160a01b038085166000908152600260209081526040808320938716835292905220549061350a565b6001600160a01b038084166000818152600260209081526040808320948716808452948252808320959095559181526003825283812092815291905220805460ff191660011790555b5050565b6000828211156040518060400160405280601281526020017129b0b332a6b0ba341032bc31b2b83a34b7b760711b81525090613afe5760405162461bcd60e51b81526004016107769190614d37565b5050900390565b600080613b11866116e7565b90506001600160a01b038616613b2e57613b2b8134613aaf565b90505b84471015613b3c60076132e0565b90613b5a5760405162461bcd60e51b81526004016107769190614d37565b50600954604051631cff79cd60e01b81526060916001600160a01b031690631cff79cd908890613b909088908a90600401614adf565b6000604051808303818588803b158015613ba957600080fd5b505af1158015613bbd573d6000803e3d6000fd5b50505050506040513d6000823e601f3d908101601f19168201604052613be69190810190614516565b905060008082806020019051810190613bff9190613fe5565b91509150886001600160a01b0316826001600160a01b0316148015613c2f575080613c2d856125708c6116e7565b145b613c3960096132e0565b90613c575760405162461bcd60e51b81526004016107769190614d37565b5098975050505050505050565b7f62135fc083646fdb4e1a9d700e351b886a4a5a39da980650269edd1ade91ffd25490565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b604051806060016040528060006001600160a01b031681526020016060815260200160006001600160a01b031681525090565b6040805160808101909152806000815260200160006001600160a01b0316815260200160608152602001600081525090565b80356114c081615092565b60008083601f840112613d3f578182fd5b50813567ffffffffffffffff811115613d56578182fd5b6020830191508360208083028501011115613d7057600080fd5b9250929050565b600082601f830112613d87578081fd5b8135613d9a613d9582614ffa565b614fd3565b818152915060208083019084810181840286018201871015613dbb57600080fd5b60005b84811015613de3578135613dd1816150aa565b84529282019290820190600101613dbe565b505050505092915050565b600082601f830112613dfe578081fd5b8135613e0c613d9582614ffa565b818152915060208083019084810181840286018201871015613e2d57600080fd5b60005b84811015613de357813584529282019290820190600101613e30565b600082601f830112613e5c578081fd5b8135613e6a613d9582614ffa565b818152915060208083019084810181840286018201871015613e8b57600080fd5b6000805b85811015613eb957823560ff81168114613ea7578283fd5b85529383019391830191600101613e8f565b50505050505092915050565b60008083601f840112613ed6578182fd5b50813567ffffffffffffffff811115613eed578182fd5b602083019150836020828501011115613d7057600080fd5b600082601f830112613f15578081fd5b8135613f23613d958261501a565b9150808252836020828501011115613f3a57600080fd5b8060208401602084013760009082016020015292915050565b600060208284031215613f64578081fd5b8135613f6f81615092565b9392505050565b60008060008060008060c08789031215613f8e578182fd5b8635613f9981615092565b95506020870135613fa981615092565b945060408701359350606087013592506080870135613fc781615092565b915060a0870135613fd781615092565b809150509295509295509295565b60008060408385031215613ff7578182fd5b825161400281615092565b6020939093015192949293505050565b60008060408385031215614024578182fd5b823561402f81615092565b9150602083013561403f81615092565b809150509250929050565b60008060006060848603121561405e578081fd5b833561406981615092565b9250602084013561407981615092565b929592945050506040919091013590565b60008060006060848603121561409e578081fd5b83356140a981615092565b925060208401356140b981615092565b915060408401356140c981615092565b809150509250925092565b600080600080600060a086880312156140eb578283fd5b85356140f681615092565b9450602086013561410681615092565b935060408601359250606086013567ffffffffffffffff811115614128578182fd5b61413488828901613f05565b925050608086013561414581615092565b809150509295509295909350565b60008060008060008060008060008060e08b8d031215614171578788fd5b8a3561417c81615092565b995060208b0135985060408b013561419381615092565b97506141a28c60608d01613d23565b965060808b013567ffffffffffffffff808211156141be578586fd5b6141ca8e838f01613ec5565b909850965060a08d01359150808211156141e2578586fd5b6141ee8e838f01613ec5565b909650945060c08d0135915080821115614206578384fd5b506142138d828e01613ec5565b915080935050809150509295989b9194979a5092959850565b600080600080600080600060a0888a031215614246578081fd5b873561425181615092565b965060208801359550604088013567ffffffffffffffff80821115614274578283fd5b6142808b838c01613ec5565b909750955060608a0135945060808a013591508082111561429f578283fd5b506142ac8a828b01613ec5565b989b979a50959850939692959293505050565b600080600080604085870312156142d4578182fd5b843567ffffffffffffffff808211156142eb578384fd5b6142f788838901613d2e565b9096509450602087013591508082111561430f578384fd5b5061431c87828801613d2e565b95989497509550505050565b600060208284031215614339578081fd5b8151613f6f816150aa565b600060208284031215614355578081fd5b5035919050565b6000806020838503121561436e578182fd5b823567ffffffffffffffff811115614384578283fd5b61439085828601613ec5565b90969095509350505050565b60008060008060008060008060008060006101408c8e0312156143bd578485fd5b67ffffffffffffffff808d3511156143d3578586fd5b6143e08e8e358f01613ec5565b909c509a5060208d0135995060408d01358110156143fc578586fd5b61440c8e60408f01358f01613dee565b98508060608e0135111561441e578586fd5b61442e8e60608f01358f01613d77565b975060808d0135965060a08d013595508060c08e0135111561444e578182fd5b61445e8e60c08f01358f01613dee565b94508060e08e01351115614470578182fd5b6144808e60e08f01358f01613e4c565b9350806101008e01351115614493578182fd5b6144a48e6101008f01358f01613dee565b9250806101208e013511156144b7578182fd5b506144c98d6101208e01358e01613dee565b90509295989b509295989b9093969950565b6000602082840312156144ec578081fd5b813567ffffffffffffffff811115614502578182fd5b61450e84828501613f05565b949350505050565b600060208284031215614527578081fd5b815167ffffffffffffffff81111561453d578182fd5b8201601f8101841361454d578182fd5b805161455b613d958261501a565b81815285602083850101111561456f578384fd5b614580826020830160208601615066565b95945050505050565b6000806040838503121561459b578182fd5b823567ffffffffffffffff8111156145b1578283fd5b6145bd85828601613f05565b95602094909401359450505050565b6000806000806000806000806000806101408b8d0312156145eb578384fd5b8a3567ffffffffffffffff80821115614602578586fd5b61460e8e838f01613f05565b9b5060208d01359a5060408d013591508082111561462a578586fd5b6146368e838f01613dee565b995060608d013591508082111561464b578586fd5b6146578e838f01613d77565b985060808d0135975060a08d0135965060c08d013591508082111561467a578586fd5b6146868e838f01613dee565b955060e08d013591508082111561469b578485fd5b6146a78e838f01613e4c565b94506101008d01359150808211156146bd578384fd5b6146c98e838f01613dee565b93506101208d01359150808211156146df578283fd5b506146ec8d828e01613dee565b9150509295989b9194979a5092959850565b600080600080600080600080600080600060e08c8e03121561471e578485fd5b67ffffffffffffffff808d351115614734578586fd5b6147418e8e358f01613ec5565b909c509a506147538e60208f01613d23565b995060408d013598508060608e0135111561476c578586fd5b61477c8e60608f01358f01613ec5565b909850965060808d0135811015614791578586fd5b6147a18e60808f01358f01613ec5565b909650945060a08d0135935060c08d01358110156147bd578182fd5b506147ce8d60c08e01358e01613ec5565b81935080925050509295989b509295989b9093969950565b6000806000806000606086880312156147fd578283fd5b853567ffffffffffffffff80821115614814578485fd5b61482089838a01613ec5565b909750955060208801359450604088013591508082111561483f578283fd5b5061484c88828901613ec5565b969995985093965092949392505050565b60006020828403121561486e578081fd5b5051919050565b6000815180845260208085019450808401835b838110156148a6578151151587529582019590820190600101614888565b509495945050505050565b6000815180845260208085019450808401835b838110156148a6578151875295820195908201906001016148c4565b6000815180845260208085019450808401835b838110156148a657815160ff16875295820195908201906001016148f3565b60008284528282602086013780602084860101526020601f19601f85011685010190509392505050565b60008151808452614954816020860160208601615066565b601f01601f19169290920160200192915050565b60ff815116825260ff602082015116602083015260408101516001600160a01b03808216604085015280606084015116606085015250506080810151608083015260a081015160a08301525050565b60008151600881106149c557fe5b808452506001600160a01b0360208301511660208401526040820151608060408501526149f5608085018261493c565b606093840151949093019390935250919050565b60008351614a1b818460208801615066565b9190910191825250602001919050565b90565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0392831681529116602082015260400190565b60006001600160a01b038088168352808716602084015285604084015260a06060840152614aca60a084018661493c565b91508084166080840152509695505050505050565b60006001600160a01b03841682526040602083015261450e604083018461493c565b60006001600160a01b038616825260806020830152614b23608083018661493c565b6040830194909452506060015292915050565b60006001600160a01b038616825260606020830152614b59606083018587614912565b905082604083015295945050505050565b60006001600160a01b038716825260806020830152614b8d608083018688614912565b604083019490945250606001529392505050565b6040808252810184905260008560608301825b87811015614be45760208335614bc981615092565b6001600160a01b031683529283019290910190600101614bb4565b5083810360208501528481527f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff851115614c1c578283fd5b602085029150818660208301370160200190815295945050505050565b901515815260200190565b60006101608d151583528c60208401528b6040840152806060840152614c6c8184018c6148b1565b90508281036080840152614c80818b614875565b90508860a08401528760c084015282810360e0840152614ca081886148b1565b9050828103610100840152614cb581876148e0565b9050828103610120840152614cca81866148b1565b9050828103610140840152614cdf81856148b1565b9e9d5050505050505050505050505050565b90815260200190565b600084825283602083015260606040830152614580606083018461493c565b93845260ff9290921660208401526040830152606082015260800190565b600060208252613f6f602083018461493c565b60208082526018908201527f67657420455243323020646563696d616c206661696c65640000000000000000604082015260600190565b6020808252603a908201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260408201527f6563697069656e74206d61792068617665207265766572746564000000000000606082015260800190565b6020808252601d908201527f416464726573733a20696e73756666696369656e742062616c616e6365000000604082015260600190565b60208082526016908201527f62616c616e63654f66206e6f6e2d636f6e747261637400000000000000000000604082015260600190565b60208082526018908201527f676574446563696d616c73206e6f6e2d636f6e74726163740000000000000000604082015260600190565b60208082526018908201527f6765742045524332302062616c616e6365206661696c65640000000000000000604082015260600190565b60c081016114c08284614968565b6000610100614ed78387614968565b8060c08401526001600160a01b038086511682850152602086015191506060610120850152614f0a61016085018361493c565b9150806040870151166101408501525082810360e0840152614f2c818561493c565b9695505050505050565b600060808252614f4960808301886149b7565b6001600160a01b038781166020850152861660408401528281036060840152614f73818587614912565b98975050505050505050565b600060408252614f9260408301866149b7565b8281036020840152614f2c818587614912565b81516001600160a01b031681526020918201519181019190915260400190565b60ff91909116815260200190565b60405181810167ffffffffffffffff81118282101715614ff257600080fd5b604052919050565b600067ffffffffffffffff821115615010578081fd5b5060209081020190565b600067ffffffffffffffff821115615030578081fd5b50601f01601f191660200190565b6000808585111561504d578182fd5b83861115615059578182fd5b5050820193919092039150565b60005b83811015615081578181015183820152602001615069565b8381111561082d5750506000910152565b6001600160a01b03811681146150a757600080fd5b50565b80151581146150a757600080fdfea264697066735822122099ad7207700f19c214687c5501da9eb61c9c1fba2a2d9dd954462f4e3c6de73364736f6c634300060c0033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.