Transactions
Token Transfers
Tokens
Internal Transactions
Coin Balance History
Logs
Code
Read Contract
Write Contract
- Contract name:
- Collector
- Optimization enabled
- false
- Compiler version
- v0.6.12+commit.27d51765
- EVM Version
- default
- Verified at
- 2022-11-01T12:17:22.352792Z
Constructor Arguments
0000000000000000000000002ef06a90b0e7ae3ae508e83ea6628a3987945460000000000000000000000000f0c73e6287867baa4f865a17ee711ec989c78ac0000000000000000000000000ae83571000af4499798d1e3b0fa0070eb3a3e3f9
Arg [0] (address) : 0x2ef06a90b0e7ae3ae508e83ea6628a3987945460
Arg [1] (address) : 0xf0c73e6287867baa4f865a17ee711ec989c78ac0
Arg [2] (address) : 0xae83571000af4499798d1e3b0fa0070eb3a3e3f9
Contract source code
// Sources flattened with hardhat v2.7.0 https://hardhat.org // File contracts/libraries/SafeMath.sol pragma solidity ^0.6.0; // a library for performing overflow-safe math, courtesy of DappHub (https://github.com/dapphub/ds-math) library SafeMath { function add(uint x, uint y) internal pure returns (uint z) { require((z = x + y) >= x, 'ds-math-add-overflow'); } function sub(uint x, uint y) internal pure returns (uint z) { require((z = x - y) <= x, 'ds-math-sub-underflow'); } function mul(uint x, uint y) internal pure returns (uint z) { require(y == 0 || (z = x * y) / y == x, 'ds-math-mul-overflow'); } } // File contracts/interfaces/IERC20.sol pragma solidity >=0.6.0; interface IERC20 { event Approval(address indexed owner, address indexed spender, uint value); event Transfer(address indexed from, address indexed to, uint value); function name() external view returns (string memory); function symbol() external view returns (string memory); function decimals() external view returns (uint8); function totalSupply() external view returns (uint); function balanceOf(address owner) external view returns (uint); function allowance(address owner, address spender) external view returns (uint); function approve(address spender, uint value) external returns (bool); function transfer(address to, uint value) external returns (bool); function transferFrom(address from, address to, uint value) external returns (bool); } // File contracts/libraries/SafeERC20.sol pragma solidity ^0.6.0; library SafeERC20 { function safeSymbol(IERC20 token) internal view returns(string memory) { (bool success, bytes memory data) = address(token).staticcall(abi.encodeWithSelector(0x95d89b41)); return success && data.length > 0 ? abi.decode(data, (string)) : "???"; } function safeName(IERC20 token) internal view returns(string memory) { (bool success, bytes memory data) = address(token).staticcall(abi.encodeWithSelector(0x06fdde03)); return success && data.length > 0 ? abi.decode(data, (string)) : "???"; } function safeDecimals(IERC20 token) public view returns (uint8) { (bool success, bytes memory data) = address(token).staticcall(abi.encodeWithSelector(0x313ce567)); return success && data.length == 32 ? abi.decode(data, (uint8)) : 18; } function safeTransfer(IERC20 token, address to, uint256 amount) internal { (bool success, bytes memory data) = address(token).call(abi.encodeWithSelector(0xa9059cbb, to, amount)); require(success && (data.length == 0 || abi.decode(data, (bool))), "SafeERC20: Transfer failed"); } function safeTransferFrom(IERC20 token, address from, uint256 amount) internal { (bool success, bytes memory data) = address(token).call(abi.encodeWithSelector(0x23b872dd, from, address(this), amount)); require(success && (data.length == 0 || abi.decode(data, (bool))), "SafeERC20: TransferFrom failed"); } } // File contracts/interfaces/IPair.sol pragma solidity ^0.6.0; interface IPair { event Approval(address indexed owner, address indexed spender, uint value); event Transfer(address indexed from, address indexed to, uint value); function name() external pure returns (string memory); function symbol() external pure returns (string memory); function decimals() external pure returns (uint8); function totalSupply() external view returns (uint); function balanceOf(address owner) external view returns (uint); function allowance(address owner, address spender) external view returns (uint); function approve(address spender, uint value) external returns (bool); function transfer(address to, uint value) external returns (bool); function transferFrom(address from, address to, uint value) external returns (bool); function DOMAIN_SEPARATOR() external view returns (bytes32); function PERMIT_TYPEHASH() external pure returns (bytes32); function nonces(address owner) external view returns (uint); function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external; event Mint(address indexed sender, uint amount0, uint amount1); event Burn(address indexed sender, uint amount0, uint amount1, address indexed to); event Swap( address indexed sender, uint amount0In, uint amount1In, uint amount0Out, uint amount1Out, address indexed to ); event Sync(uint112 reserve0, uint112 reserve1); function MINIMUM_LIQUIDITY() external pure returns (uint); function factory() external view returns (address); function token0() external view returns (address); function token1() external view returns (address); function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast); function price0CumulativeLast() external view returns (uint); function price1CumulativeLast() external view returns (uint); function kLast() external view returns (uint); function mint(address to) external returns (uint liquidity); function burn(address to) external returns (uint amount0, uint amount1); function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external; function skim(address to) external; function sync() external; function initialize(address, address) external; } // File contracts/interfaces/IFactory.sol pragma solidity ^0.6.0; interface IFactory { event PairCreated(address indexed token0, address indexed token1, address pair, uint); function feeTo() external view returns (address); function feeToSetter() external view returns (address); function getPair(address tokenA, address tokenB) external view returns (address pair); function allPairs(uint) external view returns (address pair); function allPairsLength() external view returns (uint); function createPair(address tokenA, address tokenB) external returns (address pair); function setFeeTo(address) external; function setFeeToSetter(address) external; } // File contracts/Ownable.sol // Audit on 5-Jan-2021 by Keno and BoringCrypto // P1 - P3: OK pragma solidity ^0.6.0; // Source: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol + Claimable.sol // Edited by BoringCrypto // T1 - T4: OK contract OwnableData { // V1 - V5: OK address public owner; // V1 - V5: OK address public pendingOwner; } // T1 - T4: OK contract Ownable is OwnableData { // E1: OK event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); constructor () internal { owner = msg.sender; emit OwnershipTransferred(address(0), msg.sender); } // F1 - F9: OK // C1 - C21: OK function transferOwnership(address newOwner, bool direct, bool renounce) public onlyOwner { if (direct) { // Checks require(newOwner != address(0) || renounce, "Ownable: zero address"); // Effects emit OwnershipTransferred(owner, newOwner); owner = newOwner; } else { // Effects pendingOwner = newOwner; } } // F1 - F9: OK // C1 - C21: OK function claimOwnership() public { address _pendingOwner = pendingOwner; // Checks require(msg.sender == _pendingOwner, "Ownable: caller != pending owner"); // Effects emit OwnershipTransferred(owner, _pendingOwner); owner = _pendingOwner; pendingOwner = address(0); } // M1 - M5: OK // C1 - C21: OK modifier onlyOwner() { require(msg.sender == owner, "Ownable: caller is not the owner"); _; } } // File contracts/Collector.sol // SPDX-License-Identifier: MIT pragma solidity ^0.6.0; contract Collector is Ownable { using SafeMath for uint256; using SafeERC20 for IERC20; IFactory public immutable factory; address public PToken; address public immutable wada; address public stakingContract; bool public locked; //lock liquidity inside the collector until the staking contract is deployed mapping(address => address) internal _bridges; event LogBridgeSet(address indexed token, address indexed bridge); event LogConvert( address indexed server, address indexed token0, address indexed token1, uint256 amount0, uint256 amount1, uint256 amountPToken ); constructor( address _factory, address _PToken, address _wada ) public { factory = IFactory(_factory); PToken = _PToken; wada = _wada; locked = true; } function bridgeFor(address token) public view returns (address bridge) { bridge = _bridges[token]; if (bridge == address(0)) { bridge = wada; } } function setBridge(address token, address bridge) external onlyOwner { // Checks require( token != PToken && token != wada && token != bridge, "Collector: Invalid bridge" ); // Effects _bridges[token] = bridge; emit LogBridgeSet(token, bridge); } function setStakingContract(address _stakingContract) external onlyOwner { stakingContract = _stakingContract; } function setPToken(address _PToken) external onlyOwner { PToken = _PToken; } modifier onlyEOA() { // Try to make flash-loan exploit harder to do by only allowing externally owned addresses. require(msg.sender == tx.origin, "Collector: must use EOA"); _; } modifier onlyWhenUnlocked() { require(locked == false, "Collector: liquidity is locked"); _; } function setLock(bool _locked) external onlyOwner { locked = _locked; } function convert(address token0, address token1) external onlyEOA() onlyWhenUnlocked() onlyOwner { _convert(token0, token1); } function convertMultiple( address[] calldata token0, address[] calldata token1 ) external onlyEOA() onlyWhenUnlocked() onlyOwner { require(token0.length == token1.length, "the length of the array is invalid"); uint256 len = token0.length; for (uint256 i = 0; i < len; i++) { _convert(token0[i], token1[i]); } } function _convert(address token0, address token1) internal { IPair pair = IPair(factory.getPair(token0, token1)); require(address(pair) != address(0), "Collector: Invalid pair"); IERC20(address(pair)).safeTransfer( address(pair), pair.balanceOf(address(this)) ); (uint256 amount0, uint256 amount1) = pair.burn(address(this)); if (token0 != pair.token0()) { (amount0, amount1) = (amount1, amount0); } emit LogConvert( msg.sender, token0, token1, amount0, amount1, _convertStep(token0, token1, amount0, amount1) ); } function _convertStep( address token0, address token1, uint256 amount0, uint256 amount1 ) internal returns (uint256 PTokenOut) { // Interactions if (token0 == token1) { uint256 amount = amount0.add(amount1); if (token0 == PToken) { IERC20(PToken).safeTransfer(stakingContract, amount); PTokenOut = amount; } else if (token0 == wada) { PTokenOut = _toPToken(wada, amount); } else { address bridge = bridgeFor(token0); amount = _swap(token0, bridge, amount, address(this)); PTokenOut = _convertStep(bridge, bridge, amount, 0); } } else if (token0 == PToken) { IERC20(PToken).safeTransfer(stakingContract, amount0); PTokenOut = _toPToken(token1, amount1).add(amount0); } else if (token1 == PToken) { IERC20(PToken).safeTransfer(stakingContract, amount1); PTokenOut = _toPToken(token0, amount0).add(amount1); } else if (token0 == wada) { // eg. ADA - USDC PTokenOut = _toPToken( wada, _swap(token1, wada, amount1, address(this)).add(amount0) ); } else if (token1 == wada) { // eg. USDT - ADA PTokenOut = _toPToken( wada, _swap(token0, wada, amount0, address(this)).add(amount1) ); } else { // eg. MIC - USDT address bridge0 = bridgeFor(token0); address bridge1 = bridgeFor(token1); if (bridge0 == token1) { // eg. MIC - USDT - and bridgeFor(MIC) = USDT PTokenOut = _convertStep( bridge0, token1, _swap(token0, bridge0, amount0, address(this)), amount1 ); } else if (bridge1 == token0) { // eg. WBTC - DSD - and bridgeFor(DSD) = WBTC PTokenOut = _convertStep( token0, bridge1, amount0, _swap(token1, bridge1, amount1, address(this)) ); } else { PTokenOut = _convertStep( bridge0, bridge1, // eg. USDT - DSD - and bridgeFor(DSD) = WBTC _swap(token0, bridge0, amount0, address(this)), _swap(token1, bridge1, amount1, address(this)) ); } } } function _swap( address fromToken, address toToken, uint256 amountIn, address to ) internal returns (uint256 amountOut) { IPair pair = IPair(factory.getPair(fromToken, toToken)); require(address(pair) != address(0), "Collector: Cannot convert"); (uint256 reserve0, uint256 reserve1, ) = pair.getReserves(); uint256 amountInWithFee = amountIn.mul(997); if (fromToken == pair.token0()) { amountOut = amountInWithFee.mul(reserve1) / reserve0.mul(1000).add(amountInWithFee); IERC20(fromToken).safeTransfer(address(pair), amountIn); pair.swap(0, amountOut, to, new bytes(0)); // TODO: Add maximum slippage? } else { amountOut = amountInWithFee.mul(reserve0) / reserve1.mul(1000).add(amountInWithFee); IERC20(fromToken).safeTransfer(address(pair), amountIn); pair.swap(amountOut, 0, to, new bytes(0)); // TODO: Add maximum slippage? } } function _toPToken(address token, uint256 amountIn) internal returns (uint256 amountOut) { amountOut = _swap(token, PToken, amountIn, stakingContract); } }
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_factory","internalType":"address"},{"type":"address","name":"_PToken","internalType":"address"},{"type":"address","name":"_wada","internalType":"address"}]},{"type":"event","name":"LogBridgeSet","inputs":[{"type":"address","name":"token","internalType":"address","indexed":true},{"type":"address","name":"bridge","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"LogConvert","inputs":[{"type":"address","name":"server","internalType":"address","indexed":true},{"type":"address","name":"token0","internalType":"address","indexed":true},{"type":"address","name":"token1","internalType":"address","indexed":true},{"type":"uint256","name":"amount0","internalType":"uint256","indexed":false},{"type":"uint256","name":"amount1","internalType":"uint256","indexed":false},{"type":"uint256","name":"amountPToken","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"PToken","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"bridge","internalType":"address"}],"name":"bridgeFor","inputs":[{"type":"address","name":"token","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"claimOwnership","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"convert","inputs":[{"type":"address","name":"token0","internalType":"address"},{"type":"address","name":"token1","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"convertMultiple","inputs":[{"type":"address[]","name":"token0","internalType":"address[]"},{"type":"address[]","name":"token1","internalType":"address[]"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IFactory"}],"name":"factory","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"locked","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"pendingOwner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setBridge","inputs":[{"type":"address","name":"token","internalType":"address"},{"type":"address","name":"bridge","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setLock","inputs":[{"type":"bool","name":"_locked","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setPToken","inputs":[{"type":"address","name":"_PToken","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setStakingContract","inputs":[{"type":"address","name":"_stakingContract","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"stakingContract","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"},{"type":"bool","name":"direct","internalType":"bool"},{"type":"bool","name":"renounce","internalType":"bool"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"wada","inputs":[]}]
Deployed ByteCode
0x608060405234801561001057600080fd5b50600436106101005760003560e01c80639dd373b911610097578063cf30901211610066578063cf309012146104c3578063e30c3978146104e3578063e552a11b14610517578063ee99205c1461054b57610100565b80639dd373b914610379578063a761a939146103bd578063bd1b820c1461042b578063c45a01551461048f57610100565b8063619d5194116100d3578063619d51941461026d5780638da5cb5b1461029d57806396bb4fae146102d15780639d22ae8c1461031557610100565b8063078dfbe714610105578063303e6aa4146101615780634e71e0c81461022f5780635aa8cbcd14610239575b600080fd5b61015f6004803603606081101561011b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080351515906020019092919080351515906020019092919050505061057f565b005b61022d6004803603604081101561017757600080fd5b810190808035906020019064010000000081111561019457600080fd5b8201836020820111156101a657600080fd5b803590602001918460208302840111640100000000831117156101c857600080fd5b9091929391929390803590602001906401000000008111156101e957600080fd5b8201836020820111156101fb57600080fd5b8035906020019184602083028401116401000000008311171561021d57600080fd5b90919293919293905050506107f7565b005b610237610ac2565b005b610241610c89565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61029b6004803603602081101561028357600080fd5b81019080803515159060200190929190505050610cad565b005b6102a5610d8b565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610313600480360360208110156102e757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610daf565b005b6103776004803603604081101561032b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610eb4565b005b6103bb6004803603602081101561038f57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506111a5565b005b6103ff600480360360208110156103d357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506112aa565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61048d6004803603604081101561044157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061136c565b005b610497611565565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6104cb611589565b60405180821515815260200191505060405180910390f35b6104eb61159c565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61051f6115c2565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6105536115e8565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610640576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b81156107b057600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614158061067f5750805b6106f1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f4f776e61626c653a207a65726f2061646472657373000000000000000000000081525060200191505060405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3826000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506107f2565b82600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b505050565b3273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610898576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f436f6c6c6563746f723a206d7573742075736520454f4100000000000000000081525060200191505060405180910390fd5b60001515600360149054906101000a900460ff16151514610921576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f436f6c6c6563746f723a206c6971756964697479206973206c6f636b6564000081525060200191505060405180910390fd5b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146109e2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b818190508484905014610a40576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180612a766022913960400191505060405180910390fd5b600084849050905060005b81811015610aba57610aad868683818110610a6257fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff16858584818110610a8b57fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff1661160e565b8080600101915050610a4b565b505050505050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610b8a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c657220213d2070656e64696e67206f776e657281525060200191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b7f000000000000000000000000ae83571000af4499798d1e3b0fa0070eb3a3e3f981565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610d6e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b80600360146101000a81548160ff02191690831515021790555050565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610e70576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b80600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610f75576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415801561101f57507f000000000000000000000000ae83571000af4499798d1e3b0fa0070eb3a3e3f973ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b801561105757508073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b6110c9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f436f6c6c6563746f723a20496e76616c6964206272696467650000000000000081525060200191505060405180910390fd5b80600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f2e103aa707acc565f9a1547341914802b2bfe977fd79c595209f248ae4b0061360405160405180910390a35050565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611266576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b80600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611367577f000000000000000000000000ae83571000af4499798d1e3b0fa0070eb3a3e3f990505b919050565b3273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461140d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f436f6c6c6563746f723a206d7573742075736520454f4100000000000000000081525060200191505060405180910390fd5b60001515600360149054906101000a900460ff16151514611496576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f436f6c6c6563746f723a206c6971756964697479206973206c6f636b6564000081525060200191505060405180910390fd5b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611557576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b611561828261160e565b5050565b7f0000000000000000000000002ef06a90b0e7ae3ae508e83ea6628a398794546081565b600360149054906101000a900460ff1681565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60007f0000000000000000000000002ef06a90b0e7ae3ae508e83ea6628a398794546073ffffffffffffffffffffffffffffffffffffffff1663e6a4390584846040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060206040518083038186803b1580156116b557600080fd5b505afa1580156116c9573d6000803e3d6000fd5b505050506040513d60208110156116df57600080fd5b81019080805190602001909291905050509050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611795576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f436f6c6c6563746f723a20496e76616c6964207061697200000000000000000081525060200191505060405180910390fd5b611861818273ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561180057600080fd5b505afa158015611814573d6000803e3d6000fd5b505050506040513d602081101561182a57600080fd5b81019080805190602001909291905050508373ffffffffffffffffffffffffffffffffffffffff16611a719092919063ffffffff16565b6000808273ffffffffffffffffffffffffffffffffffffffff166389afcb44306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1681526020019150506040805180830381600087803b1580156118cc57600080fd5b505af11580156118e0573d6000803e3d6000fd5b505050506040513d60408110156118f657600080fd5b810190808051906020019092919080519060200190929190505050915091508273ffffffffffffffffffffffffffffffffffffffff16630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b15801561195b57600080fd5b505afa15801561196f573d6000803e3d6000fd5b505050506040513d602081101561198557600080fd5b810190808051906020019092919050505073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16146119d357808280925081935050505b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fd06b1d7ed79b664d17472c6f6997b929f1abe463ccccb4e5b6a0038f2f730c158585611a478b8b8a8a611c54565b60405180848152602001838152602001828152602001935050505060405180910390a45050505050565b600060608473ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8585604051602401808373ffffffffffffffffffffffffffffffffffffffff168152602001828152602001925050506040516020818303038152906040529060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040518082805190602001908083835b60208310611b345780518252602082019150602081019050602083039250611b11565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114611b96576040519150601f19603f3d011682016040523d82523d6000602084013e611b9b565b606091505b5091509150818015611bdb5750600081511480611bda5750808060200190516020811015611bc857600080fd5b81019080805190602001909291905050505b5b611c4d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f5361666545524332303a205472616e73666572206661696c656400000000000081525060200191505060405180910390fd5b5050505050565b60008373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff161415611e26576000611c9f838561226d90919063ffffffff16565b9050600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff161415611d6e57611d66600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611a719092919063ffffffff16565b809150611e20565b7f000000000000000000000000ae83571000af4499798d1e3b0fa0070eb3a3e3f973ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff161415611df357611dec7f000000000000000000000000ae83571000af4499798d1e3b0fa0070eb3a3e3f9826122f0565b9150611e1f565b6000611dfe876112aa565b9050611e0c8782843061234a565b9150611e1b8182846000611c54565b9250505b5b50612265565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff161415611f0e57611eeb600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611a719092919063ffffffff16565b611f0783611ef986856122f0565b61226d90919063ffffffff16565b9050612264565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161415611ff657611fd3600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611a719092919063ffffffff16565b611fef82611fe187866122f0565b61226d90919063ffffffff16565b9050612263565b7f000000000000000000000000ae83571000af4499798d1e3b0fa0070eb3a3e3f973ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614156120b8576120b17f000000000000000000000000ae83571000af4499798d1e3b0fa0070eb3a3e3f96120ac8561209e887f000000000000000000000000ae83571000af4499798d1e3b0fa0070eb3a3e3f9883061234a565b61226d90919063ffffffff16565b6122f0565b9050612262565b7f000000000000000000000000ae83571000af4499798d1e3b0fa0070eb3a3e3f973ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16141561217a576121737f000000000000000000000000ae83571000af4499798d1e3b0fa0070eb3a3e3f961216e84612160897f000000000000000000000000ae83571000af4499798d1e3b0fa0070eb3a3e3f9893061234a565b61226d90919063ffffffff16565b6122f0565b9050612261565b6000612185866112aa565b90506000612192866112aa565b90508573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156121e6576121df82876121d98a868a3061234a565b87611c54565b925061225e565b8673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156122385761223187828761222c8a868a3061234a565b611c54565b925061225d565b61225a82826122498a868a3061234a565b6122558a868a3061234a565b611c54565b92505b5b50505b5b5b5b5b949350505050565b60008282840191508110156122ea576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f64732d6d6174682d6164642d6f766572666c6f7700000000000000000000000081525060200191505060405180910390fd5b92915050565b600061234283600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1661234a565b905092915050565b6000807f0000000000000000000000002ef06a90b0e7ae3ae508e83ea6628a398794546073ffffffffffffffffffffffffffffffffffffffff1663e6a4390587876040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060206040518083038186803b1580156123f257600080fd5b505afa158015612406573d6000803e3d6000fd5b505050506040513d602081101561241c57600080fd5b81019080805190602001909291905050509050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156124d2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f436f6c6c6563746f723a2043616e6e6f7420636f6e766572740000000000000081525060200191505060405180910390fd5b6000808273ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b815260040160606040518083038186803b15801561251b57600080fd5b505afa15801561252f573d6000803e3d6000fd5b505050506040513d606081101561254557600080fd5b81019080805190602001909291908051906020019092919080519060200190929190505050506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff16915060006125a66103e5886129e090919063ffffffff16565b90508373ffffffffffffffffffffffffffffffffffffffff16630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b1580156125ee57600080fd5b505afa158015612602573d6000803e3d6000fd5b505050506040513d602081101561261857600080fd5b810190808051906020019092919050505073ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff16141561281a57612683816126756103e8866129e090919063ffffffff16565b61226d90919063ffffffff16565b61269683836129e090919063ffffffff16565b8161269d57fe5b0494506126cb84888b73ffffffffffffffffffffffffffffffffffffffff16611a719092919063ffffffff16565b8373ffffffffffffffffffffffffffffffffffffffff1663022c0d9f60008789600067ffffffffffffffff8111801561270357600080fd5b506040519080825280601f01601f1916602001820160405280156127365781602001600182028036833780820191505090505b506040518563ffffffff1660e01b8152600401808581526020018481526020018373ffffffffffffffffffffffffffffffffffffffff16815260200180602001828103825283818151815260200191508051906020019080838360005b838110156127ae578082015181840152602081019050612793565b50505050905090810190601f1680156127db5780820380516001836020036101000a031916815260200191505b5095505050505050600060405180830381600087803b1580156127fd57600080fd5b505af1158015612811573d6000803e3d6000fd5b505050506129d4565b612841816128336103e8856129e090919063ffffffff16565b61226d90919063ffffffff16565b61285484836129e090919063ffffffff16565b8161285b57fe5b04945061288984888b73ffffffffffffffffffffffffffffffffffffffff16611a719092919063ffffffff16565b8373ffffffffffffffffffffffffffffffffffffffff1663022c0d9f86600089600067ffffffffffffffff811180156128c157600080fd5b506040519080825280601f01601f1916602001820160405280156128f45781602001600182028036833780820191505090505b506040518563ffffffff1660e01b8152600401808581526020018481526020018373ffffffffffffffffffffffffffffffffffffffff16815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561296c578082015181840152602081019050612951565b50505050905090810190601f1680156129995780820380516001836020036101000a031916815260200191505b5095505050505050600060405180830381600087803b1580156129bb57600080fd5b505af11580156129cf573d6000803e3d6000fd5b505050505b50505050949350505050565b6000808214806129fd57508282838502925082816129fa57fe5b04145b612a6f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f64732d6d6174682d6d756c2d6f766572666c6f7700000000000000000000000081525060200191505060405180910390fd5b9291505056fe746865206c656e677468206f662074686520617272617920697320696e76616c6964a264697066735822122054bfbe2719476aa7d153613e012eb66d1299af0f7a7daf3fdcdacbb482b73c6164736f6c634300060c0033