Address Details
contract
0x85538001F308B9b5A8989c8D260C5048c547d522
- Contract Name
- SavingsCELOWithUbeV1
- Creator
- 0x4d82bf–a04757 at 0xcc53dc–2d7984
- Balance
- 0.00000000000000114 CELO ( )
- Locked CELO Balance
- 0.00 CELO
- Voting CELO Balance
- 0.00 CELO
- Pending Unlocked Gold
- 0.00 CELO
- Tokens
-
Fetching tokens...
- Transactions
- 2,248 Transactions
- Transfers
- 9,457 Transfers
- Gas Used
- 428,578,150
- Last Balance Update
- 24841536
Transactions
Token Transfers
Tokens
Internal Transactions
Coin Balance History
Logs
Code
Read Contract
Write Contract
This contract has been verified via Sourcify.
View contract in Sourcify repository
- Contract name:
- SavingsCELOWithUbeV1
- Optimization enabled
- false
- Compiler version
- v0.6.8+commit.0bbfe453
- EVM Version
- istanbul
- Verified at
- 2021-07-28T05:44:38.759125Z
Contract source code
//SPDX-License-Identifier: MIT pragma solidity 0.6.8; import "@openzeppelin/contracts/math/SafeMath.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "./interfaces/ISavingsCELO.sol"; import "./interfaces/IUniswapV2.sol"; // @title SavingsCELOWithUbeV1 // @notice This contract implements useful atomic wrappers to interact with the // SavingsCELO and the Ubeswap CELO<->sCELO pool contracts. This contract doesn't hold // any state or user funds, it only exists to implement helpful atomic wrappers. // Contract itself is un-upgradable, but since it holds no state, it can be easily replaced or // extended by a new version. contract SavingsCELOWithUbeV1 { using SafeMath for uint256; /// @dev SavingsCELO contract, ISavingsCELO public savingsCELO; /// @dev Ubeswap Router contract. IUniswapV2Router public ubeRouter; /// @dev Ubeswap CELO<->sCELO pool contract. IUniswapV2Pair public ubePair; /// @dev Core GoldToken contract. IERC20 public CELO; /// @dev emitted when deposit succeeds. /// @param from address that initiated the deposit. /// @param celoAmount amount of CELO that was deposited. /// @param savingsAmount amount of sCELO that was returned in exchange. /// @param direct if True, then deposit was done through SavingsCELO contract directly. /// If false, deposit was completed through an Ubeswap trade. event Deposited(address indexed from, uint256 celoAmount, uint256 savingsAmount, bool direct); /// @dev emitted when user adds liquidity to the CELO<->sCELO Ubeswap pool. /// @param from address that added the liquidity. /// @param celoAmount amount of CELO that the user provided. /// @param savingsAmount amount of sCELO that the user provided. /// @param liquidity amount of Ubeswap Pool liquidity tokens returned to the user. event AddedLiquidity(address indexed from, uint256 celoAmount, uint256 savingsAmount, uint256 liquidity); constructor ( address _savingsCELO, address _CELO, address _ubeRouter) public { savingsCELO = ISavingsCELO(_savingsCELO); CELO = IERC20(_CELO); ubeRouter = IUniswapV2Router(_ubeRouter); IUniswapV2Factory factory = IUniswapV2Factory(ubeRouter.factory()); address _pair = factory.getPair(_savingsCELO, _CELO); if (_pair == address(0)) { _pair = factory.createPair(_savingsCELO, _CELO); } require(_pair != address(0), "Ubeswap pair must exist!"); ubePair = IUniswapV2Pair(_pair); } /// @notice Converts CELO to sCELO tokens. Automatically chooses the best rate between /// a direct deposit in SavingsCELO contract or a trade in Ubeswap CELO<->sCELO pool. /// @return received_sCELO amount of sCELO tokens returned to the caller. function deposit() external payable returns (uint256 received_sCELO) { (uint256 reserve_CELO, uint256 reserve_sCELO) = ubeGetReserves(); uint256 fromUbe_sCELO = (reserve_CELO == 0 || reserve_sCELO == 0) ? 0 : ubeGetAmountOut(msg.value, reserve_CELO, reserve_sCELO); uint256 fromDirect_sCELO = savingsCELO.celoToSavings(msg.value); bool direct; if (fromDirect_sCELO >= fromUbe_sCELO) { direct = true; received_sCELO = savingsCELO.deposit{value: msg.value}(); assert(received_sCELO >= fromDirect_sCELO); } else { direct = false; address[] memory path = new address[](2); path[0] = address(CELO); path[1] = address(savingsCELO); require( CELO.approve(address(ubeRouter), msg.value), "CELO approve failed for ubeRouter!"); received_sCELO = ubeRouter.swapExactTokensForTokens( msg.value, fromUbe_sCELO, path, address(this), block.timestamp)[1]; assert(received_sCELO >= fromUbe_sCELO); } require( savingsCELO.transfer(msg.sender, received_sCELO), "sCELO transfer failed!"); emit Deposited(msg.sender, msg.value, received_sCELO, direct); return received_sCELO; } /// @notice Adds liquidity in proportioned way to Ubeswap CELO<->sCELO pool. Will convert /// necessary amount of CELO to sCELO tokens before adding liquidity too. /// @param amount_CELO amount of CELO to take from caller. /// @param amount_sCELO amount of sCELO to take from caller. /// @param maxReserveRatio maximum allowed reserve ratio. maxReserveRatio is multiplied by 1e18 to /// represent a float value as an integer. /// @dev maxReserveRatio protects the caller from adding liquidity when pool is not balanced. /// @return addedLiquidity amount of Ubeswap pool liquidity tokens that got added and sent to the caller. function addLiquidity( uint256 amount_CELO, uint256 amount_sCELO, uint256 maxReserveRatio ) external returns (uint256 addedLiquidity) { (uint256 _amount_CELO, uint256 _amount_sCELO) = (amount_CELO, amount_sCELO); uint256 toConvert_CELO = calculateToConvertCELO(amount_CELO, amount_sCELO, maxReserveRatio); uint256 converted_sCELO = 0; if (amount_CELO > 0) { require( CELO.transferFrom(msg.sender, address(this), amount_CELO), "CELO transferFrom failed!"); } if (amount_sCELO > 0) { require( savingsCELO.transferFrom(msg.sender, address(this), amount_sCELO), "sCELO transferFrom failed!"); } if (toConvert_CELO > 0) { converted_sCELO = savingsCELO.deposit{value: toConvert_CELO}(); amount_sCELO = amount_sCELO.add(converted_sCELO); amount_CELO = amount_CELO.sub(toConvert_CELO); } if (amount_CELO > 0) { require( CELO.approve(address(ubeRouter), amount_CELO), "CELO approve failed for ubeRouter!"); } if (amount_sCELO > 0) { require( savingsCELO.approve(address(ubeRouter), amount_sCELO), "sCELO approve failed for ubeRouter!"); } // NOTE: amount_CELO might be few WEI more than needed, however there is no point // to try to return that back to the caller since GAS costs associated with dealing 1 or 2 WEI would be // multiple orders of magnitude more costly. (, , addedLiquidity) = ubeRouter.addLiquidity( address(CELO), address(savingsCELO), amount_CELO, amount_sCELO, amount_CELO.sub(5), amount_sCELO, msg.sender, block.timestamp); emit AddedLiquidity(msg.sender, _amount_CELO, _amount_sCELO, addedLiquidity); return (addedLiquidity); } /// @dev helper function to calculate amount of CELO that needs to be converted to sCELO /// to add liquidity in proportional way. function calculateToConvertCELO( uint256 amount_CELO, uint256 amount_sCELO, uint256 maxReserveRatio ) internal view returns (uint256 toConvert_CELO) { (uint256 reserve_CELO, uint256 reserve_sCELO) = ubeGetReserves(); if (reserve_CELO == 0 && reserve_sCELO == 0) { // If pool is empty, we can safely assume that the reserve ratio is just the ideal 1:1. reserve_CELO = 1; reserve_sCELO = savingsCELO.celoToSavings(1); } uint256 reserve_CELO_as_sCELO = savingsCELO.celoToSavings(reserve_CELO); // Reserve ratio is: max(reserve_sCELO/reserve_CELO_as_sCELO, reserve_CELO_as_sCELO/reserve_sCELO) // We perform comparisons without using division to keep things as safe and correct as possible. require( reserve_sCELO.mul(maxReserveRatio) >= reserve_CELO_as_sCELO.mul(1e18), "Too little sCELO in the liqudity pool. Adding liquidity is not safe!"); require( reserve_CELO_as_sCELO.mul(maxReserveRatio) >= reserve_sCELO.mul(1e18), "Too little CELO in the liqudity pool. Adding liquidity is not safe!"); // matched_CELO and amount_sCELO can be added proportionally. uint256 matched_CELO = amount_sCELO.mul(reserve_CELO).add(reserve_sCELO.sub(1)).div(reserve_sCELO); require( matched_CELO <= amount_CELO, "Too much sCELO. Can not add proportional liquidity!"); // from rest of the CELO (i.e. amount_CELO-matched_CELO), we need to convert some amount to // sCELO to keep it proportion to reserve_CELO / reserve_sCELO. // NOTE: calculations and conversions are done in such a way that all sCELO will always be consumed // and rounding errors will apply to CELO itself. It is possible that we will have to throw out 1 or 2 // WEI at most to meet the proportionality. toConvert_CELO = amount_CELO.sub(matched_CELO) .mul(reserve_sCELO) .div(reserve_sCELO.add(reserve_CELO_as_sCELO)); // Prefer to under-convert, vs to over-convert. This way we make sure that all sCELO is always // consumed when we add liquidity and there can be only 1 or 2 celoWEI left over. return toConvert_CELO > 0 ? toConvert_CELO.sub(1) : 0; } /// @notice returns Ubeswap CELO<->sCELO pool reserves. /// @return reserve_CELO amount of CELO in the pool. /// @return reserve_sCELO amount of sCELO in the pool. function ubeGetReserves() public view returns (uint256 reserve_CELO, uint256 reserve_sCELO) { (uint256 reserve0, uint256 reserve1, ) = ubePair.getReserves(); return (ubePair.token0() == address(CELO)) ? (reserve0, reserve1) : (reserve1, reserve0); } /// @dev copied from UniswapV2Library code. function ubeGetAmountOut( uint amountIn, uint reserveIn, uint reserveOut) internal pure returns (uint amountOut) { require(amountIn > 0, 'GetAmount: INSUFFICIENT_INPUT_AMOUNT'); require(reserveIn > 0 && reserveOut > 0, 'GetAmount: INSUFFICIENT_LIQUIDITY'); uint amountInWithFee = amountIn.mul(997); uint numerator = amountInWithFee.mul(reserveOut); uint denominator = reserveIn.mul(1000).add(amountInWithFee); amountOut = numerator / denominator; } }
ISavingsCELO.sol
//SPDX-License-Identifier: MIT pragma solidity 0.6.8; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; interface ISavingsCELO is IERC20 { function deposit() external payable returns (uint256); function savingsToCELO(uint256 savingsAmount) external view returns (uint256); function celoToSavings(uint256 celoAmount) external view returns (uint256); }
IUniswapV2.sol
//SPDX-License-Identifier: MIT pragma solidity 0.6.8; interface IUniswapV2Factory { 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; } interface IUniswapV2Router { function factory() 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 removeLiquidity( address tokenA, address tokenB, uint liquidity, uint amountAMin, uint amountBMin, address to, uint deadline ) external returns (uint amountA, uint amountB); 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 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 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); function swapExactTokensForTokensSupportingFeeOnTransferTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline ) external; function pairFor(address tokenA, address tokenB) external view returns (address); } interface IUniswapV2Pair { 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; }
SafeMath.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.6.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction overflow"); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } /** * @dev Returns the integer division of two unsigned integers. Reverts with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, "SafeMath: modulo by zero"); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } }
IERC20.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.6.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_savingsCELO","internalType":"address"},{"type":"address","name":"_CELO","internalType":"address"},{"type":"address","name":"_ubeRouter","internalType":"address"}]},{"type":"event","name":"AddedLiquidity","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"uint256","name":"celoAmount","internalType":"uint256","indexed":false},{"type":"uint256","name":"savingsAmount","internalType":"uint256","indexed":false},{"type":"uint256","name":"liquidity","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Deposited","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"uint256","name":"celoAmount","internalType":"uint256","indexed":false},{"type":"uint256","name":"savingsAmount","internalType":"uint256","indexed":false},{"type":"bool","name":"direct","internalType":"bool","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IERC20"}],"name":"CELO","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"addedLiquidity","internalType":"uint256"}],"name":"addLiquidity","inputs":[{"type":"uint256","name":"amount_CELO","internalType":"uint256"},{"type":"uint256","name":"amount_sCELO","internalType":"uint256"},{"type":"uint256","name":"maxReserveRatio","internalType":"uint256"}]},{"type":"function","stateMutability":"payable","outputs":[{"type":"uint256","name":"received_sCELO","internalType":"uint256"}],"name":"deposit","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract ISavingsCELO"}],"name":"savingsCELO","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"reserve_CELO","internalType":"uint256"},{"type":"uint256","name":"reserve_sCELO","internalType":"uint256"}],"name":"ubeGetReserves","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IUniswapV2Pair"}],"name":"ubePair","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IUniswapV2Router"}],"name":"ubeRouter","inputs":[]}]
Contract Creation Code
0x60806040523480156200001157600080fd5b50604051620024af380380620024af833981810160405260608110156200003757600080fd5b81019080805190602001909291908051906020019092919080519060200190929190505050826000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c45a01556040518163ffffffff1660e01b815260040160206040518083038186803b1580156200018957600080fd5b505afa1580156200019e573d6000803e3d6000fd5b505050506040513d6020811015620001b557600080fd5b8101908080519060200190929190505050905060008173ffffffffffffffffffffffffffffffffffffffff1663e6a4390586866040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060206040518083038186803b1580156200027c57600080fd5b505afa15801562000291573d6000803e3d6000fd5b505050506040513d6020811015620002a857600080fd5b81019080805190602001909291905050509050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415620003e5578173ffffffffffffffffffffffffffffffffffffffff1663c9c6539686866040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200192505050602060405180830381600087803b158015620003a557600080fd5b505af1158015620003ba573d6000803e3d6000fd5b505050506040513d6020811015620003d157600080fd5b810190808051906020019092919050505090505b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141562000489576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f556265737761702070616972206d75737420657869737421000000000000000081525060200191505060405180910390fd5b80600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050505050611fd080620004df6000396000f3fe6080604052600436106100705760003560e01c8063aae5879b1161004e578063aae5879b14610161578063b5a79bea146101b8578063d0e30db01461020f578063f60e673e1461022d57610070565b8063194b5d9614610075578063422f1043146100a7578063681088431461010a575b600080fd5b34801561008157600080fd5b5061008a610284565b604051808381526020018281526020019250505060405180910390f35b3480156100b357600080fd5b506100f4600480360360608110156100ca57600080fd5b81019080803590602001909291908035906020019092919080359060200190929190505050610471565b6040518082815260200191505060405180910390f35b34801561011657600080fd5b5061011f610da6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561016d57600080fd5b50610176610dcc565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156101c457600080fd5b506101cd610df1565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610217610e17565b6040518082815260200191505060405180910390f35b34801561023957600080fd5b506102426115fe565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b600080600080600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b815260040160606040518083038186803b1580156102f257600080fd5b505afa158015610306573d6000803e3d6000fd5b505050506040513d606081101561031c57600080fd5b81019080805190602001909291908051906020019092919080519060200190929190505050506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff169150600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b15801561040757600080fd5b505afa15801561041b573d6000803e3d6000fd5b505050506040513d602081101561043157600080fd5b810190808051906020019092919050505073ffffffffffffffffffffffffffffffffffffffff1614610464578082610467565b81815b9350935050509091565b60008060008585915091506000610489878787611624565b90506000809050600088111561062457600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd33308b6040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050602060405180830381600087803b15801561057657600080fd5b505af115801561058a573d6000803e3d6000fd5b505050506040513d60208110156105a057600080fd5b8101908080519060200190929190505050610623576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f43454c4f207472616e7366657246726f6d206661696c6564210000000000000081525060200191505060405180910390fd5b5b60008711156107b7576000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd33308a6040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050602060405180830381600087803b15801561070957600080fd5b505af115801561071d573d6000803e3d6000fd5b505050506040513d602081101561073357600080fd5b81019080805190602001909291905050506107b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f7343454c4f207472616e7366657246726f6d206661696c65642100000000000081525060200191505060405180910390fd5b5b6000821115610892576000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d0e30db0836040518263ffffffff1660e01b81526004016020604051808303818588803b15801561082957600080fd5b505af115801561083d573d6000803e3d6000fd5b50505050506040513d602081101561085457600080fd5b8101908080519060200190929190505050905061087a81886119dd90919063ffffffff16565b965061088f8289611a6590919063ffffffff16565b97505b60008811156109f757600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663095ea7b3600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168a6040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b15801561096657600080fd5b505af115801561097a573d6000803e3d6000fd5b505050506040513d602081101561099057600080fd5b81019080805190602001909291905050506109f6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180611e9b6022913960400191505060405180910390fd5b5b6000871115610b5b576000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663095ea7b3600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16896040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b158015610aca57600080fd5b505af1158015610ade573d6000803e3d6000fd5b505050506040513d6020811015610af457600080fd5b8101908080519060200190929190505050610b5a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180611ebd6023913960400191505060405180910390fd5b5b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e8e33700600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff168b8b610bf460058f611a6590919063ffffffff16565b8d33426040518963ffffffff1660e01b8152600401808973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018781526020018681526020018581526020018481526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200198505050505050505050606060405180830381600087803b158015610ce257600080fd5b505af1158015610cf6573d6000803e3d6000fd5b505050506040513d6060811015610d0c57600080fd5b810190808051906020019092919080519060200190929190805190602001909291905050509091509050809550503373ffffffffffffffffffffffffffffffffffffffff167f36da66c740aab664153746bd8cf849e92c33663cc5c2705e2a3501c66fbd3dbe85858860405180848152602001838152602001828152602001935050505060405180910390a2849450505050509392505050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000806000610e24610284565b91509150600080831480610e385750600082145b610e4c57610e47348484611aaf565b610e4f565b60005b905060008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635cefc85e346040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610ec557600080fd5b505afa158015610ed9573d6000803e3d6000fd5b505050506040513d6020811015610eef57600080fd5b810190808051906020019092919050505090506000828210610fc557600190506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d0e30db0346040518263ffffffff1660e01b81526004016020604051808303818588803b158015610f7857600080fd5b505af1158015610f8c573d6000803e3d6000fd5b50505050506040513d6020811015610fa357600080fd5b8101908080519060200190929190505050955081861015610fc057fe5b61143c565b600090506060600267ffffffffffffffff81118015610fe357600080fd5b506040519080825280602002602001820160405280156110125781602001602082028036833780820191505090505b509050600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168160008151811061104557fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff16816001815181106110ae57fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663095ea7b3600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16346040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b1580156111b357600080fd5b505af11580156111c7573d6000803e3d6000fd5b505050506040513d60208110156111dd57600080fd5b8101908080519060200190929190505050611243576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180611e9b6022913960400191505060405180910390fd5b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166338ed173934868430426040518663ffffffff1660e01b815260040180868152602001858152602001806020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001838152602001828103825285818151815260200191508051906020019060200280838360005b8381101561131c578082015181840152602081019050611301565b505050509050019650505050505050600060405180830381600087803b15801561134557600080fd5b505af1158015611359573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250602081101561138357600080fd5b81019080805160405193929190846401000000008211156113a357600080fd5b838201915060208201858111156113b957600080fd5b82518660208202830111640100000000821117156113d657600080fd5b8083526020830192505050908051906020019060200280838360005b8381101561140d5780820151818401526020810190506113f2565b5050505090500160405250505060018151811061142657fe5b602002602001015196508387101561143a57fe5b505b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb33886040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b1580156114e457600080fd5b505af11580156114f8573d6000803e3d6000fd5b505050506040513d602081101561150e57600080fd5b8101908080519060200190929190505050611591576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f7343454c4f207472616e73666572206661696c6564210000000000000000000081525060200191505060405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff167f65e6f89b6907d6277741ee4ccbc4ae260163a17f16bbb55b5344dff064867c403488846040518084815260200183815260200182151515158152602001935050505060405180910390a2859550505050505090565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000806000611631610284565b915091506000821480156116455750600081145b156116ff57600191506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635cefc85e60016040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b1580156116c157600080fd5b505afa1580156116d5573d6000803e3d6000fd5b505050506040513d60208110156116eb57600080fd5b810190808051906020019092919050505090505b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635cefc85e846040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561177357600080fd5b505afa158015611787573d6000803e3d6000fd5b505050506040513d602081101561179d57600080fd5b810190808051906020019092919050505090506117cb670de0b6b3a764000082611bdf90919063ffffffff16565b6117de8684611bdf90919063ffffffff16565b1015611835576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526044815260200180611e576044913960600191505060405180910390fd5b611850670de0b6b3a764000083611bdf90919063ffffffff16565b6118638683611bdf90919063ffffffff16565b10156118ba576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526043815260200180611f016043913960600191505060405180910390fd5b6000611906836118f86118d7600187611a6590919063ffffffff16565b6118ea888c611bdf90919063ffffffff16565b6119dd90919063ffffffff16565b611c6590919063ffffffff16565b905087811115611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526033815260200180611f446033913960400191505060405180910390fd5b6119aa61197783856119dd90919063ffffffff16565b61199c8561198e858d611a6590919063ffffffff16565b611bdf90919063ffffffff16565b611c6590919063ffffffff16565b9450600085116119bb5760006119d0565b6119cf600186611a6590919063ffffffff16565b5b9450505050509392505050565b600080828401905083811015611a5b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b6000611aa783836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250611caf565b905092915050565b6000808411611b09576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526024815260200180611f776024913960400191505060405180910390fd5b600083118015611b195750600082115b611b6e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180611e366021913960400191505060405180910390fd5b6000611b856103e586611bdf90919063ffffffff16565b90506000611b9c8483611bdf90919063ffffffff16565b90506000611bc783611bb96103e889611bdf90919063ffffffff16565b6119dd90919063ffffffff16565b9050808281611bd257fe5b0493505050509392505050565b600080831415611bf25760009050611c5f565b6000828402905082848281611c0357fe5b0414611c5a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180611ee06021913960400191505060405180910390fd5b809150505b92915050565b6000611ca783836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250611d6f565b905092915050565b6000838311158290611d5c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611d21578082015181840152602081019050611d06565b50505050905090810190601f168015611d4e5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b60008083118290611e1b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611de0578082015181840152602081019050611dc5565b50505050905090810190601f168015611e0d5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838581611e2757fe5b04905080915050939250505056fe476574416d6f756e743a20494e53554646494349454e545f4c4951554944495459546f6f206c6974746c65207343454c4f20696e20746865206c6971756469747920706f6f6c2e20416464696e67206c6971756964697479206973206e6f7420736166652143454c4f20617070726f7665206661696c656420666f7220756265526f75746572217343454c4f20617070726f7665206661696c656420666f7220756265526f7574657221536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77546f6f206c6974746c652043454c4f20696e20746865206c6971756469747920706f6f6c2e20416464696e67206c6971756964697479206973206e6f74207361666521546f6f206d756368207343454c4f2e2043616e206e6f74206164642070726f706f7274696f6e616c206c697175696469747921476574416d6f756e743a20494e53554646494349454e545f494e5055545f414d4f554e54a264697066735822122057d76cf93181454237fa4d4723e55053261fb1994f3f1169e7084ec1699e249b64736f6c634300060800330000000000000000000000002879bfd5e7c4ef331384e908aaa3bd3014b703fa000000000000000000000000471ece3750da237f93b8e339c536989b8978a438000000000000000000000000e3d8bd6aed4f159bc8000a9cd47cffdb95f96121
Deployed ByteCode
0x6080604052600436106100705760003560e01c8063aae5879b1161004e578063aae5879b14610161578063b5a79bea146101b8578063d0e30db01461020f578063f60e673e1461022d57610070565b8063194b5d9614610075578063422f1043146100a7578063681088431461010a575b600080fd5b34801561008157600080fd5b5061008a610284565b604051808381526020018281526020019250505060405180910390f35b3480156100b357600080fd5b506100f4600480360360608110156100ca57600080fd5b81019080803590602001909291908035906020019092919080359060200190929190505050610471565b6040518082815260200191505060405180910390f35b34801561011657600080fd5b5061011f610da6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561016d57600080fd5b50610176610dcc565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156101c457600080fd5b506101cd610df1565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610217610e17565b6040518082815260200191505060405180910390f35b34801561023957600080fd5b506102426115fe565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b600080600080600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b815260040160606040518083038186803b1580156102f257600080fd5b505afa158015610306573d6000803e3d6000fd5b505050506040513d606081101561031c57600080fd5b81019080805190602001909291908051906020019092919080519060200190929190505050506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff169150600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b15801561040757600080fd5b505afa15801561041b573d6000803e3d6000fd5b505050506040513d602081101561043157600080fd5b810190808051906020019092919050505073ffffffffffffffffffffffffffffffffffffffff1614610464578082610467565b81815b9350935050509091565b60008060008585915091506000610489878787611624565b90506000809050600088111561062457600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd33308b6040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050602060405180830381600087803b15801561057657600080fd5b505af115801561058a573d6000803e3d6000fd5b505050506040513d60208110156105a057600080fd5b8101908080519060200190929190505050610623576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f43454c4f207472616e7366657246726f6d206661696c6564210000000000000081525060200191505060405180910390fd5b5b60008711156107b7576000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd33308a6040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050602060405180830381600087803b15801561070957600080fd5b505af115801561071d573d6000803e3d6000fd5b505050506040513d602081101561073357600080fd5b81019080805190602001909291905050506107b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f7343454c4f207472616e7366657246726f6d206661696c65642100000000000081525060200191505060405180910390fd5b5b6000821115610892576000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d0e30db0836040518263ffffffff1660e01b81526004016020604051808303818588803b15801561082957600080fd5b505af115801561083d573d6000803e3d6000fd5b50505050506040513d602081101561085457600080fd5b8101908080519060200190929190505050905061087a81886119dd90919063ffffffff16565b965061088f8289611a6590919063ffffffff16565b97505b60008811156109f757600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663095ea7b3600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168a6040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b15801561096657600080fd5b505af115801561097a573d6000803e3d6000fd5b505050506040513d602081101561099057600080fd5b81019080805190602001909291905050506109f6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180611e9b6022913960400191505060405180910390fd5b5b6000871115610b5b576000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663095ea7b3600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16896040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b158015610aca57600080fd5b505af1158015610ade573d6000803e3d6000fd5b505050506040513d6020811015610af457600080fd5b8101908080519060200190929190505050610b5a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180611ebd6023913960400191505060405180910390fd5b5b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e8e33700600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff168b8b610bf460058f611a6590919063ffffffff16565b8d33426040518963ffffffff1660e01b8152600401808973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018781526020018681526020018581526020018481526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200198505050505050505050606060405180830381600087803b158015610ce257600080fd5b505af1158015610cf6573d6000803e3d6000fd5b505050506040513d6060811015610d0c57600080fd5b810190808051906020019092919080519060200190929190805190602001909291905050509091509050809550503373ffffffffffffffffffffffffffffffffffffffff167f36da66c740aab664153746bd8cf849e92c33663cc5c2705e2a3501c66fbd3dbe85858860405180848152602001838152602001828152602001935050505060405180910390a2849450505050509392505050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000806000610e24610284565b91509150600080831480610e385750600082145b610e4c57610e47348484611aaf565b610e4f565b60005b905060008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635cefc85e346040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015610ec557600080fd5b505afa158015610ed9573d6000803e3d6000fd5b505050506040513d6020811015610eef57600080fd5b810190808051906020019092919050505090506000828210610fc557600190506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d0e30db0346040518263ffffffff1660e01b81526004016020604051808303818588803b158015610f7857600080fd5b505af1158015610f8c573d6000803e3d6000fd5b50505050506040513d6020811015610fa357600080fd5b8101908080519060200190929190505050955081861015610fc057fe5b61143c565b600090506060600267ffffffffffffffff81118015610fe357600080fd5b506040519080825280602002602001820160405280156110125781602001602082028036833780820191505090505b509050600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168160008151811061104557fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff16816001815181106110ae57fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663095ea7b3600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16346040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b1580156111b357600080fd5b505af11580156111c7573d6000803e3d6000fd5b505050506040513d60208110156111dd57600080fd5b8101908080519060200190929190505050611243576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180611e9b6022913960400191505060405180910390fd5b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166338ed173934868430426040518663ffffffff1660e01b815260040180868152602001858152602001806020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001838152602001828103825285818151815260200191508051906020019060200280838360005b8381101561131c578082015181840152602081019050611301565b505050509050019650505050505050600060405180830381600087803b15801561134557600080fd5b505af1158015611359573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250602081101561138357600080fd5b81019080805160405193929190846401000000008211156113a357600080fd5b838201915060208201858111156113b957600080fd5b82518660208202830111640100000000821117156113d657600080fd5b8083526020830192505050908051906020019060200280838360005b8381101561140d5780820151818401526020810190506113f2565b5050505090500160405250505060018151811061142657fe5b602002602001015196508387101561143a57fe5b505b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb33886040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b1580156114e457600080fd5b505af11580156114f8573d6000803e3d6000fd5b505050506040513d602081101561150e57600080fd5b8101908080519060200190929190505050611591576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f7343454c4f207472616e73666572206661696c6564210000000000000000000081525060200191505060405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff167f65e6f89b6907d6277741ee4ccbc4ae260163a17f16bbb55b5344dff064867c403488846040518084815260200183815260200182151515158152602001935050505060405180910390a2859550505050505090565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000806000611631610284565b915091506000821480156116455750600081145b156116ff57600191506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635cefc85e60016040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b1580156116c157600080fd5b505afa1580156116d5573d6000803e3d6000fd5b505050506040513d60208110156116eb57600080fd5b810190808051906020019092919050505090505b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635cefc85e846040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561177357600080fd5b505afa158015611787573d6000803e3d6000fd5b505050506040513d602081101561179d57600080fd5b810190808051906020019092919050505090506117cb670de0b6b3a764000082611bdf90919063ffffffff16565b6117de8684611bdf90919063ffffffff16565b1015611835576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526044815260200180611e576044913960600191505060405180910390fd5b611850670de0b6b3a764000083611bdf90919063ffffffff16565b6118638683611bdf90919063ffffffff16565b10156118ba576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526043815260200180611f016043913960600191505060405180910390fd5b6000611906836118f86118d7600187611a6590919063ffffffff16565b6118ea888c611bdf90919063ffffffff16565b6119dd90919063ffffffff16565b611c6590919063ffffffff16565b905087811115611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526033815260200180611f446033913960400191505060405180910390fd5b6119aa61197783856119dd90919063ffffffff16565b61199c8561198e858d611a6590919063ffffffff16565b611bdf90919063ffffffff16565b611c6590919063ffffffff16565b9450600085116119bb5760006119d0565b6119cf600186611a6590919063ffffffff16565b5b9450505050509392505050565b600080828401905083811015611a5b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b6000611aa783836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250611caf565b905092915050565b6000808411611b09576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526024815260200180611f776024913960400191505060405180910390fd5b600083118015611b195750600082115b611b6e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180611e366021913960400191505060405180910390fd5b6000611b856103e586611bdf90919063ffffffff16565b90506000611b9c8483611bdf90919063ffffffff16565b90506000611bc783611bb96103e889611bdf90919063ffffffff16565b6119dd90919063ffffffff16565b9050808281611bd257fe5b0493505050509392505050565b600080831415611bf25760009050611c5f565b6000828402905082848281611c0357fe5b0414611c5a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180611ee06021913960400191505060405180910390fd5b809150505b92915050565b6000611ca783836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250611d6f565b905092915050565b6000838311158290611d5c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611d21578082015181840152602081019050611d06565b50505050905090810190601f168015611d4e5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b60008083118290611e1b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611de0578082015181840152602081019050611dc5565b50505050905090810190601f168015611e0d5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838581611e2757fe5b04905080915050939250505056fe476574416d6f756e743a20494e53554646494349454e545f4c4951554944495459546f6f206c6974746c65207343454c4f20696e20746865206c6971756469747920706f6f6c2e20416464696e67206c6971756964697479206973206e6f7420736166652143454c4f20617070726f7665206661696c656420666f7220756265526f75746572217343454c4f20617070726f7665206661696c656420666f7220756265526f7574657221536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77546f6f206c6974746c652043454c4f20696e20746865206c6971756469747920706f6f6c2e20416464696e67206c6971756964697479206973206e6f74207361666521546f6f206d756368207343454c4f2e2043616e206e6f74206164642070726f706f7274696f6e616c206c697175696469747921476574416d6f756e743a20494e53554646494349454e545f494e5055545f414d4f554e54a264697066735822122057d76cf93181454237fa4d4723e55053261fb1994f3f1169e7084ec1699e249b64736f6c63430006080033