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
|
|||||
---|---|---|---|---|---|---|---|---|---|
0x60808060 | 19839599 | 117 days ago | IN | 0 ETH | 0.01846532 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
XBridge
Compiler Version
v0.8.20+commit.a1b79de6
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol"; import "./interfaces/IERC20.sol"; import "./interfaces/IUniswapV2Router02.sol"; import "./interfaces/IUniswapV2Factory.sol"; contract XBridge is OwnableUpgradeable, ReentrancyGuardUpgradeable { uint256 public listingFee; address public factory; address public tokenFeeCollector; address public listingFeeCollector; address[] public admin; address public usdt; IUniswapV2Router02 public router; uint256 public thresholdLimit; struct tokenInfo { address token; uint256 chain; } mapping(address => bool) public isBase; mapping(address => bool) public isWrapped; mapping(address => uint256) public tokenTax; mapping(uint256 => bool) public chainSupported; mapping(address => uint256) public feesForToken; mapping(address => uint256) public tokenChainId; mapping(address => address) public tokenToToken; mapping(address => bool) public excludeFeeFromListing; mapping(address => mapping(address => bool)) public isMintable; mapping(uint256 => mapping(address => uint256)) public inNonce; mapping(address => mapping(address => address)) public tokenOwner; mapping(address => mapping(address => uint256)) public tokenDeposited; mapping(address => mapping(address => uint256)) public tokenWithdrawn; mapping(uint256 => mapping(address => mapping(uint256 => bool))) public nonceProcessed; event Locked(address indexed user, address indexed inToken, address indexed outToken, uint256 amount, uint256 feeAmount, uint256 _nonce, uint256 isWrapped, uint256 srcId, uint256 dstId); event UnLocked(address indexed user, address indexed outToken, uint256 amount, uint256 feeAmount, uint256 _nonce, uint256 srcId, uint256 dstId); event TokenListed(address indexed baseToken, uint256 baseTokenChain, address indexed correspondingToken, uint256 correspondingTokenChain, bool isMintable, address indexed user); event TokenDelisted(address indexed baseToken, uint256 baseTokenChain, address indexed correspondingToken, uint256 correspondingTokenChain); event TokenDeposited(address indexed user, uint256 amount); event TokenWithdrawn(address indexed user, address indexed receiver, uint256 amount); event SignersChanged(address[] indexed newSigners); event ChainSupported(uint256 _chain, bool _supported); event FeeExcludedFromListing(address indexed user, bool ifExcluded); event TokenFee(address indexed _token, uint256 _fee); mapping(uint256 => mapping(uint256 => mapping(address => bool))) public isWrappedWithChainId; mapping(uint256 => mapping(uint256 => mapping(address => mapping(address => address)))) public tokenOwnerWithChainId; mapping(uint256 => mapping(uint256 => mapping(address => address))) public tokenToTokenWithChainId; mapping(uint256 => mapping(uint256 => mapping(address => mapping(address => bool)))) public isMintableWithChainId; mapping(address => address) public _tokenOwner; address public native; // 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE constructor() { _disableInitializers(); } function initialize(address[] memory _admin, uint256 _listingFee, address _tokenFeeCollector, address _listingFeeCollector, address _router, address _factory, address _usdt) external initializer { require(_admin.length >= 3, "MINIMUM_SIGNERS_SHOULD_BE_3"); require(_listingFee > 0, "LISTING_FEE_CANT_BE_ZERO"); require(_tokenFeeCollector != address(0) && _listingFeeCollector != address(0), "CANT_PROVIDE_ZERO_ADDRESS"); __Ownable_init(); __ReentrancyGuard_init(); admin = _admin; listingFee = _listingFee; tokenFeeCollector = _tokenFeeCollector; listingFeeCollector = _listingFeeCollector; router = IUniswapV2Router02(_router); factory = _factory; usdt = _usdt; thresholdLimit = 100 * 10**6; // native = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; } /** * @dev cannot receive eth directly */ receive() external payable { revert("DIRECT_ETH_TRANSFER_NOT_SUPPORTED"); } /** * @dev cannot receive eth directly */ fallback() external payable { revert("DIRECT_ETH_TRANSFER_NOT_SUPPORTED"); } /** * @dev Lock the `_amount` of `inTokens` in the bridge contract for `dstId` chain. * @param inToken locking token address * @param _amount amount of token to lock * @param dstId destination chain on which user will claim token * Emits a {Locked} event. */ function lock(address inToken, uint256 _amount, uint256 dstId) external payable nonReentrant { require(_amount > 0, "AMOUNT_CANT_BE_ZERO"); require(inToken != address(0), "TOKEN_ADDRESS_CANT_BE_NULL"); // require(inToken.code.length > 0, "TOKEN_NOT_ON_THIS_CHAIN"); require(chainSupported[dstId], "INVALID_CHAIN"); uint256 srcId; assembly { srcId := chainid() } address outToken = tokenToTokenWithChainId[srcId][dstId][inToken]; require(outToken != address(0), "UNSUPPORTED_TOKEN"); uint256 _isWrapped; if(isWrappedWithChainId[srcId][dstId][inToken]) _isWrapped = 1; else if(inToken == native || outToken == native) _isWrapped =2; else _isWrapped = 0; address _user = msg.sender; uint256 tokenAmount; uint256 fee = feesForToken[inToken]; uint256 feesAmount; if(_isWrapped == 0) { (tokenAmount, feesAmount) = transferAndCalcAmountAndFees(inToken, _user, _amount, fee); emit Locked(_user, inToken, outToken, tokenAmount, feesAmount, inNonce[dstId][_user]++, _isWrapped, srcId, dstId); } else if(_isWrapped == 1) { (tokenAmount, feesAmount) = transferAndCalcAmountAndFees(inToken, _user, _amount, fee); burn(inToken, tokenAmount+feesAmount); emit Locked(_user, inToken, outToken, tokenAmount, feesAmount, inNonce[dstId][_user]++, _isWrapped, srcId, dstId); } else if (_isWrapped == 2) { if(inToken == native) { tokenAmount = _amount; fee = feesForToken[inToken]; if(fee > 0) { feesAmount = _amount * fee / 100; tokenAmount -= feesAmount; } require(_amount == msg.value, "LESS_LOCKING"); emit Locked(_user, inToken, outToken, tokenAmount, feesAmount, inNonce[dstId][_user]++, _isWrapped, srcId, dstId); } else { (tokenAmount, feesAmount) = transferAndCalcAmountAndFees(inToken, _user, _amount, fee); emit Locked(_user, inToken, outToken, tokenAmount, feesAmount, inNonce[dstId][_user]++, _isWrapped, srcId, dstId); } } } /** * @dev Unlock the `amount` of tokens corresponding to `inToken` * @param inToken locked token address * @param amount amount of token to unlock * @param feeAmount fee on locked amount on source chain * @param _nonce user lock nonce on source chain * @param _isWrapped 1 if inToken is mintable otherwise 0 * @param srcId source chain on which user has locked token * @param r[] r part of the signature of the signers * @param s[] s part of the signature of the signers * @param v[] v part of the signature of the signers * Emits a {unLocked} event. */ function unlock(address inToken, uint256 amount, uint256 feeAmount, uint256 _nonce, uint256 _isWrapped, uint256 srcId, bytes32[] memory r, bytes32[] memory s, uint8[] memory v) external payable nonReentrant { address user = msg.sender; require(inToken != address(0), "TOKEN_ADDRESS_CANT_BE_NULL"); require(user != address(0), "INVALID_RECEIVER"); require(amount > 0, "AMOUNT_CANT_BE_ZERO"); require(!nonceProcessed[srcId][user][_nonce], "NONCE_ALREADY_PROCESSED"); require(chainSupported[srcId], "INVALID_CHAIN"); uint256 dstId; assembly { dstId := chainid() } address outToken = tokenToTokenWithChainId[srcId][dstId][inToken]; require(outToken != address(0), "UNSUPPORTED_TOKEN"); bool mintable = isMintableWithChainId[srcId][dstId][inToken][outToken]; bool success = verify(address(this), user, inToken, outToken, _nonce, amount, feeAmount, _isWrapped, srcId, dstId, r, s, v); require(success, "INVALID_RECOVERED_SIGNER"); if(!mintable && outToken !=native) require((IERC20(outToken).balanceOf(address(this)) - tokenTax[outToken]) >= (amount + feeAmount), "INSUFFICIENT_LIQUIDITY_IN_BRIDGE"); // inToken is base token then isWrapped = 0 // inToken is wrapped token then isWrapped = 1 nonceProcessed[srcId][user][_nonce] = true; if(_isWrapped == 0) { if(mintable) { if(feeAmount > 0) mint(outToken, tokenFeeCollector, feeAmount); mint(outToken, user, amount); } else { if(feeAmount > 0) { tokenTax[outToken] += feeAmount; } success = IERC20(outToken).transfer(user, amount); if(!success) revert("TOKEN_TRANSFER_FAILED"); } } else if(_isWrapped == 1) { if(outToken == native) { require(address(this).balance >= amount+feeAmount, "INSUFFICIENT_FUND_IN_BRIDE"); if(feeAmount > 0) { (success, ) = payable(tokenFeeCollector).call{value: feeAmount}(""); require(success, "FEE_TRANSFER_FAILED"); } (success, ) = payable(user).call{value: amount}(""); require(success, "NATIVE_COIN_TRANSFER_FAILED"); } else { if(feeAmount > 0) { tokenTax[outToken] += feeAmount; } success = IERC20(outToken).transfer(user, amount); if(!success) revert("TOKEN_TRANSFER_FAILED"); } } else if(_isWrapped == 2) { if(outToken == native) { require(address(this).balance >= amount+feeAmount, "INSUFFICIENT_FUND_IN_BRIDE"); if(feeAmount > 0) { (success, ) = payable(tokenFeeCollector).call{value: feeAmount}(""); require(success, "FEE_TRANSFER_FAILED"); } (success, ) = payable(user).call{value: amount}(""); require(success, "NATIVE_COIN_TRANSFER_FAILED"); } else if(mintable) { if(feeAmount > 0) mint(outToken, tokenFeeCollector, feeAmount); mint(outToken, user, amount); } else { if(feeAmount > 0) { tokenTax[outToken] += feeAmount; } success = IERC20(outToken).transfer(user, amount); if(!success) revert("TOKEN_TRANSFER_FAILED"); } } if(outToken != native && IUniswapV2Factory(router.factory()).getPair(outToken, router.WETH()) != address(0) && tokenTax[outToken] > 0) { address[] memory path = new address[](3); path[0] = outToken; path[1] = router.WETH(); path[2] = usdt; uint _amount = router.getAmountsOut(tokenTax[outToken], path)[2]; if(_amount >= thresholdLimit) { swapTokensForETH(outToken, tokenTax[outToken], router.WETH()); tokenTax[outToken] = 0; } } else if(outToken != native && IUniswapV2Factory(router.factory()).getPair(outToken, usdt) != address(0) && tokenTax[outToken] > 0) { address[] memory path = new address[](2); path[0] = outToken; path[1] = usdt; uint _amount = router.getAmountsOut(tokenTax[outToken], path)[1]; if(_amount >= thresholdLimit) { swapTokensForETH(outToken, tokenTax[outToken], usdt); tokenTax[outToken] = 0; } } emit UnLocked(user, outToken, amount, feeAmount, _nonce, srcId, dstId); } function swapTokensForETH(address _token, uint256 _amount, address pairToken) internal { safeApprove(_token, address(router), _amount); if(pairToken == router.WETH()) { address[] memory path = new address[](2); path[0] = _token; path[1] = pairToken; router.swapExactTokensForETHSupportingFeeOnTransferTokens(_amount, 0, path, tokenFeeCollector, block.timestamp); } else { address[] memory path = new address[](3); path[0] = _token; path[1] = usdt; path[2] = router.WETH(); router.swapExactTokensForETHSupportingFeeOnTransferTokens(_amount, 0, path, tokenFeeCollector, block.timestamp); } } function safeApprove(address token, address to, uint value) internal { // bytes4(keccak256(bytes('approve(address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool))), "APPROVE_FAILED"); } /** * @dev internal function to call mint function of the token address */ function mint(address token, address to, uint256 amount) internal { bytes memory init = returnHash(to, amount); if (init.length > 0) call(init, token); } /** * @dev internal function to call burn function of the token address */ function burn(address token, uint256 amount) internal { bytes memory init = returnHash(amount); if (init.length > 0) call(init, token); } /** * @dev function to calculate the fees amount and transfer token from user to this contract */ function transferAndCalcAmountAndFees(address token, address _user, uint256 amount, uint256 fee) private returns(uint256 tokenAmount, uint256 feeAmount) { uint256 beforeAmount = (IERC20(token).balanceOf(address(this))); bool success = IERC20(token).transferFrom(_user, address(this), amount); if(!success) revert("TRANSFER_FAILED_WHILE_LOCKING"); tokenAmount = (IERC20(token).balanceOf(address(this))) - beforeAmount; if(fee > 0) { feeAmount = tokenAmount * fee / 10000; tokenAmount -= feeAmount; } } /** * @dev function to verify the authenticity of the signatures provided in form of r[], s[] and v[] */ function verify(address dstContract, address user, address inToken, address outToken, uint256 nonce, uint256 amount, uint256 feeAmount, uint256 _isWrapped, uint256 srcId, uint256 dstId, bytes32[] memory sigR, bytes32[] memory sigS, uint8[] memory sigV) internal view returns (bool) { uint256 len = admin.length; require(sigR.length == len && sigS.length == len && sigV.length == len, "INVALID_NUMBER_OF_SIGNERS"); for(uint i=0; i<len; ++i) { bytes32 hash = prefixed(keccak256(abi.encodePacked(dstContract, user, inToken, outToken, nonce, amount, feeAmount, _isWrapped, srcId, dstId))); address signer = ecrecover(hash, sigV[i], sigR[i], sigS[i]); require(signer != address(0), "INVALID_SIGNATURE"); require(admin[i] == signer, "INVALID_VALIDATOR"); } return true; } /** * @dev making hash EIP-191 compatible */ function prefixed(bytes32 hash) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); } /** * @dev returning the encoded mint function to call */ function returnHash(address to, uint256 amount) internal pure returns(bytes memory data) { data = abi.encodeWithSignature("mint(address,uint256)", to, amount); } /** * @dev calling the `token` contract with `callData` */ function call(bytes memory callData, address token) internal { IERC20 _token = IERC20(payable(token)); assembly { if eq(call(gas(), _token, 0, add(callData, 0x20), mload(callData), 0, 0), 0) { revert(0, 0) } } } /** * @dev returning the encoded mint function to call */ function returnHash(uint256 amount) internal pure returns(bytes memory data) { data = abi.encodeWithSignature("burn(uint256)", amount); } /** * @dev token owner can list the pair of their token with their corresponding chain id * @param baseToken struct that contains token address and its corresponding chain id * @param correspondingToken struct that contains token address and its corresponding chain id * @param _isMintable if corresponding token address is mintable then its `true` otherwise `false` */ function listToken(tokenInfo memory baseToken, tokenInfo memory correspondingToken, bool _isMintable) external payable { address _baseToken = baseToken.token; address _correspondingToken = correspondingToken.token; require(_baseToken != address(0), "INVALID_ADDR"); require(_correspondingToken != address(0), "INVALID_ADDR"); if(baseToken.chain == block.chainid) { require(chainSupported[correspondingToken.chain], "CHAIN_NOT_SUPPORTED"); } else if(correspondingToken.chain == block.chainid) { require(chainSupported[baseToken.chain], "CHAIN_NOT_SUPPORTED"); } else { revert("CHAIN_NOT_SUPPORTED"); } require(tokenToTokenWithChainId[baseToken.chain][correspondingToken.chain][_baseToken] == address(0) && tokenToTokenWithChainId[baseToken.chain][correspondingToken.chain][_correspondingToken] == address(0), "THIS_PAIR_ALREADY_LISTED"); isMintableWithChainId[baseToken.chain][correspondingToken.chain][_baseToken][_correspondingToken] = _isMintable; isMintableWithChainId[baseToken.chain][correspondingToken.chain][_correspondingToken][_baseToken] = _isMintable; isMintableWithChainId[correspondingToken.chain][baseToken.chain][_baseToken][_correspondingToken] = _isMintable; isMintableWithChainId[correspondingToken.chain][baseToken.chain][_correspondingToken][_baseToken] = _isMintable; tokenToTokenWithChainId[baseToken.chain][correspondingToken.chain][_baseToken] = _correspondingToken; tokenToTokenWithChainId[baseToken.chain][correspondingToken.chain][_correspondingToken] = _baseToken; tokenToTokenWithChainId[correspondingToken.chain][baseToken.chain][_baseToken] = _correspondingToken; tokenToTokenWithChainId[correspondingToken.chain][baseToken.chain][_correspondingToken] = _baseToken; if(_isMintable) { isWrappedWithChainId[baseToken.chain][correspondingToken.chain][_correspondingToken] = true; isWrappedWithChainId[correspondingToken.chain][baseToken.chain][_correspondingToken] = true; isWrapped[_correspondingToken] = true; } tokenOwnerWithChainId[baseToken.chain][correspondingToken.chain][_baseToken][_correspondingToken] = msg.sender; tokenOwnerWithChainId[baseToken.chain][correspondingToken.chain][_correspondingToken][_baseToken] = msg.sender; tokenOwnerWithChainId[correspondingToken.chain][baseToken.chain][_baseToken][_correspondingToken] = msg.sender; tokenOwnerWithChainId[correspondingToken.chain][baseToken.chain][_correspondingToken][_baseToken] = msg.sender; if(_baseToken == _correspondingToken) _tokenOwner[_baseToken] = msg.sender; else { if(_baseToken.code.length > 0) _tokenOwner[_baseToken] = msg.sender; else _tokenOwner[_correspondingToken] = msg.sender; } if(!excludeFeeFromListing[msg.sender]) transferListingFee(listingFeeCollector, msg.sender, msg.value); emit TokenListed(_baseToken, baseToken.chain, _correspondingToken, correspondingToken.chain, _isMintable, msg.sender); } /** * @dev platform owner can delist the pair of the token * @param baseToken struct that contains token address and its corresponding chain id * @param correspondingToken struct that contains token address and its corresponding chain id */ function delistTokenByOwner(tokenInfo memory baseToken, tokenInfo memory correspondingToken) external onlyOwner { address _baseToken = baseToken.token; address _correspondingToken = correspondingToken.token; require(_baseToken != address(0), "INVALID_ADDR"); require(_correspondingToken != address(0), "INVALID_ADDR"); if(baseToken.chain == block.chainid) { require(chainSupported[correspondingToken.chain], "CHAIN_NOT_SUPPORTED"); } else if(correspondingToken.chain == block.chainid) { require(chainSupported[baseToken.chain], "CHAIN_NOT_SUPPORTED"); } else { revert("CHAIN_NOT_SUPPORTED"); } require(tokenToTokenWithChainId[baseToken.chain][correspondingToken.chain][_baseToken] != address(0) && tokenToTokenWithChainId[baseToken.chain][correspondingToken.chain][_correspondingToken] != address(0), "THIS_PAIR_ALREADY_LISTED"); delete tokenToTokenWithChainId[baseToken.chain][correspondingToken.chain][_baseToken]; delete tokenToTokenWithChainId[baseToken.chain][correspondingToken.chain][_correspondingToken]; delete tokenToTokenWithChainId[correspondingToken.chain][baseToken.chain][_baseToken]; delete tokenToTokenWithChainId[correspondingToken.chain][baseToken.chain][_correspondingToken]; delete tokenOwnerWithChainId[baseToken.chain][correspondingToken.chain][_baseToken][_correspondingToken]; delete tokenOwnerWithChainId[baseToken.chain][correspondingToken.chain][_correspondingToken][_baseToken]; delete tokenOwnerWithChainId[correspondingToken.chain][baseToken.chain][_baseToken][_correspondingToken]; delete tokenOwnerWithChainId[correspondingToken.chain][baseToken.chain][_correspondingToken][_baseToken]; emit TokenDelisted(_baseToken, baseToken.chain, _correspondingToken, correspondingToken.chain); } /** * @dev token lister can delist the pair of the token * @param baseToken struct that contains token address and its corresponding chain id * @param correspondingToken struct that contains token address and its corresponding chain id */ function delistTokenByUser(tokenInfo memory baseToken, tokenInfo memory correspondingToken) external { address _baseToken = baseToken.token; address _correspondingToken = correspondingToken.token; if(baseToken.chain == block.chainid) { require(chainSupported[correspondingToken.chain], "CHAIN_NOT_SUPPORTED"); } else if(correspondingToken.chain == block.chainid) { require(chainSupported[baseToken.chain], "CHAIN_NOT_SUPPORTED"); } else { revert("CHAIN_NOT_SUPPORTED"); } require(tokenOwnerWithChainId[baseToken.chain][correspondingToken.chain][_baseToken][_correspondingToken] == msg.sender, "NOT_TOKEN_OWNER"); require(tokenToTokenWithChainId[baseToken.chain][correspondingToken.chain][_baseToken] != address(0) && tokenToTokenWithChainId[baseToken.chain][correspondingToken.chain][_correspondingToken] != address(0), "ALREADY_DELISTED"); require(_baseToken != address(0), "INVALID_ADDR"); require(_correspondingToken != address(0), "INVALID_ADDR"); delete tokenToTokenWithChainId[baseToken.chain][correspondingToken.chain][_baseToken]; delete tokenToTokenWithChainId[baseToken.chain][correspondingToken.chain][_correspondingToken]; delete tokenToTokenWithChainId[correspondingToken.chain][baseToken.chain][_baseToken]; delete tokenToTokenWithChainId[correspondingToken.chain][baseToken.chain][_correspondingToken]; delete tokenOwnerWithChainId[baseToken.chain][correspondingToken.chain][_baseToken][_correspondingToken]; delete tokenOwnerWithChainId[baseToken.chain][correspondingToken.chain][_correspondingToken][_baseToken]; delete tokenOwnerWithChainId[correspondingToken.chain][baseToken.chain][_baseToken][_correspondingToken]; delete tokenOwnerWithChainId[correspondingToken.chain][baseToken.chain][_correspondingToken][_baseToken]; emit TokenDelisted(_baseToken, baseToken.chain, _correspondingToken, correspondingToken.chain); } /** * @dev take the listing fee while listing token */ function transferListingFee(address to, address _user, uint256 _value) private nonReentrant { require(to != address(0), "CANT_SEND_TO_NULL_ADDRESS"); require(_value >= listingFee, "INCREASE_LISTING_FEE"); (bool success, ) = payable(to).call{value:listingFee}(""); require(success, "LISTING_FEE_TRANSFER_FAILED"); uint256 remainingEth = _value - listingFee; if (remainingEth > 0) { (success,) = payable(_user).call{value: remainingEth}(""); require(success, "REFUND_REMAINING_ETHER_SENT_FAILED"); } } /** * @dev owner can change the listing fee */ function setListingFee(uint256 newFee) external onlyOwner { require(newFee != listingFee, "SAME_FEE_PROVIDED"); require(newFee >= 0, "INVALID_FEE"); listingFee = newFee; } /** * @dev owner can change the listing fee collector address */ function setListingFeeCollector(address collector) external onlyOwner { require(collector != address(0), "CANT_BE_NULL_ADDRESS"); listingFeeCollector = collector; } /** * @dev owner can exclude particular address to give the listing fee while listing token */ function setExcludeFeeFromListing(address user, bool ifExcluded) external onlyOwner { require(user != address(0), "CANT_BE_NULL_ADDRESS"); bool _previousState = excludeFeeFromListing[user]; if(_previousState == ifExcluded) revert("ALREADY_SET"); else excludeFeeFromListing[user] = ifExcluded; emit FeeExcludedFromListing(user, ifExcluded); } /** * @dev owner can change the signer addresses */ function changeAdmin(address[] memory newAdmin) external onlyOwner { require(newAdmin.length >= 3, "VALIDATORS_ARE_LESS_THAN_3"); admin = newAdmin; emit SignersChanged(newAdmin); } /** * @dev owner can set fee for particular token for bridging */ function setFeeForToken(address token, uint256 fee) external onlyOwner { require(token != address(0), "INVALID_TOKEN"); require(fee < 10000, "FEE_CANT_BE_100%"); feesForToken[token] = fee; emit TokenFee(token, fee); } /** * @dev owner can set if particular chain is supported or not */ function setChainSupported(uint256 chainId, bool supported) external onlyOwner { require(chainId != 0, "INVALID_CHAIN_ID"); chainSupported[chainId] = supported; emit ChainSupported(chainId, supported); } /** * @dev owner can change the token fee collector address */ function setFeeCollector(address collector) external onlyOwner { require(collector != address(0), "INVALID_OWNER"); tokenFeeCollector = collector; } /** * @dev returns total number of signers that are verified while unlocking the tokens */ function getTotalSigners() external view returns(uint256) { return admin.length; } /** * @dev token lister has to deposit tokens if none of the listed token are mintable or burnable * @param token token address to deposit in bridge contract * @param amount amount of tokens to deposit in bridge contract */ function depositTokens(address token, uint256 amount) external payable { require(amount > 0, "AMOUNT_CANT_BE_ZERO"); if(token == native) require(msg.value > 0, "AMOUNT_CANT_BE_ZERO"); address user = msg.sender; require(user == _tokenOwner[token], "ONLY_LISTER_CAN_DEPOSIT"); uint256 actualBal; if(token != native) { require(token.code.length > 0, "TOKEN_NOT_DEPLOYED_ON_THIS_CHAIN"); uint256 beforeBal = IERC20(token).balanceOf(address(this)); IERC20(token).transferFrom(user, address(this), amount); actualBal = IERC20(token).balanceOf(address(this)) - beforeBal; } else actualBal = msg.value; emit TokenDeposited(user, actualBal); } /** * @dev token lister can withdraw tokens * @param token token address to withdraw from bridge contract * @param receiver address to recive the withdrawn tokens * @param amount amount of tokens to deposit in bridge contract */ function withdrawTokens(address token, address receiver, uint256 amount) external { require(token != address(0), "TOKEN_NOT_LISTED"); require(amount > 0, "AMOUNT_CANT_BE_ZERO"); address user = msg.sender; require(user == _tokenOwner[token], "ONLY_TOKEN_LISTER_CAN_WITHDRAW"); if(token != native) { require(amount <= (IERC20(token).balanceOf(address(this)) - tokenTax[token]), "WITHDRAW_LESS"); if(isWrapped[token]) revert("CANT_WITHDRAW_WRAPPED_TOKENS"); IERC20(token).transfer(receiver, amount); } else { require(amount <= address(this).balance, "WITHDRAW_LESS"); (bool success, ) = payable(receiver).call{value: amount}(""); require(success, "WITHDRAW_FAILED"); } emit TokenWithdrawn(user, receiver, amount); } function claimTax(address token, bool pairWithEth, bool withdrawAnyAmount) external onlyOwner { require(token != native, "CANT_BE_NATIVE_TOKEN"); if(pairWithEth && tokenTax[token] > 0) { address[] memory path = new address[](3); path[0] = token; path[1] = router.WETH(); path[2] = usdt; uint _amount = router.getAmountsOut(tokenTax[token], path)[2]; if(_amount >= thresholdLimit || withdrawAnyAmount) { swapTokensForETH(token, tokenTax[token], router.WETH()); tokenTax[token] = 0; } } else if(!pairWithEth && tokenTax[token] > 0) { address[] memory path = new address[](2); path[0] = token; path[1] = usdt; uint _amount = router.getAmountsOut(tokenTax[token], path)[1]; if(_amount >= thresholdLimit || withdrawAnyAmount) { swapTokensForETH(token, tokenTax[token], usdt); tokenTax[token] = 0; } } } function viewTax(address token, bool pairWithEth) external view returns(uint _amount) { if(pairWithEth && tokenTax[token] > 0) { address[] memory path = new address[](3); path[0] = token; path[1] = router.WETH(); path[2] = usdt; _amount = router.getAmountsOut(tokenTax[token], path)[2]; } else if(!pairWithEth && tokenTax[token] > 0) { address[] memory path = new address[](2); path[0] = token; path[1] = usdt; _amount = router.getAmountsOut(tokenTax[token], path)[1]; } else _amount = 0; } /** * @dev token lister can change their ownership of listing tokens * @param token token address to change its lister owner * @param newOwner new owner address */ function changeTokenLister(address token, address newOwner, uint256 srcId, uint256 dstId) external { require(token.code.length > 0, "TOKEN_NOT_DEPLOYED_ON_THIS_CHAIN"); require(newOwner != address(0), "NEW_OWNER_CANT_BE_NULL"); address _correspondingToken = tokenToTokenWithChainId[srcId][dstId][token]; require(_correspondingToken != address(0), "TOKEN_NOT_LISTED"); address user = msg.sender; require(tokenOwnerWithChainId[srcId][dstId][token][_correspondingToken] == user, "ONLY_TOKEN_LISTER_CAN_CHANGE"); tokenOwnerWithChainId[srcId][dstId][token][_correspondingToken] = newOwner; tokenOwnerWithChainId[srcId][dstId][_correspondingToken][token] = newOwner; tokenOwnerWithChainId[dstId][srcId][token][_correspondingToken] = newOwner; tokenOwnerWithChainId[dstId][srcId][_correspondingToken][token] = newOwner; } /** * @dev returns the addresses of signers */ function getSigners() external view returns(address[] memory ) { return admin; } function setThresholdLimit(uint256 _amount) external onlyOwner { thresholdLimit = _amount; } function setRouter(address _router) external onlyOwner { router = IUniswapV2Router02(_router); } function setUsdt(address _usdt) external onlyOwner { require(_usdt != address(0), "CANT_BE_NULL_ADDRESS"); usdt = _usdt; } function setNative(address _native) external onlyOwner { require(_native != address(0), "CANT_BE_NULL_ADDRESS"); native = _native; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import "../proxy/utils/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function __Ownable_init() internal onlyInitializing { __Ownable_init_unchained(); } function __Ownable_init_unchained() internal onlyInitializing { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a * constructor. * * Emits an {Initialized} event. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _initialized = 1; if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: setting the version to 255 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint8 version) { require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); _initialized = version; _initializing = true; _; _initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized != type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint8) { return _initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _initializing; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuardUpgradeable is Initializable { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; function __ReentrancyGuard_init() internal onlyInitializing { __ReentrancyGuard_init_unchained(); } function __ReentrancyGuard_init_unchained() internal onlyInitializing { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be _NOT_ENTERED require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { return _status == _ENTERED; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.2; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @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 * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); function mint(address to, uint256 amount) external returns (bool); function burn(uint256 amount) external returns (bool); function transferOwnership(address newOwner) external; }
// SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; interface IUniswapV2Factory { function getPair(address tokenA, address tokenB) external view returns (address pair); }
// SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; interface IUniswapV2Router01 { function factory() external pure returns (address); function WETH() external pure returns (address); function addLiquidity( address tokenA, address tokenB, uint amountADesired, uint amountBDesired, uint amountAMin, uint amountBMin, address to, uint deadline ) external returns (uint amountA, uint amountB, uint liquidity); function addLiquidityETH( address token, uint amountTokenDesired, uint amountTokenMin, uint amountETHMin, address to, uint deadline ) external payable returns (uint amountToken, uint amountETH, uint liquidity); function removeLiquidity( address tokenA, address tokenB, uint liquidity, uint amountAMin, uint amountBMin, address to, uint deadline ) external returns (uint amountA, uint amountB); function removeLiquidityETH( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline ) external returns (uint amountToken, uint amountETH); function removeLiquidityWithPermit( address tokenA, address tokenB, uint liquidity, uint amountAMin, uint amountBMin, address to, uint deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint amountA, uint amountB); function removeLiquidityETHWithPermit( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint amountToken, uint amountETH); function swapExactTokensForTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline ) external returns (uint[] memory amounts); function swapTokensForExactTokens( uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline ) external returns (uint[] memory amounts); function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline) external payable returns (uint[] memory amounts); function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts); function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts); function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline) external payable returns (uint[] memory amounts); function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB); function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut); function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn); function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts); function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts); }
// SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; import "./IUniswapV2Router01.sol"; interface IUniswapV2Router02 is IUniswapV2Router01 { function removeLiquidityETHSupportingFeeOnTransferTokens( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline ) external returns (uint amountETH); function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint amountETH); function swapExactTokensForTokensSupportingFeeOnTransferTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline ) external; function swapExactETHForTokensSupportingFeeOnTransferTokens( uint amountOutMin, address[] calldata path, address to, uint deadline ) external payable; function swapExactTokensForETHSupportingFeeOnTransferTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline ) external; }
{ "optimizer": { "enabled": true, "runs": 200 }, "viaIR": true, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_chain","type":"uint256"},{"indexed":false,"internalType":"bool","name":"_supported","type":"bool"}],"name":"ChainSupported","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"bool","name":"ifExcluded","type":"bool"}],"name":"FeeExcludedFromListing","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"inToken","type":"address"},{"indexed":true,"internalType":"address","name":"outToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"feeAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_nonce","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"isWrapped","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"srcId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"dstId","type":"uint256"}],"name":"Locked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address[]","name":"newSigners","type":"address[]"}],"name":"SignersChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"baseToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"baseTokenChain","type":"uint256"},{"indexed":true,"internalType":"address","name":"correspondingToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"correspondingTokenChain","type":"uint256"}],"name":"TokenDelisted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TokenDeposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_token","type":"address"},{"indexed":false,"internalType":"uint256","name":"_fee","type":"uint256"}],"name":"TokenFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"baseToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"baseTokenChain","type":"uint256"},{"indexed":true,"internalType":"address","name":"correspondingToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"correspondingTokenChain","type":"uint256"},{"indexed":false,"internalType":"bool","name":"isMintable","type":"bool"},{"indexed":true,"internalType":"address","name":"user","type":"address"}],"name":"TokenListed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TokenWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"outToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"feeAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_nonce","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"srcId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"dstId","type":"uint256"}],"name":"UnLocked","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"_tokenOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"chainSupported","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"newAdmin","type":"address[]"}],"name":"changeAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"newOwner","type":"address"},{"internalType":"uint256","name":"srcId","type":"uint256"},{"internalType":"uint256","name":"dstId","type":"uint256"}],"name":"changeTokenLister","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"bool","name":"pairWithEth","type":"bool"},{"internalType":"bool","name":"withdrawAnyAmount","type":"bool"}],"name":"claimTax","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"chain","type":"uint256"}],"internalType":"struct XBridge.tokenInfo","name":"baseToken","type":"tuple"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"chain","type":"uint256"}],"internalType":"struct XBridge.tokenInfo","name":"correspondingToken","type":"tuple"}],"name":"delistTokenByOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"chain","type":"uint256"}],"internalType":"struct XBridge.tokenInfo","name":"baseToken","type":"tuple"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"chain","type":"uint256"}],"internalType":"struct XBridge.tokenInfo","name":"correspondingToken","type":"tuple"}],"name":"delistTokenByUser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"depositTokens","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"excludeFeeFromListing","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"feesForToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSigners","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalSigners","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"inNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_admin","type":"address[]"},{"internalType":"uint256","name":"_listingFee","type":"uint256"},{"internalType":"address","name":"_tokenFeeCollector","type":"address"},{"internalType":"address","name":"_listingFeeCollector","type":"address"},{"internalType":"address","name":"_router","type":"address"},{"internalType":"address","name":"_factory","type":"address"},{"internalType":"address","name":"_usdt","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isBase","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"isMintable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"isMintableWithChainId","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isWrapped","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"isWrappedWithChainId","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"chain","type":"uint256"}],"internalType":"struct XBridge.tokenInfo","name":"baseToken","type":"tuple"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"chain","type":"uint256"}],"internalType":"struct XBridge.tokenInfo","name":"correspondingToken","type":"tuple"},{"internalType":"bool","name":"_isMintable","type":"bool"}],"name":"listToken","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"listingFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"listingFeeCollector","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"inToken","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"dstId","type":"uint256"}],"name":"lock","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"native","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"nonceProcessed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"router","outputs":[{"internalType":"contract IUniswapV2Router02","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"bool","name":"supported","type":"bool"}],"name":"setChainSupported","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"bool","name":"ifExcluded","type":"bool"}],"name":"setExcludeFeeFromListing","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"collector","type":"address"}],"name":"setFeeCollector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"fee","type":"uint256"}],"name":"setFeeForToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newFee","type":"uint256"}],"name":"setListingFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"collector","type":"address"}],"name":"setListingFeeCollector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_native","type":"address"}],"name":"setNative","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_router","type":"address"}],"name":"setRouter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"setThresholdLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_usdt","type":"address"}],"name":"setUsdt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"thresholdLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"tokenChainId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"tokenDeposited","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenFeeCollector","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"tokenOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"tokenOwnerWithChainId","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"tokenTax","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"tokenToToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"tokenToTokenWithChainId","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"tokenWithdrawn","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"inToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"feeAmount","type":"uint256"},{"internalType":"uint256","name":"_nonce","type":"uint256"},{"internalType":"uint256","name":"_isWrapped","type":"uint256"},{"internalType":"uint256","name":"srcId","type":"uint256"},{"internalType":"bytes32[]","name":"r","type":"bytes32[]"},{"internalType":"bytes32[]","name":"s","type":"bytes32[]"},{"internalType":"uint8[]","name":"v","type":"uint8[]"}],"name":"unlock","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"usdt","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"bool","name":"pairWithEth","type":"bool"}],"name":"viewTax","outputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60808060405234620000c4575f549060ff8260081c1662000072575060ff8082160362000037575b6040516151339081620000c98239f35b60ff90811916175f557f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498602060405160ff8152a15f62000027565b62461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b6064820152608490fd5b5f80fdfe60806040526004361015610018575b3661332b5761332b565b5f3560e01c806305a71b73146103875780630af00f1f1461038257806311b0b42d1461037d578063131dbd091461037857806322261578146103735780632a76bbee1461036e5780632cef7165146103695780632f48ab7d146103645780633782e7be1461035f5780633e4365631461035a578063404d1d8a1461035557806340f51dad1461035057806343fb2b611461034b5780634707aa2814610346578063495ee13e146103415780634ff2255b1461033c57806358979bfe146103375780635dae3014146103325780635dd64c471461032d5780635e35359e1461032857806366168bd7146103235780636a1b7ecc1461031e5780636db4cb7f146103195780636e899aa314610314578063715018a61461030f578063745392851461030a578063751327b2146103055780637c242a0f146103005780637f9d58ad146102fb57806387be6f5f146102f65780638cd869d0146102f15780638da5cb5b146102ec57806394cf795e146102e757806396804ba6146102e25780639e2e9312146102dd5780639eb154a8146102d8578063a009852c146102d3578063a0246a4d146102ce578063a42dce80146102c9578063b1957cd3146102c4578063b95058a0146102bf578063bc50b3ca146102ba578063bd6d39c1146102b5578063bfb02da8146102b0578063c0d78655146102ab578063c45a0155146102a6578063d152116b146102a1578063d599a1c61461029c578063d9f6f04914610297578063e2ab691d14610292578063eb0064be1461028d578063ee74043d14610288578063eff5390114610283578063f2fde38b1461027e5763f887ea400361000e57612ea2565b612e11565b612c94565b612c50565b612c33565b612941565b612919565b6128d2565b612798565b612770565b612729565b6126ee565b6126ae565b6125f4565b6125b7565b61257a565b6124fa565b6121fe565b6121b9565b612176565b612139565b612118565b612099565b612035565b611ff5565b611f4f565b611d4e565b6117eb565b6114fc565b611470565b611410565b6113d0565b6113a1565b611384565b6111b0565b610f1e565b610ece565b610e93565b610e43565b610e08565b610dc8565b610b56565b610b1b565b610acb565b6109e2565b610876565b61083b565b610813565b6107f6565b6106ac565b610546565b6104e3565b6104bb565b610449565b6103d8565b6001600160a01b0381160361039d57565b5f80fd5b600435906103ae8261038c565b565b604090600319011261039d576004356103c88161038c565b906024356103d58161038c565b90565b3461039d5760206104136103eb366103b0565b6001600160a01b039182165f90815260aa855260408082209290931681526020919091522090565b54604051908152f35b608090600319011261039d57600435906024359060443561043c8161038c565b906064356103d58161038c565b3461039d57602060ff6104a56104906104613661041c565b5f93845260b0885260408085209385529288528284206001600160a01b03909216845260209190915291209091565b9060018060a01b03165f5260205260405f2090565b54166040519015158152f35b5f91031261039d57565b3461039d575f36600319011261039d5760b2546040516001600160a01b039091168152602090f35b3461039d57602036600319011261039d576004356104ff612eca565b609754811461050d57609755005b60405162461bcd60e51b815260206004820152601160248201527014d0535157d1915157d41493d592511151607a1b6044820152606490fd5b3461039d57606036600319011261039d576105896024356105668161038c565b6004355f5260ac60205260405f209060018060a01b03165f5260205260405f2090565b6044355f52602052602060ff60405f2054166040519015158152f35b634e487b7160e01b5f52604160045260245ffd5b6040810190811067ffffffffffffffff8211176105d557604052565b6105a5565b67ffffffffffffffff81116105d557604052565b6060810190811067ffffffffffffffff8211176105d557604052565b90601f8019910116810190811067ffffffffffffffff8211176105d557604052565b67ffffffffffffffff81116105d55760051b60200190565b81601f8201121561039d5780359161065b8361062c565b92610669604051948561060a565b808452602092838086019260051b82010192831161039d578301905b828210610693575050505090565b83809183356106a18161038c565b815201910190610685565b3461039d5760208060031936011261039d5767ffffffffffffffff60043581811161039d576106df903690600401610644565b916106e8612eca565b60038351106107b25782519182116105d557600160401b82116105d557609b5482609b5580831061077f575b50609b5f52828101905f805160206150be833981519152905f5b8481106107645761073e86614dcb565b7f02ae5c14158ac00f040514a245154d1ffd6ed0b4dad8a0ce70130bd689d745255f80a2005b83516001600160a01b0316838201559281019260010161072e565b5f609b8152835f805160206150be83398151915292830192015b8281106107a7575050610714565b818155600101610799565b6064906040519062461bcd60e51b82526004820152601a60248201527f56414c494441544f52535f4152455f4c4553535f5448414e5f330000000000006044820152fd5b3461039d575f36600319011261039d576020609b54604051908152f35b3461039d575f36600319011261039d57609c546040516001600160a01b039091168152602090f35b3461039d57602061041361084e366103b0565b6001600160a01b039182165f90815260ab855260408082209290931681526020919091522090565b3461039d5760e036600319011261039d5760043567ffffffffffffffff811161039d576108a7903690600401610644565b61092b6044356108b68161038c565b6064356108c28161038c565b6084356108ce8161038c565b60a435916108db8361038c565b60c435936108e88561038c565b5f549661090c60ff8960081c16158099819a6109a5575b8115610985575b50612f6a565b8761091d600160ff195f5416175f55565b61096e575b60243590613135565b61093157005b61093f61ff00195f54165f55565b604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249890602090a1005b61098061010061ff00195f5416175f55565b610922565b303b15915081610997575b505f610906565b6001915060ff16145f610990565b600160ff82161091506108ff565b8015150361039d57565b604090600319011261039d576004356109d58161038c565b906024356103d5816109b3565b3461039d576109f0366109bd565b6109f8612eca565b6001600160a01b03821691610a0e831515614d88565b5f83815260a6602052604090205460ff16151582151503610a605760405162461bcd60e51b815260206004820152600b60248201526a1053149150511657d4d15560aa1b6044820152606490fd5b0390fd5b6001600160a01b03165f90815260a6602052604090207f6692a0f9d25aba8bdf9876d6e8dd1604bb556b6934531c78259502b8b2f5d7a291610ac691610ab49082905b9060ff801983541691151516179055565b60405190151581529081906020820190565b0390a2005b3461039d57602036600319011261039d57600435610ae88161038c565b610af0612eca565b6001600160a01b0316610b04811515614d88565b6001600160601b0360a01b609a541617609a555f80f35b3461039d57602036600319011261039d57600435610b388161038c565b60018060a01b03165f5260a1602052602060405f2054604051908152f35b3461039d57610b64366109bd565b5f908080610da8575b15610cca575050610b7c614250565b610b9882610b898361427c565b6001600160a01b039091169052565b609d54610bb5906001600160a01b03165b6001600160a01b031690565b6040516315ab88c960e31b81529190602083600481845afa8015610c9757610c4094610bf1610c23925f968791610c9c575b50610b8986614289565b609c54610c0a906001600160a01b0316610b8986614299565b6001600160a01b03165f90815260a16020526040902090565b5460405180958194829363d06ca61f60e01b845260048401614337565b03915afa908115610c9757610c7291610c60915f91610c76575b50614299565b515b6040519081529081906020820190565b0390f35b610c91913d8091833e610c89818361060a565b8101906142bd565b5f610c5a565b61406c565b610cbd915060203d8111610cc3575b610cb5818361060a565b810190614220565b5f610be7565b503d610cab565b1580610d88575b15610d7e57505f610d3f91610ce4614235565b90610cf281610b898461427c565b609c54610d0b906001600160a01b0316610b8984614289565b609d54610c2390610d24906001600160a01b0316610ba9565b6001600160a01b039092165f90815260a16020526040902090565b03915afa908115610c9757610c7291610d5f915f91610d65575b50614289565b51610c62565b610d78913d8091833e610c89818361060a565b5f610d59565b610c729150610c62565b506001600160a01b0382165f90815260a160205260409020541515610cd1565b506001600160a01b0383165f90815260a160205260409020541515610b6d565b3461039d57602036600319011261039d57600435610de58161038c565b60018060a01b03165f5260a0602052602060ff60405f2054166040519015158152f35b3461039d57602036600319011261039d57600435610e258161038c565b60018060a01b03165f5260a3602052602060405f2054604051908152f35b3461039d57602036600319011261039d57600435610e608161038c565b610e68612eca565b6001600160a01b0316610e7c811515614d88565b6001600160601b0360a01b609c541617609c555f80f35b3461039d57602036600319011261039d57600435610eb08161038c565b60018060a01b03165f5260a4602052602060405f2054604051908152f35b3461039d57602036600319011261039d57600435610eeb8161038c565b610ef3612eca565b6001600160a01b0316610f07811515614d88565b6001600160601b0360a01b60b254161760b2555f80f35b3461039d57606036600319011261039d57600435610f3b8161038c565b60243590610f488261038c565b604435906001600160a01b0380821691610f63831515614ea4565b610f6e84151561337a565b610fa5610f9e610ba9610f918460018060a01b03165f5260b160205260405f2090565b546001600160a01b031690565b3314614ee3565b60b254610fba906001600160a01b0316610ba9565b8314611160576040516370a0823160e01b8152306004820152602091908281602481885afa918215610c975761102361101b6110439461103c945f91611133575b506001600160a01b0384165f90815260a1602052604090205b5490613492565b881115614f2f565b6001600160a01b03165f90815260a06020526040902090565b5460ff1690565b6110ee5760405163a9059cbb60e01b81526001600160a01b038616600482015260248101859052928190849060449082905f905af1928315610c97577f8210728e7c071f615b840ee026032693858fbcd5e5359e67e438c890f59e5620936110c0575b50505b60405192835290921691339180602081015b0390a3005b816110df92903d106110e7575b6110d7818361060a565b8101906140c2565b505f806110a6565b503d6110cd565b60405162461bcd60e51b815260206004820152601c60248201527f43414e545f57495448445241575f575241505045445f544f4b454e53000000006044820152606490fd5b6111539150873d8911611159575b61114b818361060a565b81019061405d565b5f610ffb565b503d611141565b507f8210728e7c071f615b840ee026032693858fbcd5e5359e67e438c890f59e5620915061119047841115614f2f565b6111ab5f80808087868a165af16111a5614153565b50614f6b565b6110a9565b604036600319011261039d576004356111c88161038c565b6024356111d681151561337a565b60b2546111eb906001600160a01b0316610ba9565b6001600160a01b0383169290831480611374575b611229611222610ba9610f918560018060a01b03165f5260b160205260405f2090565b3314614e0d565b61136b57611239903b1515614e59565b6040516370a0823160e01b808252306004830152602093908483602481855afa928315610c975785905f94611348575b506040516323b872dd60e01b81523360048201523060248201526044810195909552929391928280606481015b03815f875af1918215610c9757859261132b575b5060405190815230600482015291829060249082905afa908115610c97576112da935f9261130e575b5050613492565b60405190815233907fbc7c8a4d8049a3f99a02f2a20640c206a2e4d3f2fa54fd20da9f01fda3620cda908060208101610ac6565b6113249250803d106111595761114b818361060a565b5f806112d3565b61134190833d85116110e7576110d7818361060a565b505f6112aa565b61129693945061136490823d84116111595761114b818361060a565b9392611269565b505050346112da565b61137f34151561337a565b6111ff565b3461039d575f36600319011261039d576020609754604051908152f35b3461039d57602036600319011261039d576004355f5260a2602052602060ff60405f2054166040519015158152f35b3461039d57602036600319011261039d576004356113ed8161038c565b60018060a01b03165f52609f602052602060ff60405f2054166040519015158152f35b3461039d575f8060031936011261146d57611429612eca565b603380546001600160a01b0319811690915581906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b80fd5b3461039d575f36600319011261039d576099546040516001600160a01b039091168152602090f35b604090600319011261039d57604051906114b1826105b9565b816004356114be8161038c565b81526020602435910152565b604090604319011261039d57604051906114e3826105b9565b816044356114f08161038c565b81526020606435910152565b3461039d57608036600319011261039d5761151636611498565b61151f366114ca565b611527612eca565b815181516001600160a01b039182169290821691839060209061154b831515614ac6565b841695611559871515614ac6565b0190815146145f1461176e5761160e611726916104905f8051602061507e8339815191529661159f61159a61103c60208a01515f5260a260205260405f2090565b614b01565b6115d2610ba9610f918561049060206115c18c515f5260af60205260405f2090565b9c019b8c515f5260205260405f2090565b151580611741575b6115e390614b08565b61161e61160e846104906116008a515f5260af60205260405f2090565b8b515f5260205260405f2090565b80546001600160a01b0319169055565b61163b61160e826104906116008a515f5260af60205260405f2090565b61166661160e846104906116588b515f5260af60205260405f2090565b8a515f5260205260405f2090565b61168361160e826104906116588b515f5260af60205260405f2090565b6116b261160e82610490866104906116a48c515f5260ae60205260405f2090565b8d515f5260205260405f2090565b6116d361160e84610490846104906116a48c515f5260ae60205260405f2090565b61170261160e82610490866104906116f48d515f5260ae60205260405f2090565b8c515f5260205260405f2090565b61049061171888515f5260ae60205260405f2090565b87515f5260205260405f2090565b519051604080519283526020830191909152819081016110bb565b506115e3611765610ba9610f91846104906116a48c515f5260af60205260405f2090565b151590506115da565b602083015146036117b05761160e611726916104905f8051602061507e833981519152966117ab61159a61103c88515f5260a260205260405f2090565b61159f565b60405162461bcd60e51b815260206004820152601360248201527210d210525397d393d517d4d5541413d4951151606a1b6044820152606490fd5b60a036600319011261039d5761180036611498565b611809366114ca565b6118146084356109b3565b81516001600160a01b031681519091906001600160a01b0316926001600160a01b03916118448484161515614ac6565b6118518386161515614ac6565b60208201514603611cfe576020807f2c77a82144bdfced090e1946cf209e1730d693834f2cc87a805d041417b34b479361189c61159a61103c848701515f5260a260205260405f2090565b6118ce610ba9610f91896104906118be878701515f5260af60205260405f2090565b878a01515f5260205260405f2090565b1580611cc0575b6118de90614b08565b6119156118f6838301515f5260b060205260405f2090565b610aa38a6104908b61049060843595898c01515f5260205260405f2090565b61194c61192d838301515f5260b060205260405f2090565b610aa3896104908c61049060843595898c01515f5260205260405f2090565b611983611964838601515f5260b060205260405f2090565b610aa38a6104908b61049060843595898901515f5260205260405f2090565b6119ba61199b838601515f5260b060205260405f2090565b610aa3896104908c61049060843595898901515f5260205260405f2090565b6119f9886119da896104906118be878701515f5260af60205260405f2090565b80546001600160a01b0319166001600160a01b03909216919091179055565b611a19876119da8a6104906118be878701515f5260af60205260405f2090565b611a49886119da89610490611a39878a01515f5260af60205260405f2090565b878701515f5260205260405f2090565b611a69876119da8a610490611a39878a01515f5260af60205260405f2090565b608435611c30575b611aa6611a89838301515f5260ae60205260405f2090565b6119da8a6104908b6104903395898c01515f5260205260405f2090565b611adb611abe838301515f5260ae60205260405f2090565b6119da896104908c6104903395898c01515f5260205260405f2090565b611b10611af3838601515f5260ae60205260405f2090565b6119da8a6104908b6104903395898901515f5260205260405f2090565b611b45611b28838601515f5260ae60205260405f2090565b6119da896104908c6104903395898901515f5260205260405f2090565b86861688871603611be0576001600160a01b0387165f90815260b160205260409020611b729033906119da565b335f90815260a660205260409020611b9190611b8d9061103c565b1590565b611bc2575b0151910151604080519283526020830191909152608435151590820152339483169390921691606090a4005b609a54611bdb906001600160a01b031634903390614bd1565b611b96565b863b15611c0e576001600160a01b0387165f90815260b160205260409020611c099033906119da565b611b72565b6001600160a01b0388165f90815260b160205260409020611c099033906119da565b611c6c611c5f89610490611c4f868601515f5260ad60205260405f2090565b868901515f5260205260405f2090565b805460ff19166001179055565b611c9b611c5f89610490611c8b868901515f5260ad60205260405f2090565b868601515f5260205260405f2090565b6001600160a01b0388165f90815260a060205260409020611cbb90611c5f565b611a71565b506118de611cf6610ba9610f918b610490611ce6888801515f5260af60205260405f2090565b888b01515f5260205260405f2090565b1590506118d5565b602081015146036117b05760208083611d4961159a61103c847f2c77a82144bdfced090e1946cf209e1730d693834f2cc87a805d041417b34b479801515f5260a260205260405f2090565b61189c565b3461039d57608036600319011261039d57611e87600435611d6e8161038c565b6119da60243591611d7e8361038c565b61049060643581604435611d94853b1515614e59565b6001600160a01b0392611dce90611dae8986161515614fec565b611e13611ddb610f918961049085611dce895f5260af60205260405f2090565b905f5260205260405f2090565b95611de98188161515614ea4565b3390611e0c610f91896104908d61049089611dce8d5f5260ae60205260405f2090565b1614615031565b611e35896119da876104908b61049087611dce8b5f5260ae60205260405f2090565b611e57896119da896104908961049087611dce8b5f5260ae60205260405f2090565b611e79896119da876104908b61049089611dce895f5260ae60205260405f2090565b5f5260ae60205260405f2090565b005b81601f8201121561039d57803591611ea08361062c565b92611eae604051948561060a565b808452602092838086019260051b82010192831161039d578301905b828210611ed8575050505090565b81358152908301908301611eca565b81601f8201121561039d57803591611efe8361062c565b92611f0c604051948561060a565b808452602092838086019260051b82010192831161039d578301905b828210611f36575050505090565b813560ff8116810361039d578152908301908301611f28565b61012036600319011261039d57611f646103a1565b67ffffffffffffffff9060c43582811161039d57611f86903690600401611e89565b60e43583811161039d57611f9e903690600401611e89565b906101043593841161039d57611fbb611e87943690600401611ee7565b9260a435906084359060643590604435906024359061353d565b606090600319011261039d5760043590602435906044356103d58161038c565b3461039d57602060ff6104a561200a36611fd5565b5f92835260ad865260408084209284529186528183206001600160a01b039091168352602052902090565b3461039d575f36600319011261039d576033546040516001600160a01b039091168152602090f35b9081518082526020808093019301915f5b82811061207c575050505090565b83516001600160a01b03168552938101939281019260010161206e565b3461039d575f36600319011261039d5760405180609b54808252826020809301609b5f525f805160206150be833981519152925f5b858282106120f9575050506120e59250038361060a565b610c7260405192828493845283019061205d565b85546001600160a01b03168452600195860195889550930192016120ce565b3461039d57602036600319011261039d57612131612eca565b600435609e55005b3461039d57602036600319011261039d5760206004356121588161038c565b60018060a01b038091165f5260b1825260405f205416604051908152f35b3461039d57602061218636611fd5565b5f92835260af845260408084209284529184528183206001600160a01b03918216845260205291205b5416604051908152f35b3461039d5760206121af6121cc3661041c565b5f93845260ae865260408085209385529286528284206001600160a01b03928316855260205291909220919291610490565b3461039d57606036600319011261039d5760043561221b8161038c565b602435612227816109b3565b60443590612234826109b3565b61223c612eca565b60b25461226690612255906001600160a01b0316610ba9565b6001600160a01b0385161415614fa9565b80806124da575b156123e657509061227c614250565b9061228a81610b898461427c565b609d5461229f906001600160a01b0316610ba9565b91604051936315ab88c960e31b948581526020928382600481895afa908115610c97576122dc5f926123289484916123c9575b50610b8983614289565b609c546122f5906001600160a01b0316610b8983614299565b6001600160a01b0386165f90815260a1602052604090205460405163d06ca61f60e01b8152938492839260048401614337565b0381885afa8015610c9757612343915f91610c765750614299565b51609e5411908115916123c1575b5061235857005b6001600160a01b0382165f90815260a1602052604090208190549460046040518096819382525afa8015610c97575f9461239f94610c0a9387936123a2575b505083614387565b55005b6123b9929350803d10610cc357610cb5818361060a565b905f80612397565b90505f612351565b6123e09150873d8911610cc357610cb5818361060a565b5f6122d2565b15806124ba575b6123f357005b6123fb614235565b9061240983610b898461427c565b609c5461245a905f906001600160a01b03169361242985610b8983614289565b609d5461243e906001600160a01b0316610ba9565b6001600160a01b0387165f90815260a160205260409020610c23565b03915afa8015610c9757612474915f91610d655750614289565b51609e5411908115916124b2575b5015611e875781610c0a61239f926124ab5f9560018060a01b03165f5260a160205260405f2090565b5483614387565b90505f612482565b506001600160a01b0382165f90815260a1602052604090205415156123ed565b506001600160a01b0383165f90815260a16020526040902054151561226d565b3461039d57602036600319011261039d576004356125178161038c565b61251f612eca565b6001600160a01b03168015612545576001600160601b0360a01b60995416176099555f80f35b60405162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22fa7aba722a960991b6044820152606490fd5b3461039d57602060ff6104a561258f366103b0565b6001600160a01b039182165f90815260a7865260408082209290931681526020919091522090565b3461039d57602036600319011261039d5760206004356125d68161038c565b60018060a01b038091165f5260a5825260405f205416604051908152f35b3461039d57604036600319011261039d57600435602435612614816109b3565b61261c612eca565b811561267657816040917fe78910fc1a08062969a9edf6b274d453a04a1734507fabbd5bb445d5cb8eaeae935f5260a260205261266781845f209060ff801983541691151516179055565b825191825215156020820152a1005b60405162461bcd60e51b815260206004820152601060248201526f1253959053125117d0d210525397d25160821b6044820152606490fd5b3461039d57602036600319011261039d576004356126cb8161038c565b60018060a01b03165f5260a6602052602060ff60405f2054166040519015158152f35b3461039d5760206121af612701366103b0565b6001600160a01b039182165f90815260a9855260408082209284168252602092909252209091565b3461039d57602036600319011261039d576004356127468161038c565b61274e612eca565b609d80546001600160a01b0319166001600160a01b0392909216919091179055005b3461039d575f36600319011261039d576098546040516001600160a01b039091168152602090f35b3461039d57604036600319011261039d576004356127b58161038c565b6024356127c0612eca565b6001600160a01b0382169182156128625761271082101561282a576001600160a01b03165f90815260a3602052604090207fe4427eddc01962bfd3d30c0f180ab69439b489e5cd0c9c607aed338f3edc350691610ac6918190556040519081529081906020820190565b60405162461bcd60e51b815260206004820152601060248201526f4645455f43414e545f42455f3130302560801b6044820152606490fd5b60405162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22faa27a5a2a760991b6044820152606490fd5b634e487b7160e01b5f52603260045260245ffd5b609b548110156128cd57609b5f525f805160206150be83398151915201905f90565b612897565b3461039d57602036600319011261039d57600435609b5481101561039d57609b5f525f805160206150be83398151915201546040516001600160a01b039091168152602090f35b3461039d575f36600319011261039d57609a546040516001600160a01b039091168152602090f35b606036600319011261039d576004356129598161038c565b602435604435916129686134e7565b61297382151561337a565b6001600160a01b03818116929061298b8415156133bc565b6129a86129a361103c875f5260a260205260405f2090565b613408565b6129c5610f918461049088611dce465f5260af60205260405f2090565b16936129d2851515613444565b5f6129f061103c8561049085611dce465f5260ad60205260405f2090565b15612bf457506001915b6001600160a01b0384165f90815260a36020526040812054919084612aa357505f805160206150de833981519152939291612a3a91612a95963390614671565b949091612a5333610490835f5260a860205260405f2090565b92835493612a6085613484565b905560405194859433984693879260a094919796959260c0850198855260208501526040840152606083015260808201520152565b0390a45b611e876001606555565b92949260018503612b035750612ae594612ad25f805160206150de833981519152959493612afb933386614671565b969093612adf88866134da565b9061464e565b612a5333610490835f5260a860205260405f2090565b0390a4612a99565b93929160028414612b1c575b5050505050505050612a99565b60b254612b31906001600160a01b0316610ba9565b8703612bcc57506001600160a01b039091165f90815260a36020526040902081905480612b89575b505f805160206150de8339815191529394612ae5612b7892341461349f565b0390a45b5f80808080808080612b0f565b5f805160206150de8339815191529450819250612bac612bb391612b7893613079565b6064900490565b94612ae5612bc18785613492565b939250509493612b59565b5f805160206150de8339815191529450612a3a91612bec96933390614671565b0390a4612b7c565b60b254612c09906001600160a01b0316610ba9565b808614908115612c29575b5015612c2357506002916129fa565b916129fa565b905086145f612c14565b3461039d575f36600319011261039d576020609e54604051908152f35b3461039d57604036600319011261039d576020610413602435612c728161038c565b6004355f5260a8835260405f209060018060a01b03165f5260205260405f2090565b3461039d57608036600319011261039d57612cae36611498565b612cb7366114ca565b81516001600160a01b031681519091906020906001600160a01b0316930190815146145f14612dd9575f8051602061507e83398151915291612d0b61159a61103c60208501515f5260a260205260405f2090565b61172661160e612d45610f9188610490896104906020612d348a515f5260ae60205260405f2090565b9a01998a515f5260205260405f2090565b6001600160a01b039690612d5c9088163314614b54565b86612d7a610f918361049061165889515f5260af60205260405f2090565b16151580612dac575b612d8c90614b92565b61049087821697612d9e891515614ac6565b8916986115e38a1515614ac6565b50612d8c612dd0610ba9610f918b6104906116008a515f5260af60205260405f2090565b15159050612d83565b602081015146036117b05781612e0c61159a61103c5f8051602061507e83398151915295515f5260a260205260405f2090565b612d0b565b3461039d57602036600319011261039d57600435612e2e8161038c565b612e36612eca565b6001600160a01b03811615612e4e57611e8790612f22565b60405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608490fd5b3461039d575f36600319011261039d57609d546040516001600160a01b039091168152602090f35b6033546001600160a01b03163303612ede57565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b603380546001600160a01b039283166001600160a01b0319821681179092559091167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a3565b15612f7157565b60405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608490fd5b15612fd457565b60405162461bcd60e51b815260206004820152601860248201527f4c495354494e475f4645455f43414e545f42455f5a45524f00000000000000006044820152606490fd5b1561302057565b60405162461bcd60e51b815260206004820152601960248201527f43414e545f50524f564944455f5a45524f5f41444452455353000000000000006044820152606490fd5b634e487b7160e01b5f52601160045260245ffd5b8181029291811591840414171561308c57565b613065565b80519067ffffffffffffffff82116105d557600160401b82116105d557609b5482609b55808310613102575b50609b5f526020908101905f805160206150be833981519152905f5b8481106130e7575050505050565b83516001600160a01b031683820155928101926001016130d9565b5f609b8152835f805160206150be83398151915292830192015b82811061312a5750506130bd565b81815560010161311c565b9091959492936003825110613249576131d9613214956131bc6132319961319f876131646131f7991515612fcd565b6001600160a01b039761319a90848a1615158061323e575b61318590613019565b61318d6132ee565b613195613310565b613091565b609755565b60018060a01b03166001600160601b0360a01b6099541617609955565b60018060a01b03166001600160601b0360a01b609a541617609a55565b1660018060a01b03166001600160601b0360a01b609d541617609d55565b60018060a01b03166001600160601b0360a01b6098541617609855565b60018060a01b03166001600160601b0360a01b609c541617609c55565b6103ae6305f5e100609e55565b50868a16151561317c565b60405162461bcd60e51b815260206004820152601b60248201527f4d494e494d554d5f5349474e4552535f53484f554c445f42455f3300000000006044820152606490fd5b1561329557565b60405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608490fd5b61330760ff5f5460081c166133028161328e565b61328e565b6103ae33612f22565b61332460ff5f5460081c166133028161328e565b6001606555565b60405162461bcd60e51b815260206004820152602160248201527f4449524543545f4554485f5452414e534645525f4e4f545f535550504f5254456044820152601160fa1b6064820152608490fd5b1561338157565b60405162461bcd60e51b8152602060048201526013602482015272414d4f554e545f43414e545f42455f5a45524f60681b6044820152606490fd5b156133c357565b60405162461bcd60e51b815260206004820152601a60248201527f544f4b454e5f414444524553535f43414e545f42455f4e554c4c0000000000006044820152606490fd5b1561340f57565b60405162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22fa1a420a4a760991b6044820152606490fd5b1561344b57565b60405162461bcd60e51b81526020600482015260116024820152702aa729aaa82827a92a22a22faa27a5a2a760791b6044820152606490fd5b5f19811461308c5760010190565b9190820391821161308c57565b156134a657565b60405162461bcd60e51b815260206004820152600c60248201526b4c4553535f4c4f434b494e4760a01b6044820152606490fd5b9190820180921161308c57565b6002606554146134f8576002606555565b60405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606490fd5b9382979394989291969861354f6134e7565b6001600160a01b039361356582861615156133bc565b613570331515613f86565b61357b89151561337a565b863361358f8a5f5260ac60205260405f2090565b6001600160a01b039091165f908152602091909152604090205f918252602052604090205460ff16156135c190613fc5565b6135d3885f5260a260205260405f2090565b5460ff166135e090613408565b81466135f48a5f5260af60205260405f2090565b5f918252602052604090206001600160a01b039091165f90815260209190915260409020546001600160a01b0316958587169b8c151561363390613444565b8a8a868a874661364b855f5260b060205260405f2090565b5f918252602090815260408083206001600160a01b03948516845282528083209490931682529290925290205460ff169861368e974694908e908e9033306148b4565b61369790614011565b811580613f68575b613ee5575b6136c1611c5f86611dce336104908b5f5260ac60205260405f2090565b80613c67575015613bca5785613bac575b6136dd853384614602565b60b2546136f2906001600160a01b0316610ba9565b871415908180613a90575b80613a70575b15613866575050613712614250565b9061372081610b898461427c565b609d54613735906001600160a01b0316610ba9565b604051906315ab88c960e31b918281526020948582600481865afa908115610c97576122dc5f9261377094849161384f5750610b8983614289565b0381855afa8015610c975761378b915f91610c765750614299565b51609e5411156137e9575b505050506137dc5f8051602061509e833981519152935b60405193849333974693869192608093969594919660a084019784526020840152604083015260608201520152565b0390a36103ae6001606555565b6001600160a01b0383165f90815260a160205260409020939692938790549260046040518094819382525afa938415610c9757610c0a6137dc955f94613846945f8051602061509e8339815191529b87936123a257505083614387565b55935f80613796565b6123e09150893d8b11610cc357610cb5818361060a565b8161399b575b508061397b575b613890575b506137dc5f8051602061509e833981519152936137ad565b61390f9361389c614235565b916138aa81610b898561427c565b609c545f906001600160a01b0316936138c685610b8983614289565b609d546138db906001600160a01b0316610ba9565b6001600160a01b0384165f90815260a16020526040902054604051809a8194829363d06ca61f60e01b845260048401614337565b03915afa928315610c975761393c6137dc945f8051602061509e833981519152985f91610d655750614289565b51609e541115613950575b50509350613878565b81610c0a613973926124ab5f9560018060a01b03165f5260a160205260405f2090565b555f80613947565b506001600160a01b0381165f90815260a160205260409020541515613873565b609d549091506139b3906001600160a01b0316610ba9565b604051809163c45a015560e01b825281600460209485935afa8015610c9757613a18839185935f91613a53575b50609c5460405163e6a4390560e01b81526001600160a01b038981166004830152909116602482015293849283919082906044820190565b0392165afa918215610c97575f92613a36575b50501615155f61386c565b613a4c9250803d10610cc357610cb5818361060a565b5f80613a2b565b613a6a9150833d8511610cc357610cb5818361060a565b5f6139e0565b506001600160a01b0383165f90815260a160205260409020541515613703565b50609d54613aa6906001600160a01b0316610ba9565b60405163c45a015560e01b8152602091908281600481855afa908115610c975783905f92613b8c575b506040516315ab88c960e31b81529192829060049082905afa908115610c975784928492613b33925f91613b6f575b5060405163e6a4390560e01b81526001600160a01b03808b166004830152909116602482015293849283919082906044820190565b0392165afa908115610c975783925f92613b52575b50501615156136fd565b613b689250803d10610cc357610cb5818361060a565b5f80613b48565b613b869150843d8611610cc357610cb5818361060a565b5f613afe565b60049250613ba690823d8411610cc357610cb5818361060a565b91613acf565b609954613bc59087906001600160a01b03165b84614602565b6136d2565b85613c3e575b60405163a9059cbb60e01b8152336004820152602481018690526020816044815f8c5af1908115610c97575f91613c20575b506136dd5760405162461bcd60e51b815280610a5c600482016140d7565b613c38915060203d81116110e7576110d7818361060a565b5f613c02565b6001600160a01b0382165f90815260a160205260409020613c608782546134da565b9055613bd0565b60018103613d9657505060b254613c86906001600160a01b0316610ba9565b8703613cf957613ca147613c9a88886134da565b1115614107565b85613cc5575b613cc05f80808089335af1613cba614153565b506141d4565b6136dd565b613cf45f8080808a613ce4610ba9610ba960995460018060a01b031690565b5af1613cee614153565b50614192565b613ca7565b85613d6d575b60405163a9059cbb60e01b8152336004820152602481018690526020816044815f8c5af1908115610c97575f91613d4f575b50613cc05760405162461bcd60e51b815280610a5c600482016140d7565b613d67915060203d81116110e7576110d7818361060a565b5f613d31565b6001600160a01b0382165f90815260a160205260409020613d8f8782546134da565b9055613cff565b600214613da4575b506136dd565b60b254613db9906001600160a01b0316610ba9565b8803613e115750613dce47613c9a88886134da565b85613ded575b613de75f80808089335af1613cba614153565b5f613d9e565b613e0c5f8080808a613ce4610ba9610ba960995460018060a01b031690565b613dd4565b15613e485785613e2c575b613e27853384614602565b613de7565b609954613e439087906001600160a01b0316613bbf565b613e1c565b85613ebc575b60405163a9059cbb60e01b8152336004820152602481018690526020816044815f8c5af1908115610c97575f91613e9e575b50613de75760405162461bcd60e51b815280610a5c600482016140d7565b613eb6915060203d81116110e7576110d7818361060a565b5f613e80565b6001600160a01b0382165f90815260a160205260409020613ede8782546134da565b9055613e4e565b6040516370a0823160e01b81523060048201526020816024818d5afa908115610c9757613f4591613f34915f91613f4a575b506001600160a01b0387165f90815260a160205260409020611014565b613f3e8a8a6134da565b1115614077565b6136a4565b613f62915060203d81116111595761114b818361060a565b5f613f17565b5060b254613f7e906001600160a01b0316610ba9565b89141561369f565b15613f8d57565b60405162461bcd60e51b815260206004820152601060248201526f24a72b20a624a22fa922a1a2a4ab22a960811b6044820152606490fd5b15613fcc57565b60405162461bcd60e51b815260206004820152601760248201527f4e4f4e43455f414c52454144595f50524f4345535345440000000000000000006044820152606490fd5b1561401857565b60405162461bcd60e51b815260206004820152601860248201527f494e56414c49445f5245434f56455245445f5349474e455200000000000000006044820152606490fd5b9081602091031261039d575190565b6040513d5f823e3d90fd5b1561407e57565b606460405162461bcd60e51b815260206004820152602060248201527f494e53554646494349454e545f4c49515549444954595f494e5f4252494447456044820152fd5b9081602091031261039d57516103d5816109b3565b6060906020815260156020820152741513d2d15397d514905394d1915497d19052531151605a1b60408201520190565b1561410e57565b60405162461bcd60e51b815260206004820152601a60248201527f494e53554646494349454e545f46554e445f494e5f42524944450000000000006044820152606490fd5b3d1561418d573d9067ffffffffffffffff82116105d55760405191614182601f8201601f19166020018461060a565b82523d5f602084013e565b606090565b1561419957565b60405162461bcd60e51b815260206004820152601360248201527211915157d514905394d1915497d19052531151606a1b6044820152606490fd5b156141db57565b60405162461bcd60e51b815260206004820152601b60248201527f4e41544956455f434f494e5f5452414e534645525f4641494c454400000000006044820152606490fd5b9081602091031261039d57516103d58161038c565b60405190614242826105ee565b600282526040366020840137565b604051906080820182811067ffffffffffffffff8211176105d557604052600382526060366020840137565b8051156128cd5760200190565b8051600110156128cd5760400190565b8051600210156128cd5760600190565b80518210156128cd5760209160051b010190565b602090818184031261039d5780519067ffffffffffffffff821161039d57019180601f8401121561039d5782516142f38161062c565b93614301604051958661060a565b818552838086019260051b82010192831161039d578301905b828210614328575050505090565b8151815290830190830161431a565b6040906103d593928152816020820152019061205d565b90608092614373919695949683525f602084015260a0604084015260a083019061205d565b6001600160a01b0390951660608201520152565b90916143a7836143a1610ba9609d5460018060a01b031690565b8461453b565b609d546143bc906001600160a01b0316610ba9565b6040516315ab88c960e31b8082526020918281600481875afa908115610c97575f9161451e575b506001600160a01b038581169116036144925750505061441b90614412614408614235565b93610b898561427c565b610b8983614289565b609d54614430906001600160a01b0316610ba9565b6099549092906001600160a01b03165b92803b1561039d5761446e935f80946040519687958694859363791ac94760e01b855242926004860161434e565b03925af18015610c975761447f5750565b8061448c6103ae926105da565b806104b1565b90919492506144ac6144a2614250565b94610b898661427c565b609c546144c5906001600160a01b0316610b8986614289565b6040519081528181600481885afa908115610c97576144f0925f92614501575b5050610b8984614299565b6099546001600160a01b0316614440565b6145179250803d10610cc357610cb5818361060a565b5f806144e5565b6145359150833d8511610cc357610cb5818361060a565b5f6143e3565b60405163095ea7b360e01b602082019081526001600160a01b03909316602482015260448101939093525f92839290839061458381606481015b03601f19810183528261060a565b51925af161458f614153565b816145d3575b501561459d57565b60405162461bcd60e51b815260206004820152600e60248201526d1054141493d59157d1905253115160921b6044820152606490fd5b80518015925082156145e8575b50505f614595565b6145fb92506020809183010191016140c2565b5f806145e0565b6040516340c10f1960e01b60208201526001600160a01b039290921660248301526044808301939093529181529061463b60648361060a565b8151614645575050565b6103ae91614aa8565b60405191630852cd8d60e31b602084015260248301526024825261463b826105ee565b6040516370a0823160e01b80825230600483015294955f959094602094936001600160a01b031692908582602481875afa948515610c975786925f966147c1575b506040516323b872dd60e01b81526001600160a01b0390911660048201523060248201526044810191909152908180606481015b03815f875af1908115610c97575f916147a4575b501561475f57604051908152306004820152908390829060249082905afa908115610c9757614730935f9261130e575050613492565b92806147395750565b83925061474d6147559161475c9395613079565b612710900490565b8092613492565b91565b60405162461bcd60e51b815260206004820152601d60248201527f5452414e534645525f4641494c45445f5748494c455f4c4f434b494e470000006044820152606490fd5b6147bb9150853d87116110e7576110d7818361060a565b5f6146fa565b83929196506147df906146e6943d85116111595761114b818361060a565b959091926146b2565b156147ef57565b60405162461bcd60e51b815260206004820152601960248201527f494e56414c49445f4e554d4245525f4f465f5349474e455253000000000000006044820152606490fd5b1561483b57565b60405162461bcd60e51b8152602060048201526011602482015270494e56414c49445f5349474e415455524560781b6044820152606490fd5b1561487b57565b60405162461bcd60e51b815260206004820152601160248201527024a72b20a624a22fab20a624a220aa27a960791b6044820152606490fd5b97938b9d9c999591969297938b9c609b54809e819051149182614a58575b505080614a4e575b6148e3906147e8565b5f5b8d8110614900575060019e5050505050505050505050505050565b8f5f8e8e6149ed8f948f8f8f8f8f8f8f8f8f9d8f979860209f6149c59a6145756149be9a8c9a6149b89a6149b19a8d9a6149ab9a6149a3986040519a6020998c9a8b019d8e98969492906101109a989694916001600160601b0319809481809460601b168d5260601b1660148c015260601b1660288a015260601b16603c88015260508701526070860152609085015260b084015260d083015260f08201520190565b519020614a65565b996142a9565b5160ff1690565b976142a9565b51926142a9565b5190604051948594859094939260ff6060936080840197845216602083015260408201520152565b838052039060015afa15610c97575f51614a499190614a44906001600160a01b0316614a1a811515614834565b614a3e610ba9614a29856128ab565b905460039190911b1c6001600160a01b031690565b14614874565b613484565b6148e5565b508a518d146148da565b90915051148f8e906148d2565b60405160208101917f19457468657265756d205369676e6564204d6573736167653a0a3332000000008352603c820152603c8152614aa2816105ee565b51902090565b80515f9283926020019083906001600160a01b03165af11561039d57565b15614acd57565b60405162461bcd60e51b815260206004820152600c60248201526b24a72b20a624a22fa0a2222960a11b6044820152606490fd5b156117b057565b15614b0f57565b60405162461bcd60e51b815260206004820152601860248201527f544849535f504149525f414c52454144595f4c495354454400000000000000006044820152606490fd5b15614b5b57565b60405162461bcd60e51b815260206004820152600f60248201526e2727aa2faa27a5a2a72fa7aba722a960891b6044820152606490fd5b15614b9957565b60405162461bcd60e51b815260206004820152601060248201526f1053149150511657d111531254d5115160821b6044820152606490fd5b919091614bdc6134e7565b6001600160a01b03908116918215614c5d57614c2590614c1c60975494614c0586841015614ca2565b5f8080809881945af1614c16614153565b50614ce5565b60975490613492565b9081614c3a575b505050506103ae6001606555565b8280928192614c5496165af1614c4e614153565b50614d31565b5f808080614c2c565b60405162461bcd60e51b815260206004820152601960248201527f43414e545f53454e445f544f5f4e554c4c5f41444452455353000000000000006044820152606490fd5b15614ca957565b60405162461bcd60e51b8152602060048201526014602482015273494e4352454153455f4c495354494e475f46454560601b6044820152606490fd5b15614cec57565b60405162461bcd60e51b815260206004820152601b60248201527f4c495354494e475f4645455f5452414e534645525f4641494c454400000000006044820152606490fd5b15614d3857565b60405162461bcd60e51b815260206004820152602260248201527f524546554e445f52454d41494e494e475f45544845525f53454e545f4641494c604482015261115160f21b6064820152608490fd5b15614d8f57565b60405162461bcd60e51b815260206004820152601460248201527343414e545f42455f4e554c4c5f4144445245535360601b6044820152606490fd5b6040519081818392516020809201915f5b828110614ded575050505003902090565b83516001600160a01b031685528695509381019392810192600101614ddc565b15614e1457565b60405162461bcd60e51b815260206004820152601760248201527f4f4e4c595f4c49535445525f43414e5f4445504f5349540000000000000000006044820152606490fd5b15614e6057565b606460405162461bcd60e51b815260206004820152602060248201527f544f4b454e5f4e4f545f4445504c4f5945445f4f4e5f544849535f434841494e6044820152fd5b15614eab57565b60405162461bcd60e51b815260206004820152601060248201526f1513d2d15397d393d517d31254d5115160821b6044820152606490fd5b15614eea57565b60405162461bcd60e51b815260206004820152601e60248201527f4f4e4c595f544f4b454e5f4c49535445525f43414e5f574954484452415700006044820152606490fd5b15614f3657565b60405162461bcd60e51b815260206004820152600d60248201526c57495448445241575f4c45535360981b6044820152606490fd5b15614f7257565b60405162461bcd60e51b815260206004820152600f60248201526e15d2551211149055d7d19052531151608a1b6044820152606490fd5b15614fb057565b60405162461bcd60e51b815260206004820152601460248201527321a0a72a2fa122afa720aa24ab22afaa27a5a2a760611b6044820152606490fd5b15614ff357565b60405162461bcd60e51b8152602060048201526016602482015275139155d7d3d5d3915497d0d0539517d09157d395531360521b6044820152606490fd5b1561503857565b60405162461bcd60e51b815260206004820152601c60248201527f4f4e4c595f544f4b454e5f4c49535445525f43414e5f4348414e4745000000006044820152606490fdfefa35030c3c7d834268ab6e51b6af06e24b8f502f8fde9c54ed6ba28f36f0e3cbf3f7debab57cb669dc23552fd1d27d490d1a2a8a8750f60cf0d43a6f2ac04072bba9db4cdbea0a37c207bbb83e20f828cd4441c49891101dc94fd20dc8efc349a921fe040b86ab1aa7b07f5c8d9bc081d3082ffdcd001dd54bfb7ee1b186e66ba26469706673582212209af746975f4ecc454cd4a90a7bc94193c0982c72466659757eae0b5e8956759f64736f6c63430008140033
Deployed Bytecode
0x60806040526004361015610018575b3661332b5761332b565b5f3560e01c806305a71b73146103875780630af00f1f1461038257806311b0b42d1461037d578063131dbd091461037857806322261578146103735780632a76bbee1461036e5780632cef7165146103695780632f48ab7d146103645780633782e7be1461035f5780633e4365631461035a578063404d1d8a1461035557806340f51dad1461035057806343fb2b611461034b5780634707aa2814610346578063495ee13e146103415780634ff2255b1461033c57806358979bfe146103375780635dae3014146103325780635dd64c471461032d5780635e35359e1461032857806366168bd7146103235780636a1b7ecc1461031e5780636db4cb7f146103195780636e899aa314610314578063715018a61461030f578063745392851461030a578063751327b2146103055780637c242a0f146103005780637f9d58ad146102fb57806387be6f5f146102f65780638cd869d0146102f15780638da5cb5b146102ec57806394cf795e146102e757806396804ba6146102e25780639e2e9312146102dd5780639eb154a8146102d8578063a009852c146102d3578063a0246a4d146102ce578063a42dce80146102c9578063b1957cd3146102c4578063b95058a0146102bf578063bc50b3ca146102ba578063bd6d39c1146102b5578063bfb02da8146102b0578063c0d78655146102ab578063c45a0155146102a6578063d152116b146102a1578063d599a1c61461029c578063d9f6f04914610297578063e2ab691d14610292578063eb0064be1461028d578063ee74043d14610288578063eff5390114610283578063f2fde38b1461027e5763f887ea400361000e57612ea2565b612e11565b612c94565b612c50565b612c33565b612941565b612919565b6128d2565b612798565b612770565b612729565b6126ee565b6126ae565b6125f4565b6125b7565b61257a565b6124fa565b6121fe565b6121b9565b612176565b612139565b612118565b612099565b612035565b611ff5565b611f4f565b611d4e565b6117eb565b6114fc565b611470565b611410565b6113d0565b6113a1565b611384565b6111b0565b610f1e565b610ece565b610e93565b610e43565b610e08565b610dc8565b610b56565b610b1b565b610acb565b6109e2565b610876565b61083b565b610813565b6107f6565b6106ac565b610546565b6104e3565b6104bb565b610449565b6103d8565b6001600160a01b0381160361039d57565b5f80fd5b600435906103ae8261038c565b565b604090600319011261039d576004356103c88161038c565b906024356103d58161038c565b90565b3461039d5760206104136103eb366103b0565b6001600160a01b039182165f90815260aa855260408082209290931681526020919091522090565b54604051908152f35b608090600319011261039d57600435906024359060443561043c8161038c565b906064356103d58161038c565b3461039d57602060ff6104a56104906104613661041c565b5f93845260b0885260408085209385529288528284206001600160a01b03909216845260209190915291209091565b9060018060a01b03165f5260205260405f2090565b54166040519015158152f35b5f91031261039d57565b3461039d575f36600319011261039d5760b2546040516001600160a01b039091168152602090f35b3461039d57602036600319011261039d576004356104ff612eca565b609754811461050d57609755005b60405162461bcd60e51b815260206004820152601160248201527014d0535157d1915157d41493d592511151607a1b6044820152606490fd5b3461039d57606036600319011261039d576105896024356105668161038c565b6004355f5260ac60205260405f209060018060a01b03165f5260205260405f2090565b6044355f52602052602060ff60405f2054166040519015158152f35b634e487b7160e01b5f52604160045260245ffd5b6040810190811067ffffffffffffffff8211176105d557604052565b6105a5565b67ffffffffffffffff81116105d557604052565b6060810190811067ffffffffffffffff8211176105d557604052565b90601f8019910116810190811067ffffffffffffffff8211176105d557604052565b67ffffffffffffffff81116105d55760051b60200190565b81601f8201121561039d5780359161065b8361062c565b92610669604051948561060a565b808452602092838086019260051b82010192831161039d578301905b828210610693575050505090565b83809183356106a18161038c565b815201910190610685565b3461039d5760208060031936011261039d5767ffffffffffffffff60043581811161039d576106df903690600401610644565b916106e8612eca565b60038351106107b25782519182116105d557600160401b82116105d557609b5482609b5580831061077f575b50609b5f52828101905f805160206150be833981519152905f5b8481106107645761073e86614dcb565b7f02ae5c14158ac00f040514a245154d1ffd6ed0b4dad8a0ce70130bd689d745255f80a2005b83516001600160a01b0316838201559281019260010161072e565b5f609b8152835f805160206150be83398151915292830192015b8281106107a7575050610714565b818155600101610799565b6064906040519062461bcd60e51b82526004820152601a60248201527f56414c494441544f52535f4152455f4c4553535f5448414e5f330000000000006044820152fd5b3461039d575f36600319011261039d576020609b54604051908152f35b3461039d575f36600319011261039d57609c546040516001600160a01b039091168152602090f35b3461039d57602061041361084e366103b0565b6001600160a01b039182165f90815260ab855260408082209290931681526020919091522090565b3461039d5760e036600319011261039d5760043567ffffffffffffffff811161039d576108a7903690600401610644565b61092b6044356108b68161038c565b6064356108c28161038c565b6084356108ce8161038c565b60a435916108db8361038c565b60c435936108e88561038c565b5f549661090c60ff8960081c16158099819a6109a5575b8115610985575b50612f6a565b8761091d600160ff195f5416175f55565b61096e575b60243590613135565b61093157005b61093f61ff00195f54165f55565b604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249890602090a1005b61098061010061ff00195f5416175f55565b610922565b303b15915081610997575b505f610906565b6001915060ff16145f610990565b600160ff82161091506108ff565b8015150361039d57565b604090600319011261039d576004356109d58161038c565b906024356103d5816109b3565b3461039d576109f0366109bd565b6109f8612eca565b6001600160a01b03821691610a0e831515614d88565b5f83815260a6602052604090205460ff16151582151503610a605760405162461bcd60e51b815260206004820152600b60248201526a1053149150511657d4d15560aa1b6044820152606490fd5b0390fd5b6001600160a01b03165f90815260a6602052604090207f6692a0f9d25aba8bdf9876d6e8dd1604bb556b6934531c78259502b8b2f5d7a291610ac691610ab49082905b9060ff801983541691151516179055565b60405190151581529081906020820190565b0390a2005b3461039d57602036600319011261039d57600435610ae88161038c565b610af0612eca565b6001600160a01b0316610b04811515614d88565b6001600160601b0360a01b609a541617609a555f80f35b3461039d57602036600319011261039d57600435610b388161038c565b60018060a01b03165f5260a1602052602060405f2054604051908152f35b3461039d57610b64366109bd565b5f908080610da8575b15610cca575050610b7c614250565b610b9882610b898361427c565b6001600160a01b039091169052565b609d54610bb5906001600160a01b03165b6001600160a01b031690565b6040516315ab88c960e31b81529190602083600481845afa8015610c9757610c4094610bf1610c23925f968791610c9c575b50610b8986614289565b609c54610c0a906001600160a01b0316610b8986614299565b6001600160a01b03165f90815260a16020526040902090565b5460405180958194829363d06ca61f60e01b845260048401614337565b03915afa908115610c9757610c7291610c60915f91610c76575b50614299565b515b6040519081529081906020820190565b0390f35b610c91913d8091833e610c89818361060a565b8101906142bd565b5f610c5a565b61406c565b610cbd915060203d8111610cc3575b610cb5818361060a565b810190614220565b5f610be7565b503d610cab565b1580610d88575b15610d7e57505f610d3f91610ce4614235565b90610cf281610b898461427c565b609c54610d0b906001600160a01b0316610b8984614289565b609d54610c2390610d24906001600160a01b0316610ba9565b6001600160a01b039092165f90815260a16020526040902090565b03915afa908115610c9757610c7291610d5f915f91610d65575b50614289565b51610c62565b610d78913d8091833e610c89818361060a565b5f610d59565b610c729150610c62565b506001600160a01b0382165f90815260a160205260409020541515610cd1565b506001600160a01b0383165f90815260a160205260409020541515610b6d565b3461039d57602036600319011261039d57600435610de58161038c565b60018060a01b03165f5260a0602052602060ff60405f2054166040519015158152f35b3461039d57602036600319011261039d57600435610e258161038c565b60018060a01b03165f5260a3602052602060405f2054604051908152f35b3461039d57602036600319011261039d57600435610e608161038c565b610e68612eca565b6001600160a01b0316610e7c811515614d88565b6001600160601b0360a01b609c541617609c555f80f35b3461039d57602036600319011261039d57600435610eb08161038c565b60018060a01b03165f5260a4602052602060405f2054604051908152f35b3461039d57602036600319011261039d57600435610eeb8161038c565b610ef3612eca565b6001600160a01b0316610f07811515614d88565b6001600160601b0360a01b60b254161760b2555f80f35b3461039d57606036600319011261039d57600435610f3b8161038c565b60243590610f488261038c565b604435906001600160a01b0380821691610f63831515614ea4565b610f6e84151561337a565b610fa5610f9e610ba9610f918460018060a01b03165f5260b160205260405f2090565b546001600160a01b031690565b3314614ee3565b60b254610fba906001600160a01b0316610ba9565b8314611160576040516370a0823160e01b8152306004820152602091908281602481885afa918215610c975761102361101b6110439461103c945f91611133575b506001600160a01b0384165f90815260a1602052604090205b5490613492565b881115614f2f565b6001600160a01b03165f90815260a06020526040902090565b5460ff1690565b6110ee5760405163a9059cbb60e01b81526001600160a01b038616600482015260248101859052928190849060449082905f905af1928315610c97577f8210728e7c071f615b840ee026032693858fbcd5e5359e67e438c890f59e5620936110c0575b50505b60405192835290921691339180602081015b0390a3005b816110df92903d106110e7575b6110d7818361060a565b8101906140c2565b505f806110a6565b503d6110cd565b60405162461bcd60e51b815260206004820152601c60248201527f43414e545f57495448445241575f575241505045445f544f4b454e53000000006044820152606490fd5b6111539150873d8911611159575b61114b818361060a565b81019061405d565b5f610ffb565b503d611141565b507f8210728e7c071f615b840ee026032693858fbcd5e5359e67e438c890f59e5620915061119047841115614f2f565b6111ab5f80808087868a165af16111a5614153565b50614f6b565b6110a9565b604036600319011261039d576004356111c88161038c565b6024356111d681151561337a565b60b2546111eb906001600160a01b0316610ba9565b6001600160a01b0383169290831480611374575b611229611222610ba9610f918560018060a01b03165f5260b160205260405f2090565b3314614e0d565b61136b57611239903b1515614e59565b6040516370a0823160e01b808252306004830152602093908483602481855afa928315610c975785905f94611348575b506040516323b872dd60e01b81523360048201523060248201526044810195909552929391928280606481015b03815f875af1918215610c9757859261132b575b5060405190815230600482015291829060249082905afa908115610c97576112da935f9261130e575b5050613492565b60405190815233907fbc7c8a4d8049a3f99a02f2a20640c206a2e4d3f2fa54fd20da9f01fda3620cda908060208101610ac6565b6113249250803d106111595761114b818361060a565b5f806112d3565b61134190833d85116110e7576110d7818361060a565b505f6112aa565b61129693945061136490823d84116111595761114b818361060a565b9392611269565b505050346112da565b61137f34151561337a565b6111ff565b3461039d575f36600319011261039d576020609754604051908152f35b3461039d57602036600319011261039d576004355f5260a2602052602060ff60405f2054166040519015158152f35b3461039d57602036600319011261039d576004356113ed8161038c565b60018060a01b03165f52609f602052602060ff60405f2054166040519015158152f35b3461039d575f8060031936011261146d57611429612eca565b603380546001600160a01b0319811690915581906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b80fd5b3461039d575f36600319011261039d576099546040516001600160a01b039091168152602090f35b604090600319011261039d57604051906114b1826105b9565b816004356114be8161038c565b81526020602435910152565b604090604319011261039d57604051906114e3826105b9565b816044356114f08161038c565b81526020606435910152565b3461039d57608036600319011261039d5761151636611498565b61151f366114ca565b611527612eca565b815181516001600160a01b039182169290821691839060209061154b831515614ac6565b841695611559871515614ac6565b0190815146145f1461176e5761160e611726916104905f8051602061507e8339815191529661159f61159a61103c60208a01515f5260a260205260405f2090565b614b01565b6115d2610ba9610f918561049060206115c18c515f5260af60205260405f2090565b9c019b8c515f5260205260405f2090565b151580611741575b6115e390614b08565b61161e61160e846104906116008a515f5260af60205260405f2090565b8b515f5260205260405f2090565b80546001600160a01b0319169055565b61163b61160e826104906116008a515f5260af60205260405f2090565b61166661160e846104906116588b515f5260af60205260405f2090565b8a515f5260205260405f2090565b61168361160e826104906116588b515f5260af60205260405f2090565b6116b261160e82610490866104906116a48c515f5260ae60205260405f2090565b8d515f5260205260405f2090565b6116d361160e84610490846104906116a48c515f5260ae60205260405f2090565b61170261160e82610490866104906116f48d515f5260ae60205260405f2090565b8c515f5260205260405f2090565b61049061171888515f5260ae60205260405f2090565b87515f5260205260405f2090565b519051604080519283526020830191909152819081016110bb565b506115e3611765610ba9610f91846104906116a48c515f5260af60205260405f2090565b151590506115da565b602083015146036117b05761160e611726916104905f8051602061507e833981519152966117ab61159a61103c88515f5260a260205260405f2090565b61159f565b60405162461bcd60e51b815260206004820152601360248201527210d210525397d393d517d4d5541413d4951151606a1b6044820152606490fd5b60a036600319011261039d5761180036611498565b611809366114ca565b6118146084356109b3565b81516001600160a01b031681519091906001600160a01b0316926001600160a01b03916118448484161515614ac6565b6118518386161515614ac6565b60208201514603611cfe576020807f2c77a82144bdfced090e1946cf209e1730d693834f2cc87a805d041417b34b479361189c61159a61103c848701515f5260a260205260405f2090565b6118ce610ba9610f91896104906118be878701515f5260af60205260405f2090565b878a01515f5260205260405f2090565b1580611cc0575b6118de90614b08565b6119156118f6838301515f5260b060205260405f2090565b610aa38a6104908b61049060843595898c01515f5260205260405f2090565b61194c61192d838301515f5260b060205260405f2090565b610aa3896104908c61049060843595898c01515f5260205260405f2090565b611983611964838601515f5260b060205260405f2090565b610aa38a6104908b61049060843595898901515f5260205260405f2090565b6119ba61199b838601515f5260b060205260405f2090565b610aa3896104908c61049060843595898901515f5260205260405f2090565b6119f9886119da896104906118be878701515f5260af60205260405f2090565b80546001600160a01b0319166001600160a01b03909216919091179055565b611a19876119da8a6104906118be878701515f5260af60205260405f2090565b611a49886119da89610490611a39878a01515f5260af60205260405f2090565b878701515f5260205260405f2090565b611a69876119da8a610490611a39878a01515f5260af60205260405f2090565b608435611c30575b611aa6611a89838301515f5260ae60205260405f2090565b6119da8a6104908b6104903395898c01515f5260205260405f2090565b611adb611abe838301515f5260ae60205260405f2090565b6119da896104908c6104903395898c01515f5260205260405f2090565b611b10611af3838601515f5260ae60205260405f2090565b6119da8a6104908b6104903395898901515f5260205260405f2090565b611b45611b28838601515f5260ae60205260405f2090565b6119da896104908c6104903395898901515f5260205260405f2090565b86861688871603611be0576001600160a01b0387165f90815260b160205260409020611b729033906119da565b335f90815260a660205260409020611b9190611b8d9061103c565b1590565b611bc2575b0151910151604080519283526020830191909152608435151590820152339483169390921691606090a4005b609a54611bdb906001600160a01b031634903390614bd1565b611b96565b863b15611c0e576001600160a01b0387165f90815260b160205260409020611c099033906119da565b611b72565b6001600160a01b0388165f90815260b160205260409020611c099033906119da565b611c6c611c5f89610490611c4f868601515f5260ad60205260405f2090565b868901515f5260205260405f2090565b805460ff19166001179055565b611c9b611c5f89610490611c8b868901515f5260ad60205260405f2090565b868601515f5260205260405f2090565b6001600160a01b0388165f90815260a060205260409020611cbb90611c5f565b611a71565b506118de611cf6610ba9610f918b610490611ce6888801515f5260af60205260405f2090565b888b01515f5260205260405f2090565b1590506118d5565b602081015146036117b05760208083611d4961159a61103c847f2c77a82144bdfced090e1946cf209e1730d693834f2cc87a805d041417b34b479801515f5260a260205260405f2090565b61189c565b3461039d57608036600319011261039d57611e87600435611d6e8161038c565b6119da60243591611d7e8361038c565b61049060643581604435611d94853b1515614e59565b6001600160a01b0392611dce90611dae8986161515614fec565b611e13611ddb610f918961049085611dce895f5260af60205260405f2090565b905f5260205260405f2090565b95611de98188161515614ea4565b3390611e0c610f91896104908d61049089611dce8d5f5260ae60205260405f2090565b1614615031565b611e35896119da876104908b61049087611dce8b5f5260ae60205260405f2090565b611e57896119da896104908961049087611dce8b5f5260ae60205260405f2090565b611e79896119da876104908b61049089611dce895f5260ae60205260405f2090565b5f5260ae60205260405f2090565b005b81601f8201121561039d57803591611ea08361062c565b92611eae604051948561060a565b808452602092838086019260051b82010192831161039d578301905b828210611ed8575050505090565b81358152908301908301611eca565b81601f8201121561039d57803591611efe8361062c565b92611f0c604051948561060a565b808452602092838086019260051b82010192831161039d578301905b828210611f36575050505090565b813560ff8116810361039d578152908301908301611f28565b61012036600319011261039d57611f646103a1565b67ffffffffffffffff9060c43582811161039d57611f86903690600401611e89565b60e43583811161039d57611f9e903690600401611e89565b906101043593841161039d57611fbb611e87943690600401611ee7565b9260a435906084359060643590604435906024359061353d565b606090600319011261039d5760043590602435906044356103d58161038c565b3461039d57602060ff6104a561200a36611fd5565b5f92835260ad865260408084209284529186528183206001600160a01b039091168352602052902090565b3461039d575f36600319011261039d576033546040516001600160a01b039091168152602090f35b9081518082526020808093019301915f5b82811061207c575050505090565b83516001600160a01b03168552938101939281019260010161206e565b3461039d575f36600319011261039d5760405180609b54808252826020809301609b5f525f805160206150be833981519152925f5b858282106120f9575050506120e59250038361060a565b610c7260405192828493845283019061205d565b85546001600160a01b03168452600195860195889550930192016120ce565b3461039d57602036600319011261039d57612131612eca565b600435609e55005b3461039d57602036600319011261039d5760206004356121588161038c565b60018060a01b038091165f5260b1825260405f205416604051908152f35b3461039d57602061218636611fd5565b5f92835260af845260408084209284529184528183206001600160a01b03918216845260205291205b5416604051908152f35b3461039d5760206121af6121cc3661041c565b5f93845260ae865260408085209385529286528284206001600160a01b03928316855260205291909220919291610490565b3461039d57606036600319011261039d5760043561221b8161038c565b602435612227816109b3565b60443590612234826109b3565b61223c612eca565b60b25461226690612255906001600160a01b0316610ba9565b6001600160a01b0385161415614fa9565b80806124da575b156123e657509061227c614250565b9061228a81610b898461427c565b609d5461229f906001600160a01b0316610ba9565b91604051936315ab88c960e31b948581526020928382600481895afa908115610c97576122dc5f926123289484916123c9575b50610b8983614289565b609c546122f5906001600160a01b0316610b8983614299565b6001600160a01b0386165f90815260a1602052604090205460405163d06ca61f60e01b8152938492839260048401614337565b0381885afa8015610c9757612343915f91610c765750614299565b51609e5411908115916123c1575b5061235857005b6001600160a01b0382165f90815260a1602052604090208190549460046040518096819382525afa8015610c97575f9461239f94610c0a9387936123a2575b505083614387565b55005b6123b9929350803d10610cc357610cb5818361060a565b905f80612397565b90505f612351565b6123e09150873d8911610cc357610cb5818361060a565b5f6122d2565b15806124ba575b6123f357005b6123fb614235565b9061240983610b898461427c565b609c5461245a905f906001600160a01b03169361242985610b8983614289565b609d5461243e906001600160a01b0316610ba9565b6001600160a01b0387165f90815260a160205260409020610c23565b03915afa8015610c9757612474915f91610d655750614289565b51609e5411908115916124b2575b5015611e875781610c0a61239f926124ab5f9560018060a01b03165f5260a160205260405f2090565b5483614387565b90505f612482565b506001600160a01b0382165f90815260a1602052604090205415156123ed565b506001600160a01b0383165f90815260a16020526040902054151561226d565b3461039d57602036600319011261039d576004356125178161038c565b61251f612eca565b6001600160a01b03168015612545576001600160601b0360a01b60995416176099555f80f35b60405162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22fa7aba722a960991b6044820152606490fd5b3461039d57602060ff6104a561258f366103b0565b6001600160a01b039182165f90815260a7865260408082209290931681526020919091522090565b3461039d57602036600319011261039d5760206004356125d68161038c565b60018060a01b038091165f5260a5825260405f205416604051908152f35b3461039d57604036600319011261039d57600435602435612614816109b3565b61261c612eca565b811561267657816040917fe78910fc1a08062969a9edf6b274d453a04a1734507fabbd5bb445d5cb8eaeae935f5260a260205261266781845f209060ff801983541691151516179055565b825191825215156020820152a1005b60405162461bcd60e51b815260206004820152601060248201526f1253959053125117d0d210525397d25160821b6044820152606490fd5b3461039d57602036600319011261039d576004356126cb8161038c565b60018060a01b03165f5260a6602052602060ff60405f2054166040519015158152f35b3461039d5760206121af612701366103b0565b6001600160a01b039182165f90815260a9855260408082209284168252602092909252209091565b3461039d57602036600319011261039d576004356127468161038c565b61274e612eca565b609d80546001600160a01b0319166001600160a01b0392909216919091179055005b3461039d575f36600319011261039d576098546040516001600160a01b039091168152602090f35b3461039d57604036600319011261039d576004356127b58161038c565b6024356127c0612eca565b6001600160a01b0382169182156128625761271082101561282a576001600160a01b03165f90815260a3602052604090207fe4427eddc01962bfd3d30c0f180ab69439b489e5cd0c9c607aed338f3edc350691610ac6918190556040519081529081906020820190565b60405162461bcd60e51b815260206004820152601060248201526f4645455f43414e545f42455f3130302560801b6044820152606490fd5b60405162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22faa27a5a2a760991b6044820152606490fd5b634e487b7160e01b5f52603260045260245ffd5b609b548110156128cd57609b5f525f805160206150be83398151915201905f90565b612897565b3461039d57602036600319011261039d57600435609b5481101561039d57609b5f525f805160206150be83398151915201546040516001600160a01b039091168152602090f35b3461039d575f36600319011261039d57609a546040516001600160a01b039091168152602090f35b606036600319011261039d576004356129598161038c565b602435604435916129686134e7565b61297382151561337a565b6001600160a01b03818116929061298b8415156133bc565b6129a86129a361103c875f5260a260205260405f2090565b613408565b6129c5610f918461049088611dce465f5260af60205260405f2090565b16936129d2851515613444565b5f6129f061103c8561049085611dce465f5260ad60205260405f2090565b15612bf457506001915b6001600160a01b0384165f90815260a36020526040812054919084612aa357505f805160206150de833981519152939291612a3a91612a95963390614671565b949091612a5333610490835f5260a860205260405f2090565b92835493612a6085613484565b905560405194859433984693879260a094919796959260c0850198855260208501526040840152606083015260808201520152565b0390a45b611e876001606555565b92949260018503612b035750612ae594612ad25f805160206150de833981519152959493612afb933386614671565b969093612adf88866134da565b9061464e565b612a5333610490835f5260a860205260405f2090565b0390a4612a99565b93929160028414612b1c575b5050505050505050612a99565b60b254612b31906001600160a01b0316610ba9565b8703612bcc57506001600160a01b039091165f90815260a36020526040902081905480612b89575b505f805160206150de8339815191529394612ae5612b7892341461349f565b0390a45b5f80808080808080612b0f565b5f805160206150de8339815191529450819250612bac612bb391612b7893613079565b6064900490565b94612ae5612bc18785613492565b939250509493612b59565b5f805160206150de8339815191529450612a3a91612bec96933390614671565b0390a4612b7c565b60b254612c09906001600160a01b0316610ba9565b808614908115612c29575b5015612c2357506002916129fa565b916129fa565b905086145f612c14565b3461039d575f36600319011261039d576020609e54604051908152f35b3461039d57604036600319011261039d576020610413602435612c728161038c565b6004355f5260a8835260405f209060018060a01b03165f5260205260405f2090565b3461039d57608036600319011261039d57612cae36611498565b612cb7366114ca565b81516001600160a01b031681519091906020906001600160a01b0316930190815146145f14612dd9575f8051602061507e83398151915291612d0b61159a61103c60208501515f5260a260205260405f2090565b61172661160e612d45610f9188610490896104906020612d348a515f5260ae60205260405f2090565b9a01998a515f5260205260405f2090565b6001600160a01b039690612d5c9088163314614b54565b86612d7a610f918361049061165889515f5260af60205260405f2090565b16151580612dac575b612d8c90614b92565b61049087821697612d9e891515614ac6565b8916986115e38a1515614ac6565b50612d8c612dd0610ba9610f918b6104906116008a515f5260af60205260405f2090565b15159050612d83565b602081015146036117b05781612e0c61159a61103c5f8051602061507e83398151915295515f5260a260205260405f2090565b612d0b565b3461039d57602036600319011261039d57600435612e2e8161038c565b612e36612eca565b6001600160a01b03811615612e4e57611e8790612f22565b60405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608490fd5b3461039d575f36600319011261039d57609d546040516001600160a01b039091168152602090f35b6033546001600160a01b03163303612ede57565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b603380546001600160a01b039283166001600160a01b0319821681179092559091167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a3565b15612f7157565b60405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608490fd5b15612fd457565b60405162461bcd60e51b815260206004820152601860248201527f4c495354494e475f4645455f43414e545f42455f5a45524f00000000000000006044820152606490fd5b1561302057565b60405162461bcd60e51b815260206004820152601960248201527f43414e545f50524f564944455f5a45524f5f41444452455353000000000000006044820152606490fd5b634e487b7160e01b5f52601160045260245ffd5b8181029291811591840414171561308c57565b613065565b80519067ffffffffffffffff82116105d557600160401b82116105d557609b5482609b55808310613102575b50609b5f526020908101905f805160206150be833981519152905f5b8481106130e7575050505050565b83516001600160a01b031683820155928101926001016130d9565b5f609b8152835f805160206150be83398151915292830192015b82811061312a5750506130bd565b81815560010161311c565b9091959492936003825110613249576131d9613214956131bc6132319961319f876131646131f7991515612fcd565b6001600160a01b039761319a90848a1615158061323e575b61318590613019565b61318d6132ee565b613195613310565b613091565b609755565b60018060a01b03166001600160601b0360a01b6099541617609955565b60018060a01b03166001600160601b0360a01b609a541617609a55565b1660018060a01b03166001600160601b0360a01b609d541617609d55565b60018060a01b03166001600160601b0360a01b6098541617609855565b60018060a01b03166001600160601b0360a01b609c541617609c55565b6103ae6305f5e100609e55565b50868a16151561317c565b60405162461bcd60e51b815260206004820152601b60248201527f4d494e494d554d5f5349474e4552535f53484f554c445f42455f3300000000006044820152606490fd5b1561329557565b60405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608490fd5b61330760ff5f5460081c166133028161328e565b61328e565b6103ae33612f22565b61332460ff5f5460081c166133028161328e565b6001606555565b60405162461bcd60e51b815260206004820152602160248201527f4449524543545f4554485f5452414e534645525f4e4f545f535550504f5254456044820152601160fa1b6064820152608490fd5b1561338157565b60405162461bcd60e51b8152602060048201526013602482015272414d4f554e545f43414e545f42455f5a45524f60681b6044820152606490fd5b156133c357565b60405162461bcd60e51b815260206004820152601a60248201527f544f4b454e5f414444524553535f43414e545f42455f4e554c4c0000000000006044820152606490fd5b1561340f57565b60405162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22fa1a420a4a760991b6044820152606490fd5b1561344b57565b60405162461bcd60e51b81526020600482015260116024820152702aa729aaa82827a92a22a22faa27a5a2a760791b6044820152606490fd5b5f19811461308c5760010190565b9190820391821161308c57565b156134a657565b60405162461bcd60e51b815260206004820152600c60248201526b4c4553535f4c4f434b494e4760a01b6044820152606490fd5b9190820180921161308c57565b6002606554146134f8576002606555565b60405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606490fd5b9382979394989291969861354f6134e7565b6001600160a01b039361356582861615156133bc565b613570331515613f86565b61357b89151561337a565b863361358f8a5f5260ac60205260405f2090565b6001600160a01b039091165f908152602091909152604090205f918252602052604090205460ff16156135c190613fc5565b6135d3885f5260a260205260405f2090565b5460ff166135e090613408565b81466135f48a5f5260af60205260405f2090565b5f918252602052604090206001600160a01b039091165f90815260209190915260409020546001600160a01b0316958587169b8c151561363390613444565b8a8a868a874661364b855f5260b060205260405f2090565b5f918252602090815260408083206001600160a01b03948516845282528083209490931682529290925290205460ff169861368e974694908e908e9033306148b4565b61369790614011565b811580613f68575b613ee5575b6136c1611c5f86611dce336104908b5f5260ac60205260405f2090565b80613c67575015613bca5785613bac575b6136dd853384614602565b60b2546136f2906001600160a01b0316610ba9565b871415908180613a90575b80613a70575b15613866575050613712614250565b9061372081610b898461427c565b609d54613735906001600160a01b0316610ba9565b604051906315ab88c960e31b918281526020948582600481865afa908115610c97576122dc5f9261377094849161384f5750610b8983614289565b0381855afa8015610c975761378b915f91610c765750614299565b51609e5411156137e9575b505050506137dc5f8051602061509e833981519152935b60405193849333974693869192608093969594919660a084019784526020840152604083015260608201520152565b0390a36103ae6001606555565b6001600160a01b0383165f90815260a160205260409020939692938790549260046040518094819382525afa938415610c9757610c0a6137dc955f94613846945f8051602061509e8339815191529b87936123a257505083614387565b55935f80613796565b6123e09150893d8b11610cc357610cb5818361060a565b8161399b575b508061397b575b613890575b506137dc5f8051602061509e833981519152936137ad565b61390f9361389c614235565b916138aa81610b898561427c565b609c545f906001600160a01b0316936138c685610b8983614289565b609d546138db906001600160a01b0316610ba9565b6001600160a01b0384165f90815260a16020526040902054604051809a8194829363d06ca61f60e01b845260048401614337565b03915afa928315610c975761393c6137dc945f8051602061509e833981519152985f91610d655750614289565b51609e541115613950575b50509350613878565b81610c0a613973926124ab5f9560018060a01b03165f5260a160205260405f2090565b555f80613947565b506001600160a01b0381165f90815260a160205260409020541515613873565b609d549091506139b3906001600160a01b0316610ba9565b604051809163c45a015560e01b825281600460209485935afa8015610c9757613a18839185935f91613a53575b50609c5460405163e6a4390560e01b81526001600160a01b038981166004830152909116602482015293849283919082906044820190565b0392165afa918215610c97575f92613a36575b50501615155f61386c565b613a4c9250803d10610cc357610cb5818361060a565b5f80613a2b565b613a6a9150833d8511610cc357610cb5818361060a565b5f6139e0565b506001600160a01b0383165f90815260a160205260409020541515613703565b50609d54613aa6906001600160a01b0316610ba9565b60405163c45a015560e01b8152602091908281600481855afa908115610c975783905f92613b8c575b506040516315ab88c960e31b81529192829060049082905afa908115610c975784928492613b33925f91613b6f575b5060405163e6a4390560e01b81526001600160a01b03808b166004830152909116602482015293849283919082906044820190565b0392165afa908115610c975783925f92613b52575b50501615156136fd565b613b689250803d10610cc357610cb5818361060a565b5f80613b48565b613b869150843d8611610cc357610cb5818361060a565b5f613afe565b60049250613ba690823d8411610cc357610cb5818361060a565b91613acf565b609954613bc59087906001600160a01b03165b84614602565b6136d2565b85613c3e575b60405163a9059cbb60e01b8152336004820152602481018690526020816044815f8c5af1908115610c97575f91613c20575b506136dd5760405162461bcd60e51b815280610a5c600482016140d7565b613c38915060203d81116110e7576110d7818361060a565b5f613c02565b6001600160a01b0382165f90815260a160205260409020613c608782546134da565b9055613bd0565b60018103613d9657505060b254613c86906001600160a01b0316610ba9565b8703613cf957613ca147613c9a88886134da565b1115614107565b85613cc5575b613cc05f80808089335af1613cba614153565b506141d4565b6136dd565b613cf45f8080808a613ce4610ba9610ba960995460018060a01b031690565b5af1613cee614153565b50614192565b613ca7565b85613d6d575b60405163a9059cbb60e01b8152336004820152602481018690526020816044815f8c5af1908115610c97575f91613d4f575b50613cc05760405162461bcd60e51b815280610a5c600482016140d7565b613d67915060203d81116110e7576110d7818361060a565b5f613d31565b6001600160a01b0382165f90815260a160205260409020613d8f8782546134da565b9055613cff565b600214613da4575b506136dd565b60b254613db9906001600160a01b0316610ba9565b8803613e115750613dce47613c9a88886134da565b85613ded575b613de75f80808089335af1613cba614153565b5f613d9e565b613e0c5f8080808a613ce4610ba9610ba960995460018060a01b031690565b613dd4565b15613e485785613e2c575b613e27853384614602565b613de7565b609954613e439087906001600160a01b0316613bbf565b613e1c565b85613ebc575b60405163a9059cbb60e01b8152336004820152602481018690526020816044815f8c5af1908115610c97575f91613e9e575b50613de75760405162461bcd60e51b815280610a5c600482016140d7565b613eb6915060203d81116110e7576110d7818361060a565b5f613e80565b6001600160a01b0382165f90815260a160205260409020613ede8782546134da565b9055613e4e565b6040516370a0823160e01b81523060048201526020816024818d5afa908115610c9757613f4591613f34915f91613f4a575b506001600160a01b0387165f90815260a160205260409020611014565b613f3e8a8a6134da565b1115614077565b6136a4565b613f62915060203d81116111595761114b818361060a565b5f613f17565b5060b254613f7e906001600160a01b0316610ba9565b89141561369f565b15613f8d57565b60405162461bcd60e51b815260206004820152601060248201526f24a72b20a624a22fa922a1a2a4ab22a960811b6044820152606490fd5b15613fcc57565b60405162461bcd60e51b815260206004820152601760248201527f4e4f4e43455f414c52454144595f50524f4345535345440000000000000000006044820152606490fd5b1561401857565b60405162461bcd60e51b815260206004820152601860248201527f494e56414c49445f5245434f56455245445f5349474e455200000000000000006044820152606490fd5b9081602091031261039d575190565b6040513d5f823e3d90fd5b1561407e57565b606460405162461bcd60e51b815260206004820152602060248201527f494e53554646494349454e545f4c49515549444954595f494e5f4252494447456044820152fd5b9081602091031261039d57516103d5816109b3565b6060906020815260156020820152741513d2d15397d514905394d1915497d19052531151605a1b60408201520190565b1561410e57565b60405162461bcd60e51b815260206004820152601a60248201527f494e53554646494349454e545f46554e445f494e5f42524944450000000000006044820152606490fd5b3d1561418d573d9067ffffffffffffffff82116105d55760405191614182601f8201601f19166020018461060a565b82523d5f602084013e565b606090565b1561419957565b60405162461bcd60e51b815260206004820152601360248201527211915157d514905394d1915497d19052531151606a1b6044820152606490fd5b156141db57565b60405162461bcd60e51b815260206004820152601b60248201527f4e41544956455f434f494e5f5452414e534645525f4641494c454400000000006044820152606490fd5b9081602091031261039d57516103d58161038c565b60405190614242826105ee565b600282526040366020840137565b604051906080820182811067ffffffffffffffff8211176105d557604052600382526060366020840137565b8051156128cd5760200190565b8051600110156128cd5760400190565b8051600210156128cd5760600190565b80518210156128cd5760209160051b010190565b602090818184031261039d5780519067ffffffffffffffff821161039d57019180601f8401121561039d5782516142f38161062c565b93614301604051958661060a565b818552838086019260051b82010192831161039d578301905b828210614328575050505090565b8151815290830190830161431a565b6040906103d593928152816020820152019061205d565b90608092614373919695949683525f602084015260a0604084015260a083019061205d565b6001600160a01b0390951660608201520152565b90916143a7836143a1610ba9609d5460018060a01b031690565b8461453b565b609d546143bc906001600160a01b0316610ba9565b6040516315ab88c960e31b8082526020918281600481875afa908115610c97575f9161451e575b506001600160a01b038581169116036144925750505061441b90614412614408614235565b93610b898561427c565b610b8983614289565b609d54614430906001600160a01b0316610ba9565b6099549092906001600160a01b03165b92803b1561039d5761446e935f80946040519687958694859363791ac94760e01b855242926004860161434e565b03925af18015610c975761447f5750565b8061448c6103ae926105da565b806104b1565b90919492506144ac6144a2614250565b94610b898661427c565b609c546144c5906001600160a01b0316610b8986614289565b6040519081528181600481885afa908115610c97576144f0925f92614501575b5050610b8984614299565b6099546001600160a01b0316614440565b6145179250803d10610cc357610cb5818361060a565b5f806144e5565b6145359150833d8511610cc357610cb5818361060a565b5f6143e3565b60405163095ea7b360e01b602082019081526001600160a01b03909316602482015260448101939093525f92839290839061458381606481015b03601f19810183528261060a565b51925af161458f614153565b816145d3575b501561459d57565b60405162461bcd60e51b815260206004820152600e60248201526d1054141493d59157d1905253115160921b6044820152606490fd5b80518015925082156145e8575b50505f614595565b6145fb92506020809183010191016140c2565b5f806145e0565b6040516340c10f1960e01b60208201526001600160a01b039290921660248301526044808301939093529181529061463b60648361060a565b8151614645575050565b6103ae91614aa8565b60405191630852cd8d60e31b602084015260248301526024825261463b826105ee565b6040516370a0823160e01b80825230600483015294955f959094602094936001600160a01b031692908582602481875afa948515610c975786925f966147c1575b506040516323b872dd60e01b81526001600160a01b0390911660048201523060248201526044810191909152908180606481015b03815f875af1908115610c97575f916147a4575b501561475f57604051908152306004820152908390829060249082905afa908115610c9757614730935f9261130e575050613492565b92806147395750565b83925061474d6147559161475c9395613079565b612710900490565b8092613492565b91565b60405162461bcd60e51b815260206004820152601d60248201527f5452414e534645525f4641494c45445f5748494c455f4c4f434b494e470000006044820152606490fd5b6147bb9150853d87116110e7576110d7818361060a565b5f6146fa565b83929196506147df906146e6943d85116111595761114b818361060a565b959091926146b2565b156147ef57565b60405162461bcd60e51b815260206004820152601960248201527f494e56414c49445f4e554d4245525f4f465f5349474e455253000000000000006044820152606490fd5b1561483b57565b60405162461bcd60e51b8152602060048201526011602482015270494e56414c49445f5349474e415455524560781b6044820152606490fd5b1561487b57565b60405162461bcd60e51b815260206004820152601160248201527024a72b20a624a22fab20a624a220aa27a960791b6044820152606490fd5b97938b9d9c999591969297938b9c609b54809e819051149182614a58575b505080614a4e575b6148e3906147e8565b5f5b8d8110614900575060019e5050505050505050505050505050565b8f5f8e8e6149ed8f948f8f8f8f8f8f8f8f8f9d8f979860209f6149c59a6145756149be9a8c9a6149b89a6149b19a8d9a6149ab9a6149a3986040519a6020998c9a8b019d8e98969492906101109a989694916001600160601b0319809481809460601b168d5260601b1660148c015260601b1660288a015260601b16603c88015260508701526070860152609085015260b084015260d083015260f08201520190565b519020614a65565b996142a9565b5160ff1690565b976142a9565b51926142a9565b5190604051948594859094939260ff6060936080840197845216602083015260408201520152565b838052039060015afa15610c97575f51614a499190614a44906001600160a01b0316614a1a811515614834565b614a3e610ba9614a29856128ab565b905460039190911b1c6001600160a01b031690565b14614874565b613484565b6148e5565b508a518d146148da565b90915051148f8e906148d2565b60405160208101917f19457468657265756d205369676e6564204d6573736167653a0a3332000000008352603c820152603c8152614aa2816105ee565b51902090565b80515f9283926020019083906001600160a01b03165af11561039d57565b15614acd57565b60405162461bcd60e51b815260206004820152600c60248201526b24a72b20a624a22fa0a2222960a11b6044820152606490fd5b156117b057565b15614b0f57565b60405162461bcd60e51b815260206004820152601860248201527f544849535f504149525f414c52454144595f4c495354454400000000000000006044820152606490fd5b15614b5b57565b60405162461bcd60e51b815260206004820152600f60248201526e2727aa2faa27a5a2a72fa7aba722a960891b6044820152606490fd5b15614b9957565b60405162461bcd60e51b815260206004820152601060248201526f1053149150511657d111531254d5115160821b6044820152606490fd5b919091614bdc6134e7565b6001600160a01b03908116918215614c5d57614c2590614c1c60975494614c0586841015614ca2565b5f8080809881945af1614c16614153565b50614ce5565b60975490613492565b9081614c3a575b505050506103ae6001606555565b8280928192614c5496165af1614c4e614153565b50614d31565b5f808080614c2c565b60405162461bcd60e51b815260206004820152601960248201527f43414e545f53454e445f544f5f4e554c4c5f41444452455353000000000000006044820152606490fd5b15614ca957565b60405162461bcd60e51b8152602060048201526014602482015273494e4352454153455f4c495354494e475f46454560601b6044820152606490fd5b15614cec57565b60405162461bcd60e51b815260206004820152601b60248201527f4c495354494e475f4645455f5452414e534645525f4641494c454400000000006044820152606490fd5b15614d3857565b60405162461bcd60e51b815260206004820152602260248201527f524546554e445f52454d41494e494e475f45544845525f53454e545f4641494c604482015261115160f21b6064820152608490fd5b15614d8f57565b60405162461bcd60e51b815260206004820152601460248201527343414e545f42455f4e554c4c5f4144445245535360601b6044820152606490fd5b6040519081818392516020809201915f5b828110614ded575050505003902090565b83516001600160a01b031685528695509381019392810192600101614ddc565b15614e1457565b60405162461bcd60e51b815260206004820152601760248201527f4f4e4c595f4c49535445525f43414e5f4445504f5349540000000000000000006044820152606490fd5b15614e6057565b606460405162461bcd60e51b815260206004820152602060248201527f544f4b454e5f4e4f545f4445504c4f5945445f4f4e5f544849535f434841494e6044820152fd5b15614eab57565b60405162461bcd60e51b815260206004820152601060248201526f1513d2d15397d393d517d31254d5115160821b6044820152606490fd5b15614eea57565b60405162461bcd60e51b815260206004820152601e60248201527f4f4e4c595f544f4b454e5f4c49535445525f43414e5f574954484452415700006044820152606490fd5b15614f3657565b60405162461bcd60e51b815260206004820152600d60248201526c57495448445241575f4c45535360981b6044820152606490fd5b15614f7257565b60405162461bcd60e51b815260206004820152600f60248201526e15d2551211149055d7d19052531151608a1b6044820152606490fd5b15614fb057565b60405162461bcd60e51b815260206004820152601460248201527321a0a72a2fa122afa720aa24ab22afaa27a5a2a760611b6044820152606490fd5b15614ff357565b60405162461bcd60e51b8152602060048201526016602482015275139155d7d3d5d3915497d0d0539517d09157d395531360521b6044820152606490fd5b1561503857565b60405162461bcd60e51b815260206004820152601c60248201527f4f4e4c595f544f4b454e5f4c49535445525f43414e5f4348414e4745000000006044820152606490fdfefa35030c3c7d834268ab6e51b6af06e24b8f502f8fde9c54ed6ba28f36f0e3cbf3f7debab57cb669dc23552fd1d27d490d1a2a8a8750f60cf0d43a6f2ac04072bba9db4cdbea0a37c207bbb83e20f828cd4441c49891101dc94fd20dc8efc349a921fe040b86ab1aa7b07f5c8d9bc081d3082ffdcd001dd54bfb7ee1b186e66ba26469706673582212209af746975f4ecc454cd4a90a7bc94193c0982c72466659757eae0b5e8956759f64736f6c63430008140033
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.