Address Details
contract
0x90eD9a893bC7be80F2D0E68650a8780A4E7373a5
- Contract Name
- FeeHandler
- Creator
- 0xf3eb91–a79239 at 0x0d0750–65f93f
- Balance
- 0 CELO ( )
- Locked CELO Balance
- 0.00 CELO
- Voting CELO Balance
- 0.00 CELO
- Pending Unlocked Gold
- 0.00 CELO
- Tokens
-
Fetching tokens...
- Transactions
- 0 Transactions
- Transfers
- 0 Transfers
- Gas Used
- Fetching gas used...
- Last Balance Update
- 28270132
This contract has been verified via Sourcify.
View contract in Sourcify repository
- Contract name:
- FeeHandler
- Optimization enabled
- false
- Compiler version
- v0.5.13+commit.5b0b510c
- EVM Version
- istanbul
- Verified at
- 2024-01-05T17:23:42.091991Z
project:/contracts/common/FeeHandler.sol
pragma solidity ^0.5.13; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; import "openzeppelin-solidity/contracts/math/Math.sol"; import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; import "openzeppelin-solidity/contracts/utils/EnumerableSet.sol"; import "./UsingRegistry.sol"; import "../common/Freezable.sol"; import "../common/FixidityLib.sol"; import "../common/Initializable.sol"; import "../common/interfaces/IFeeHandler.sol"; import "../common/interfaces/IFeeHandlerSeller.sol"; // TODO move to IStableToken when it adds method getExchangeRegistryId import "./interfaces/IStableTokenMento.sol"; import "../common/interfaces/ICeloVersionedContract.sol"; import "../common/interfaces/ICeloToken.sol"; import "../stability/interfaces/ISortedOracles.sol"; // Using the minimal required signatures in the interfaces so more contracts could be compatible import "../common/libraries/ReentrancyGuard.sol"; // An implementation of FeeHandler as described in CIP-52 // See https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0052.md contract FeeHandler is Ownable, Initializable, UsingRegistry, ICeloVersionedContract, Freezable, IFeeHandler, ReentrancyGuard { using SafeMath for uint256; using FixidityLib for FixidityLib.Fraction; using EnumerableSet for EnumerableSet.AddressSet; uint256 public constant FIXED1_UINT = 1000000000000000000000000; // TODO move to FIX and add check // Min units that can be burned uint256 public constant MIN_BURN = 200; // last day the daily limits were updated uint256 public lastLimitDay; FixidityLib.Fraction public burnFraction; // 80% address public feeBeneficiary; uint256 public celoToBeBurned; // This mapping can not be public because it contains a FixidityLib.Fraction // and that'd be only supported with experimental features in this // compiler version mapping(address => TokenState) private tokenStates; struct TokenState { address handler; FixidityLib.Fraction maxSlippage; // Max amounts that can be burned in a day for a token uint256 dailySellLimit; // Max amounts that can be burned today for a token uint256 currentDaySellLimit; uint256 toDistribute; // Historical amounts burned by this contract uint256 pastBurn; } EnumerableSet.AddressSet private activeTokens; event SoldAndBurnedToken(address token, uint256 value); event DailyLimitSet(address tokenAddress, uint256 newLimit); event DailyLimitHit(address token, uint256 burning); event MaxSlippageSet(address token, uint256 maxSlippage); event DailySellLimitUpdated(uint256 amount); event FeeBeneficiarySet(address newBeneficiary); event BurnFractionSet(uint256 fraction); event TokenAdded(address tokenAddress, address handlerAddress); event TokenRemoved(address tokenAddress); /** * @notice Sets initialized == true on implementation contracts. * @param test Set to true to skip implementation initialisation. */ constructor(bool test) public Initializable(test) {} /** * @notice Used in place of the constructor to allow the contract to be upgradable via proxy. */ function initialize( address _registryAddress, address newFeeBeneficiary, uint256 newBurnFraction, address[] calldata tokens, address[] calldata handlers, uint256[] calldata newLimits, uint256[] calldata newMaxSlippages ) external initializer { require(tokens.length == handlers.length, "handlers length should match tokens length"); require(tokens.length == newLimits.length, "limits length should match tokens length"); require( tokens.length == newMaxSlippages.length, "maxSlippage length should match tokens length" ); _transferOwnership(msg.sender); setRegistry(_registryAddress); _setFeeBeneficiary(newFeeBeneficiary); _setBurnFraction(newBurnFraction); for (uint256 i = 0; i < tokens.length; i++) { _addToken(tokens[i], handlers[i]); _setDailySellLimit(tokens[i], newLimits[i]); _setMaxSplippage(tokens[i], newMaxSlippages[i]); } } // Without this the contract cant receive Celo as native transfer function() external payable {} /** @dev Returns the handler address for the specified token. @param tokenAddress The address of the token for which to return the handler. @return The address of the handler contract for the specified token. */ function getTokenHandler(address tokenAddress) external view returns (address) { return tokenStates[tokenAddress].handler; } /** @dev Returns a boolean indicating whether the specified token is active or not. @param tokenAddress The address of the token for which to retrieve the active status. @return A boolean representing the active status of the specified token. */ function getTokenActive(address tokenAddress) external view returns (bool) { return activeTokens.contains(tokenAddress); } /** @dev Returns the maximum slippage percentage for the specified token. @param tokenAddress The address of the token for which to retrieve the maximum slippage percentage. @return The maximum slippage percentage as a uint256 value. */ function getTokenMaxSlippage(address tokenAddress) external view returns (uint256) { return FixidityLib.unwrap(tokenStates[tokenAddress].maxSlippage); } /** @dev Returns the daily burn limit for the specified token. @param tokenAddress The address of the token for which to retrieve the daily burn limit. @return The daily burn limit as a uint256 value. */ function getTokenDailySellLimit(address tokenAddress) external view returns (uint256) { return tokenStates[tokenAddress].dailySellLimit; } /** @dev Returns the current daily sell limit for the specified token. @param tokenAddress The address of the token for which to retrieve the current daily limit. @return The current daily limit as a uint256 value. */ function getTokenCurrentDaySellLimit(address tokenAddress) external view returns (uint256) { return tokenStates[tokenAddress].currentDaySellLimit; } /** @dev Returns the amount of tokens available to distribute for the specified token. @param tokenAddress The address of the token for which to retrieve the amount of tokens available to distribute. @return The amount of tokens available to distribute as a uint256 value. */ function getTokenToDistribute(address tokenAddress) external view returns (uint256) { return tokenStates[tokenAddress].toDistribute; } function getActiveTokens() public view returns (address[] memory) { return activeTokens.values; } /** @dev Sets the fee beneficiary address to the specified address. @param beneficiary The address to set as the fee beneficiary. */ function setFeeBeneficiary(address beneficiary) external onlyOwner { return _setFeeBeneficiary(beneficiary); } function _setFeeBeneficiary(address beneficiary) private { feeBeneficiary = beneficiary; emit FeeBeneficiarySet(beneficiary); } /** @dev Sets the burn fraction to the specified value. @param fraction The value to set as the burn fraction. */ function setBurnFraction(uint256 fraction) external onlyOwner { return _setBurnFraction(fraction); } function _setBurnFraction(uint256 newFraction) private { FixidityLib.Fraction memory fraction = FixidityLib.wrap(newFraction); require( FixidityLib.lte(fraction, FixidityLib.fixed1()), "Burn fraction must be less than or equal to 1" ); burnFraction = fraction; emit BurnFractionSet(newFraction); } /** @dev Sets the burn fraction to the specified value. Token has to have a handler set. @param tokenAddress The address of the token to sell */ function sell(address tokenAddress) external { return _sell(tokenAddress); } /** @dev Adds a new token to the contract with the specified token and handler addresses. @param tokenAddress The address of the token to add. @param handlerAddress The address of the handler contract for the specified token. */ function addToken(address tokenAddress, address handlerAddress) external onlyOwner { _addToken(tokenAddress, handlerAddress); } function _addToken(address tokenAddress, address handlerAddress) private { require(handlerAddress != address(0), "Can't set handler to zero"); TokenState storage tokenState = tokenStates[tokenAddress]; tokenState.handler = handlerAddress; activeTokens.add(tokenAddress); emit TokenAdded(tokenAddress, handlerAddress); } /** @notice Allows the owner to activate a specified token. @param tokenAddress The address of the token to be activated. */ function activateToken(address tokenAddress) external onlyOwner { _activateToken(tokenAddress); } function _activateToken(address tokenAddress) private { TokenState storage tokenState = tokenStates[tokenAddress]; require( tokenState.handler != address(0) || tokenAddress == registry.getAddressForOrDie(GOLD_TOKEN_REGISTRY_ID), "Handler has to be set to activate token" ); activeTokens.add(tokenAddress); } /** @dev Deactivates the specified token by marking it as inactive. @param tokenAddress The address of the token to deactivate. */ function deactivateToken(address tokenAddress) external onlyOwner { _deactivateToken(tokenAddress); } function _deactivateToken(address tokenAddress) private { activeTokens.remove(tokenAddress); } /** @notice Allows the owner to set a handler contract for a specified token. @param tokenAddress The address of the token to set the handler for. @param handlerAddress The address of the handler contract to be set. */ function setHandler(address tokenAddress, address handlerAddress) external onlyOwner { _setHandler(tokenAddress, handlerAddress); } function _setHandler(address tokenAddress, address handlerAddress) private { require(handlerAddress != address(0), "Can't set handler to zero, use deactivateToken"); TokenState storage tokenState = tokenStates[tokenAddress]; tokenState.handler = handlerAddress; } function removeToken(address tokenAddress) external onlyOwner { _removeToken(tokenAddress); } function _removeToken(address tokenAddress) private { _deactivateToken(tokenAddress); TokenState storage tokenState = tokenStates[tokenAddress]; tokenState.handler = address(0); emit TokenRemoved(tokenAddress); } function _sell(address tokenAddress) private onlyWhenNotFrozen nonReentrant { IERC20 token = IERC20(tokenAddress); TokenState storage tokenState = tokenStates[tokenAddress]; require(tokenState.handler != address(0), "Handler has to be set to sell token"); require( FixidityLib.unwrap(tokenState.maxSlippage) != 0, "Max slippage has to be set to sell token" ); FixidityLib.Fraction memory balanceToProcess = FixidityLib.newFixed( token.balanceOf(address(this)).sub(tokenState.toDistribute) ); uint256 balanceToBurn = (burnFraction.multiply(balanceToProcess).fromFixed()); tokenState.toDistribute = tokenState.toDistribute.add( balanceToProcess.fromFixed().sub(balanceToBurn) ); // small numbers cause rounding errors and zero case should be skipped if (balanceToBurn < MIN_BURN) { return; } if (dailySellLimitHit(tokenAddress, balanceToBurn)) { // in case the limit is hit, burn the max possible balanceToBurn = tokenState.currentDaySellLimit; emit DailyLimitHit(tokenAddress, balanceToBurn); } token.transfer(tokenState.handler, balanceToBurn); IFeeHandlerSeller handler = IFeeHandlerSeller(tokenState.handler); uint256 celoReceived = handler.sell( tokenAddress, registry.getAddressForOrDie(GOLD_TOKEN_REGISTRY_ID), balanceToBurn, FixidityLib.unwrap(tokenState.maxSlippage) ); celoToBeBurned = celoToBeBurned.add(celoReceived); tokenState.pastBurn = tokenState.pastBurn.add(balanceToBurn); updateLimits(tokenAddress, balanceToBurn); emit SoldAndBurnedToken(tokenAddress, balanceToBurn); } /** @dev Distributes the available tokens for the specified token address to the fee beneficiary. @param tokenAddress The address of the token for which to distribute the available tokens. */ function distribute(address tokenAddress) external { return _distribute(tokenAddress); } function _distribute(address tokenAddress) private onlyWhenNotFrozen nonReentrant { require(feeBeneficiary != address(0), "Can't distribute to the zero address"); IERC20 token = IERC20(tokenAddress); uint256 tokenBalance = token.balanceOf(address(this)); TokenState storage tokenState = tokenStates[tokenAddress]; require( tokenState.handler != address(0) || tokenAddress == registry.getAddressForOrDie(GOLD_TOKEN_REGISTRY_ID), "Handler has to be set to sell token" ); // safty check to avoid a revert due balance uint256 balanceToDistribute = Math.min(tokenBalance, tokenState.toDistribute); if (balanceToDistribute == 0) { // don't distribute with zero balance return; } token.transfer(feeBeneficiary, balanceToDistribute); tokenState.toDistribute = tokenState.toDistribute.sub(balanceToDistribute); } /** * @notice Returns the storage, major, minor, and patch version of the contract. * @return Storage version of the contract. * @return Major version of the contract. * @return Minor version of the contract. * @return Patch version of the contract. */ function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256) { return (1, 1, 0, 0); } /** * @notice Allows owner to set max slippage for a token. * @param token Address of the token to set. * @param newMax New sllipage to set, as Fixidity fraction. */ function setMaxSplippage(address token, uint256 newMax) external onlyOwner { _setMaxSplippage(token, newMax); } function _setMaxSplippage(address token, uint256 newMax) private { TokenState storage tokenState = tokenStates[token]; require(newMax != 0, "Cannot set max slippage to zero"); tokenState.maxSlippage = FixidityLib.wrap(newMax); require( FixidityLib.lte(tokenState.maxSlippage, FixidityLib.fixed1()), "Splippage must be less than or equal to 1" ); emit MaxSlippageSet(token, newMax); } /** * @notice Allows owner to set the daily burn limit for a token. * @param token Address of the token to set. * @param newLimit The new limit to set, in the token units. */ function setDailySellLimit(address token, uint256 newLimit) external onlyOwner { _setDailySellLimit(token, newLimit); } function _setDailySellLimit(address token, uint256 newLimit) private { TokenState storage tokenState = tokenStates[token]; tokenState.dailySellLimit = newLimit; emit DailyLimitSet(token, newLimit); } /** @dev Burns CELO tokens according to burnFraction. */ function burnCelo() external { return _burnCelo(); } /** @dev Distributes the available tokens for all registered tokens to the feeBeneficiary. */ function distributeAll() external { return _distributeAll(); } function _distributeAll() private { for (uint256 i = 0; i < EnumerableSet.length(activeTokens); i++) { address token = activeTokens.get(i); _distribute(token); } // distribute Celo _distribute(registry.getAddressForOrDie(GOLD_TOKEN_REGISTRY_ID)); } /** @dev Distributes the available tokens for all registered tokens to the feeBeneficiary. */ function handleAll() external { return _handleAll(); } function _handleAll() private { for (uint256 i = 0; i < EnumerableSet.length(activeTokens); i++) { // calling _handle would trigger may burn Celo and distributions // that can be just batched at the end address token = activeTokens.get(i); _sell(token); } _distributeAll(); // distributes Celo as well _burnCelo(); } /** @dev Distributes the the token for to the feeBeneficiary. */ function handle(address tokenAddress) external { return _handle(tokenAddress); } function _handle(address tokenAddress) private { // Celo doesn't have to be exchanged for anything if (tokenAddress != registry.getAddressForOrDie(GOLD_TOKEN_REGISTRY_ID)) { _sell(tokenAddress); } _burnCelo(); _distribute(tokenAddress); _distribute(registry.getAddressForOrDie(GOLD_TOKEN_REGISTRY_ID)); } /** * @notice Burns all the Celo balance of this contract. */ function _burnCelo() private { TokenState storage tokenState = tokenStates[registry.getAddressForOrDie( GOLD_TOKEN_REGISTRY_ID )]; ICeloToken celo = ICeloToken(registry.getAddressForOrDie(GOLD_TOKEN_REGISTRY_ID)); uint256 balanceOfCelo = address(this).balance; uint256 balanceToProcess = balanceOfCelo.sub(tokenState.toDistribute).sub(celoToBeBurned); uint256 currentBalanceToBurn = FixidityLib .newFixed(balanceToProcess) .multiply(burnFraction) .fromFixed(); uint256 totalBalanceToBurn = currentBalanceToBurn.add(celoToBeBurned); celo.burn(totalBalanceToBurn); celoToBeBurned = 0; tokenState.toDistribute = tokenState.toDistribute.add( balanceToProcess.sub(currentBalanceToBurn) ); } /** * @param token The address of the token to query. * @return The amount burned for a token. */ function getPastBurnForToken(address token) external view returns (uint256) { return tokenStates[token].pastBurn; } /** * @param token The address of the token to query. * @param amountToBurn The amount of the token to burn. * @return Returns true if burning amountToBurn would exceed the daily limit. */ function dailySellLimitHit(address token, uint256 amountToBurn) public returns (bool) { TokenState storage tokenState = tokenStates[token]; if (tokenState.dailySellLimit == 0) { // if no limit set, assume uncapped return false; } uint256 currentDay = now / 1 days; // Pattern borrowed from Reserve.sol if (currentDay > lastLimitDay) { lastLimitDay = currentDay; tokenState.currentDaySellLimit = tokenState.dailySellLimit; } return amountToBurn >= tokenState.currentDaySellLimit; } /** * @notice Updates the current day limit for a token. * @param token The address of the token to query. * @param amountBurned the amount of the token that was burned. */ function updateLimits(address token, uint256 amountBurned) private { TokenState storage tokenState = tokenStates[token]; if (tokenState.dailySellLimit == 0) { // if no limit set, assume uncapped return; } tokenState.currentDaySellLimit = tokenState.currentDaySellLimit.sub(amountBurned); emit DailySellLimitUpdated(amountBurned); } /** * @notice Allows owner to transfer tokens of this contract. It's meant for governance to trigger use cases not contemplated in this contract. @param token The address of the token to transfer. @param recipient The address of the recipient to transfer the tokens to. @param value The amount of tokens to transfer. @return A boolean indicating whether the transfer was successful or not. */ function transfer(address token, address recipient, uint256 value) external onlyOwner returns (bool) { return IERC20(token).transfer(recipient, value); } }
/openzeppelin-solidity/contracts/GSN/Context.sol
pragma solidity ^0.5.0; /* * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with GSN meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ contract Context { // Empty internal constructor, to prevent people from mistakenly deploying // an instance of this contract, which should be used via inheritance. constructor () internal { } // solhint-disable-previous-line no-empty-blocks function _msgSender() internal view returns (address payable) { return msg.sender; } function _msgData() internal view returns (bytes memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } }
/openzeppelin-solidity/contracts/math/Math.sol
pragma solidity ^0.5.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a >= b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow, so we distribute return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2); } }
/openzeppelin-solidity/contracts/math/SafeMath.sol
pragma solidity ^0.5.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. * * _Available since v2.4.0._ */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } /** * @dev Returns the integer division of two unsigned integers. Reverts with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. * * _Available since v2.4.0._ */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { // Solidity only automatically asserts when dividing by 0 require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, "SafeMath: modulo by zero"); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. * * _Available since v2.4.0._ */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } }
/openzeppelin-solidity/contracts/ownership/Ownable.sol
pragma solidity ^0.5.0; import "../GSN/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor () internal { address msgSender = _msgSender(); _owner = msgSender; emit OwnershipTransferred(address(0), msgSender); } /** * @dev Returns the address of the current owner. */ function owner() public view returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(isOwner(), "Ownable: caller is not the owner"); _; } /** * @dev Returns true if the caller is the current owner. */ function isOwner() public view returns (bool) { return _msgSender() == _owner; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public onlyOwner { emit OwnershipTransferred(_owner, address(0)); _owner = address(0); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public onlyOwner { _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). */ function _transferOwnership(address newOwner) internal { require(newOwner != address(0), "Ownable: new owner is the zero address"); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } }
/openzeppelin-solidity/contracts/token/ERC20/IERC20.sol
pragma solidity ^0.5.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. Does not include * the optional functions; to access them see {ERC20Detailed}. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (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); }
/openzeppelin-solidity/contracts/utils/EnumerableSet.sol
pragma solidity ^0.5.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * As of v2.5.0, only `address` sets are supported. * * Include with `using EnumerableSet for EnumerableSet.AddressSet;`. * * _Available since v2.5.0._ * * @author Alberto Cuesta Cañada */ library EnumerableSet { struct AddressSet { // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping (address => uint256) index; address[] values; } /** * @dev Add a value to a set. O(1). * Returns false if the value was already in the set. */ function add(AddressSet storage set, address value) internal returns (bool) { if (!contains(set, value)){ set.index[value] = set.values.push(value); return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * Returns false if the value was not present in the set. */ function remove(AddressSet storage set, address value) internal returns (bool) { if (contains(set, value)){ uint256 toDeleteIndex = set.index[value] - 1; uint256 lastIndex = set.values.length - 1; // If the element we're deleting is the last one, we can just remove it without doing a swap if (lastIndex != toDeleteIndex) { address lastValue = set.values[lastIndex]; // Move the last value to the index where the deleted value is set.values[toDeleteIndex] = lastValue; // Update the index for the moved value set.index[lastValue] = toDeleteIndex + 1; // All indexes are 1-based } // Delete the index entry for the deleted value delete set.index[value]; // Delete the old entry for the moved value set.values.pop(); return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return set.index[value] != 0; } /** * @dev Returns an array with all values in the set. O(N). * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * WARNING: This function may run out of gas on large sets: use {length} and * {get} instead in these cases. */ function enumerate(AddressSet storage set) internal view returns (address[] memory) { address[] memory output = new address[](set.values.length); for (uint256 i; i < set.values.length; i++){ output[i] = set.values[i]; } return output; } /** * @dev Returns the number of elements on the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return set.values.length; } /** @dev Returns the element stored at position `index` in the set. O(1). * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function get(AddressSet storage set, uint256 index) internal view returns (address) { return set.values[index]; } }
/project:/contracts/common/FixidityLib.sol
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.5.13 <0.9.0; /** * @title FixidityLib * @author Gadi Guy, Alberto Cuesta Canada * @notice This library provides fixed point arithmetic with protection against * overflow. * All operations are done with uint256 and the operands must have been created * with any of the newFrom* functions, which shift the comma digits() to the * right and check for limits, or with wrap() which expects a number already * in the internal representation of a fraction. * When using this library be sure to use maxNewFixed() as the upper limit for * creation of fixed point numbers. * @dev All contained functions are pure and thus marked internal to be inlined * on consuming contracts at compile time for gas efficiency. */ library FixidityLib { struct Fraction { uint256 value; } /** * @notice Number of positions that the comma is shifted to the right. */ function digits() internal pure returns (uint8) { return 24; } uint256 private constant FIXED1_UINT = 1000000000000000000000000; /** * @notice This is 1 in the fixed point units used in this library. * @dev Test fixed1() equals 10^digits() * Hardcoded to 24 digits. */ function fixed1() internal pure returns (Fraction memory) { return Fraction(FIXED1_UINT); } /** * @notice Wrap a uint256 that represents a 24-decimal fraction in a Fraction * struct. * @param x Number that already represents a 24-decimal fraction. * @return A Fraction struct with contents x. */ function wrap(uint256 x) internal pure returns (Fraction memory) { return Fraction(x); } /** * @notice Unwraps the uint256 inside of a Fraction struct. */ function unwrap(Fraction memory x) internal pure returns (uint256) { return x.value; } /** * @notice The amount of decimals lost on each multiplication operand. * @dev Test mulPrecision() equals sqrt(fixed1) */ function mulPrecision() internal pure returns (uint256) { return 1000000000000; } /** * @notice Maximum value that can be converted to fixed point. Optimize for deployment. * @dev * Test maxNewFixed() equals maxUint256() / fixed1() */ function maxNewFixed() internal pure returns (uint256) { return 115792089237316195423570985008687907853269984665640564; } /** * @notice Converts a uint256 to fixed point Fraction * @dev Test newFixed(0) returns 0 * Test newFixed(1) returns fixed1() * Test newFixed(maxNewFixed()) returns maxNewFixed() * fixed1() * Test newFixed(maxNewFixed()+1) fails */ function newFixed(uint256 x) internal pure returns (Fraction memory) { require(x <= maxNewFixed(), "can't create fixidity number larger than maxNewFixed()"); return Fraction(x * FIXED1_UINT); } /** * @notice Converts a uint256 in the fixed point representation of this * library to a non decimal. All decimal digits will be truncated. */ function fromFixed(Fraction memory x) internal pure returns (uint256) { return x.value / FIXED1_UINT; } /** * @notice Converts two uint256 representing a fraction to fixed point units, * equivalent to multiplying dividend and divisor by 10^digits(). * @param numerator numerator must be <= maxNewFixed() * @param denominator denominator must be <= maxNewFixed() and denominator can't be 0 * @dev * Test newFixedFraction(1,0) fails * Test newFixedFraction(0,1) returns 0 * Test newFixedFraction(1,1) returns fixed1() * Test newFixedFraction(1,fixed1()) returns 1 */ function newFixedFraction(uint256 numerator, uint256 denominator) internal pure returns (Fraction memory) { Fraction memory convertedNumerator = newFixed(numerator); Fraction memory convertedDenominator = newFixed(denominator); return divide(convertedNumerator, convertedDenominator); } /** * @notice Returns the integer part of a fixed point number. * @dev * Test integer(0) returns 0 * Test integer(fixed1()) returns fixed1() * Test integer(newFixed(maxNewFixed())) returns maxNewFixed()*fixed1() */ function integer(Fraction memory x) internal pure returns (Fraction memory) { return Fraction((x.value / FIXED1_UINT) * FIXED1_UINT); // Can't overflow } /** * @notice Returns the fractional part of a fixed point number. * In the case of a negative number the fractional is also negative. * @dev * Test fractional(0) returns 0 * Test fractional(fixed1()) returns 0 * Test fractional(fixed1()-1) returns 10^24-1 */ function fractional(Fraction memory x) internal pure returns (Fraction memory) { return Fraction(x.value - (x.value / FIXED1_UINT) * FIXED1_UINT); // Can't overflow } /** * @notice x+y. * @dev The maximum value that can be safely used as an addition operator is defined as * maxFixedAdd = maxUint256()-1 / 2, or * 57896044618658097711785492504343953926634992332820282019728792003956564819967. * Test add(maxFixedAdd,maxFixedAdd) equals maxFixedAdd + maxFixedAdd * Test add(maxFixedAdd+1,maxFixedAdd+1) throws */ function add(Fraction memory x, Fraction memory y) internal pure returns (Fraction memory) { uint256 z = x.value + y.value; require(z >= x.value, "add overflow detected"); return Fraction(z); } /** * @notice x-y. * @dev * Test subtract(6, 10) fails */ function subtract(Fraction memory x, Fraction memory y) internal pure returns (Fraction memory) { require(x.value >= y.value, "substraction underflow detected"); return Fraction(x.value - y.value); } /** * @notice x*y. If any of the operators is higher than the max multiplier value it * might overflow. * @dev The maximum value that can be safely used as a multiplication operator * (maxFixedMul) is calculated as sqrt(maxUint256()*fixed1()), * or 340282366920938463463374607431768211455999999999999 * Test multiply(0,0) returns 0 * Test multiply(maxFixedMul,0) returns 0 * Test multiply(0,maxFixedMul) returns 0 * Test multiply(fixed1()/mulPrecision(),fixed1()*mulPrecision()) returns fixed1() * Test multiply(maxFixedMul,maxFixedMul) is around maxUint256() * Test multiply(maxFixedMul+1,maxFixedMul+1) fails */ function multiply(Fraction memory x, Fraction memory y) internal pure returns (Fraction memory) { if (x.value == 0 || y.value == 0) return Fraction(0); if (y.value == FIXED1_UINT) return x; if (x.value == FIXED1_UINT) return y; // Separate into integer and fractional parts // x = x1 + x2, y = y1 + y2 uint256 x1 = integer(x).value / FIXED1_UINT; uint256 x2 = fractional(x).value; uint256 y1 = integer(y).value / FIXED1_UINT; uint256 y2 = fractional(y).value; // (x1 + x2) * (y1 + y2) = (x1 * y1) + (x1 * y2) + (x2 * y1) + (x2 * y2) uint256 x1y1 = x1 * y1; if (x1 != 0) require(x1y1 / x1 == y1, "overflow x1y1 detected"); // x1y1 needs to be multiplied back by fixed1 // solium-disable-next-line mixedcase uint256 fixed_x1y1 = x1y1 * FIXED1_UINT; if (x1y1 != 0) require(fixed_x1y1 / x1y1 == FIXED1_UINT, "overflow x1y1 * fixed1 detected"); x1y1 = fixed_x1y1; uint256 x2y1 = x2 * y1; if (x2 != 0) require(x2y1 / x2 == y1, "overflow x2y1 detected"); uint256 x1y2 = x1 * y2; if (x1 != 0) require(x1y2 / x1 == y2, "overflow x1y2 detected"); x2 = x2 / mulPrecision(); y2 = y2 / mulPrecision(); uint256 x2y2 = x2 * y2; if (x2 != 0) require(x2y2 / x2 == y2, "overflow x2y2 detected"); // result = fixed1() * x1 * y1 + x1 * y2 + x2 * y1 + x2 * y2 / fixed1(); Fraction memory result = Fraction(x1y1); result = add(result, Fraction(x2y1)); // Add checks for overflow result = add(result, Fraction(x1y2)); // Add checks for overflow result = add(result, Fraction(x2y2)); // Add checks for overflow return result; } /** * @notice 1/x * @dev * Test reciprocal(0) fails * Test reciprocal(fixed1()) returns fixed1() * Test reciprocal(fixed1()*fixed1()) returns 1 // Testing how the fractional is truncated * Test reciprocal(1+fixed1()*fixed1()) returns 0 // Testing how the fractional is truncated * Test reciprocal(newFixedFraction(1, 1e24)) returns newFixed(1e24) */ function reciprocal(Fraction memory x) internal pure returns (Fraction memory) { require(x.value != 0, "can't call reciprocal(0)"); return Fraction((FIXED1_UINT * FIXED1_UINT) / x.value); // Can't overflow } /** * @notice x/y. If the dividend is higher than the max dividend value, it * might overflow. You can use multiply(x,reciprocal(y)) instead. * @dev The maximum value that can be safely used as a dividend (maxNewFixed) is defined as * divide(maxNewFixed,newFixedFraction(1,fixed1())) is around maxUint256(). * This yields the value 115792089237316195423570985008687907853269984665640564. * Test maxNewFixed equals maxUint256()/fixed1() * Test divide(maxNewFixed,1) equals maxNewFixed*(fixed1) * Test divide(maxNewFixed+1,multiply(mulPrecision(),mulPrecision())) throws * Test divide(fixed1(),0) fails * Test divide(maxNewFixed,1) = maxNewFixed*(10^digits()) * Test divide(maxNewFixed+1,1) throws */ function divide(Fraction memory x, Fraction memory y) internal pure returns (Fraction memory) { require(y.value != 0, "can't divide by 0"); uint256 X = x.value * FIXED1_UINT; require(X / FIXED1_UINT == x.value, "overflow at divide"); return Fraction(X / y.value); } /** * @notice x > y */ function gt(Fraction memory x, Fraction memory y) internal pure returns (bool) { return x.value > y.value; } /** * @notice x >= y */ function gte(Fraction memory x, Fraction memory y) internal pure returns (bool) { return x.value >= y.value; } /** * @notice x < y */ function lt(Fraction memory x, Fraction memory y) internal pure returns (bool) { return x.value < y.value; } /** * @notice x <= y */ function lte(Fraction memory x, Fraction memory y) internal pure returns (bool) { return x.value <= y.value; } /** * @notice x == y */ function equals(Fraction memory x, Fraction memory y) internal pure returns (bool) { return x.value == y.value; } /** * @notice x <= 1 */ function isProperFraction(Fraction memory x) internal pure returns (bool) { return lte(x, fixed1()); } }
/project:/contracts/common/Freezable.sol
pragma solidity ^0.5.13; import "./UsingRegistry.sol"; contract Freezable is UsingRegistry { // onlyWhenNotFrozen functions can only be called when `frozen` is false, otherwise they will // revert. modifier onlyWhenNotFrozen() { require(!getFreezer().isFrozen(address(this)), "can't call when contract is frozen"); _; } }
/project:/contracts/common/Initializable.sol
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.5.13 <0.9.0; contract Initializable { bool public initialized; constructor(bool testingDeployment) public { if (!testingDeployment) { initialized = true; } } modifier initializer() { require(!initialized, "contract already initialized"); initialized = true; _; } }
/project:/contracts/common/UsingRegistry.sol
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity ^0.5.13; import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; import "./interfaces/IAccounts.sol"; import "./interfaces/IFeeCurrencyWhitelist.sol"; import "./interfaces/IFreezer.sol"; import "./interfaces/IRegistry.sol"; import "../governance/interfaces/IElection.sol"; import "../governance/interfaces/IGovernance.sol"; import "../governance/interfaces/ILockedGold.sol"; import "../governance/interfaces/IValidators.sol"; import "../identity/interfaces/IRandom.sol"; import "../identity/interfaces/IAttestations.sol"; import "../../lib/mento-core/contracts/interfaces/IExchange.sol"; import "../../lib/mento-core/contracts/interfaces/IReserve.sol"; import "../../lib/mento-core/contracts/interfaces/IStableToken.sol"; import "../stability/interfaces/ISortedOracles.sol"; contract UsingRegistry is Ownable { event RegistrySet(address indexed registryAddress); // solhint-disable state-visibility bytes32 constant ACCOUNTS_REGISTRY_ID = keccak256(abi.encodePacked("Accounts")); bytes32 constant ATTESTATIONS_REGISTRY_ID = keccak256(abi.encodePacked("Attestations")); bytes32 constant DOWNTIME_SLASHER_REGISTRY_ID = keccak256(abi.encodePacked("DowntimeSlasher")); bytes32 constant DOUBLE_SIGNING_SLASHER_REGISTRY_ID = keccak256( abi.encodePacked("DoubleSigningSlasher") ); bytes32 constant ELECTION_REGISTRY_ID = keccak256(abi.encodePacked("Election")); bytes32 constant EXCHANGE_REGISTRY_ID = keccak256(abi.encodePacked("Exchange")); bytes32 constant FEE_CURRENCY_WHITELIST_REGISTRY_ID = keccak256( abi.encodePacked("FeeCurrencyWhitelist") ); bytes32 constant FREEZER_REGISTRY_ID = keccak256(abi.encodePacked("Freezer")); bytes32 constant GOLD_TOKEN_REGISTRY_ID = keccak256(abi.encodePacked("GoldToken")); bytes32 constant GOVERNANCE_REGISTRY_ID = keccak256(abi.encodePacked("Governance")); bytes32 constant GOVERNANCE_SLASHER_REGISTRY_ID = keccak256( abi.encodePacked("GovernanceSlasher") ); bytes32 constant LOCKED_GOLD_REGISTRY_ID = keccak256(abi.encodePacked("LockedGold")); bytes32 constant RESERVE_REGISTRY_ID = keccak256(abi.encodePacked("Reserve")); bytes32 constant RANDOM_REGISTRY_ID = keccak256(abi.encodePacked("Random")); bytes32 constant SORTED_ORACLES_REGISTRY_ID = keccak256(abi.encodePacked("SortedOracles")); bytes32 constant STABLE_TOKEN_REGISTRY_ID = keccak256(abi.encodePacked("StableToken")); bytes32 constant VALIDATORS_REGISTRY_ID = keccak256(abi.encodePacked("Validators")); // solhint-enable state-visibility IRegistry public registry; modifier onlyRegisteredContract(bytes32 identifierHash) { require(registry.getAddressForOrDie(identifierHash) == msg.sender, "only registered contract"); _; } modifier onlyRegisteredContracts(bytes32[] memory identifierHashes) { require(registry.isOneOf(identifierHashes, msg.sender), "only registered contracts"); _; } /** * @notice Updates the address pointing to a Registry contract. * @param registryAddress The address of a registry contract for routing to other contracts. */ function setRegistry(address registryAddress) public onlyOwner { require(registryAddress != address(0), "Cannot register the null address"); registry = IRegistry(registryAddress); emit RegistrySet(registryAddress); } function getAccounts() internal view returns (IAccounts) { return IAccounts(registry.getAddressForOrDie(ACCOUNTS_REGISTRY_ID)); } function getAttestations() internal view returns (IAttestations) { return IAttestations(registry.getAddressForOrDie(ATTESTATIONS_REGISTRY_ID)); } function getElection() internal view returns (IElection) { return IElection(registry.getAddressForOrDie(ELECTION_REGISTRY_ID)); } function getExchange() internal view returns (IExchange) { return IExchange(registry.getAddressForOrDie(EXCHANGE_REGISTRY_ID)); } function getFeeCurrencyWhitelistRegistry() internal view returns (IFeeCurrencyWhitelist) { return IFeeCurrencyWhitelist(registry.getAddressForOrDie(FEE_CURRENCY_WHITELIST_REGISTRY_ID)); } function getFreezer() internal view returns (IFreezer) { return IFreezer(registry.getAddressForOrDie(FREEZER_REGISTRY_ID)); } function getGoldToken() internal view returns (IERC20) { return IERC20(registry.getAddressForOrDie(GOLD_TOKEN_REGISTRY_ID)); } function getGovernance() internal view returns (IGovernance) { return IGovernance(registry.getAddressForOrDie(GOVERNANCE_REGISTRY_ID)); } function getLockedGold() internal view returns (ILockedGold) { return ILockedGold(registry.getAddressForOrDie(LOCKED_GOLD_REGISTRY_ID)); } function getRandom() internal view returns (IRandom) { return IRandom(registry.getAddressForOrDie(RANDOM_REGISTRY_ID)); } function getReserve() internal view returns (IReserve) { return IReserve(registry.getAddressForOrDie(RESERVE_REGISTRY_ID)); } function getSortedOracles() internal view returns (ISortedOracles) { return ISortedOracles(registry.getAddressForOrDie(SORTED_ORACLES_REGISTRY_ID)); } function getStableToken() internal view returns (IStableToken) { return IStableToken(registry.getAddressForOrDie(STABLE_TOKEN_REGISTRY_ID)); } function getValidators() internal view returns (IValidators) { return IValidators(registry.getAddressForOrDie(VALIDATORS_REGISTRY_ID)); } }
/project:/contracts/common/interfaces/IAccounts.sol
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.5.13 <0.9.0; interface IAccounts { function isAccount(address) external view returns (bool); function voteSignerToAccount(address) external view returns (address); function validatorSignerToAccount(address) external view returns (address); function attestationSignerToAccount(address) external view returns (address); function signerToAccount(address) external view returns (address); function getAttestationSigner(address) external view returns (address); function getValidatorSigner(address) external view returns (address); function getVoteSigner(address) external view returns (address); function hasAuthorizedVoteSigner(address) external view returns (bool); function hasAuthorizedValidatorSigner(address) external view returns (bool); function hasAuthorizedAttestationSigner(address) external view returns (bool); function setAccountDataEncryptionKey(bytes calldata) external; function setMetadataURL(string calldata) external; function setName(string calldata) external; function setWalletAddress(address, uint8, bytes32, bytes32) external; function setAccount(string calldata, bytes calldata, address, uint8, bytes32, bytes32) external; function getDataEncryptionKey(address) external view returns (bytes memory); function getWalletAddress(address) external view returns (address); function getMetadataURL(address) external view returns (string memory); function batchGetMetadataURL(address[] calldata) external view returns (uint256[] memory, bytes memory); function getName(address) external view returns (string memory); function authorizeVoteSigner(address, uint8, bytes32, bytes32) external; function authorizeValidatorSigner(address, uint8, bytes32, bytes32) external; function authorizeValidatorSignerWithPublicKey(address, uint8, bytes32, bytes32, bytes calldata) external; function authorizeValidatorSignerWithKeys( address, uint8, bytes32, bytes32, bytes calldata, bytes calldata, bytes calldata ) external; function authorizeAttestationSigner(address, uint8, bytes32, bytes32) external; function createAccount() external returns (bool); function setPaymentDelegation(address, uint256) external; function getPaymentDelegation(address) external view returns (address, uint256); function isSigner(address, address, bytes32) external view returns (bool); }
/project:/contracts/common/interfaces/ICeloToken.sol
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.5.13 <0.9.0; /** * @title This interface describes the non- ERC20 shared interface for all Celo Tokens, and * in the absence of interface inheritance is intended as a companion to IERC20.sol. */ interface ICeloToken { function transferWithComment(address, uint256, string calldata) external returns (bool); function name() external view returns (string memory); function symbol() external view returns (string memory); function decimals() external view returns (uint8); function burn(uint256 value) external returns (bool); }
/project:/contracts/common/interfaces/ICeloVersionedContract.sol
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.5.13 <0.9.0; interface ICeloVersionedContract { /** * @notice Returns the storage, major, minor, and patch version of the contract. * @return Storage version of the contract. * @return Major version of the contract. * @return Minor version of the contract. * @return Patch version of the contract. */ function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256); }
/project:/contracts/common/interfaces/IFeeCurrencyWhitelist.sol
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.5.13 <0.9.0; interface IFeeCurrencyWhitelist { function addToken(address) external; function getWhitelist() external view returns (address[] memory); }
/project:/contracts/common/interfaces/IFeeHandler.sol
pragma solidity ^0.5.13; import "../FixidityLib.sol"; interface IFeeHandler { // sets the portion of the fee that should be burned. function setBurnFraction(uint256 fraction) external; function addToken(address tokenAddress, address handlerAddress) external; function removeToken(address tokenAddress) external; function setHandler(address tokenAddress, address handlerAddress) external; // marks token to be handled in "handleAll()) function activateToken(address tokenAddress) external; function deactivateToken(address tokenAddress) external; function sell(address tokenAddress) external; // calls exchange(tokenAddress), and distribute(tokenAddress) function handle(address tokenAddress) external; // main entrypoint for a burn, iterates over token and calles handle function handleAll() external; // Sends the balance of token at tokenAddress to feesBeneficiary, // according to the entry tokensToDistribute[tokenAddress] function distribute(address tokenAddress) external; // burns the balance of Celo in the contract minus the entry of tokensToDistribute[CeloAddress] function burnCelo() external; // calls distribute for all the nonCeloTokens function distributeAll() external; // in case some funds need to be returned or moved to another contract function transfer(address token, address recipient, uint256 value) external returns (bool); }
/project:/contracts/common/interfaces/IFeeHandlerSeller.sol
pragma solidity ^0.5.13; import "../FixidityLib.sol"; interface IFeeHandlerSeller { function sell( address sellTokenAddress, address buyTokenAddress, uint256 amount, uint256 minAmount ) external returns (uint256); // in case some funds need to be returned or moved to another contract function transfer(address token, uint256 amount, address to) external returns (bool); }
/project:/contracts/common/interfaces/IFreezer.sol
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.5.13 <0.9.0; interface IFreezer { function isFrozen(address) external view returns (bool); }
/project:/contracts/common/interfaces/IRegistry.sol
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.5.13 <0.9.0; interface IRegistry { function setAddressFor(string calldata, address) external; function getAddressForOrDie(bytes32) external view returns (address); function getAddressFor(bytes32) external view returns (address); function getAddressForStringOrDie(string calldata identifier) external view returns (address); function getAddressForString(string calldata identifier) external view returns (address); function isOneOf(bytes32[] calldata, address) external view returns (bool); }
/project:/contracts/common/interfaces/IStableTokenMento.sol
pragma solidity ^0.5.13; /** * @title This interface describes the functions specific to Celo Stable Tokens, and in the * absence of interface inheritance is intended as a companion to IERC20.sol and ICeloToken.sol. */ interface IStableTokenMento { function mint(address, uint256) external returns (bool); function burn(uint256) external returns (bool); function setInflationParameters(uint256, uint256) external; function valueToUnits(uint256) external view returns (uint256); function unitsToValue(uint256) external view returns (uint256); function getInflationParameters() external view returns (uint256, uint256, uint256, uint256); // NOTE: duplicated with IERC20.sol, remove once interface inheritance is supported. function balanceOf(address) external view returns (uint256); function getExchangeRegistryId() external view returns (bytes32); function approve(address spender, uint256 value) external returns (bool); }
/project:/contracts/common/libraries/ReentrancyGuard.sol
pragma solidity ^0.5.13; /** * @title Helps contracts guard against reentrancy attacks. * @author Remco Bloemen <remco@2π.com>, Eenae <[email protected]> * @dev If you mark a function `nonReentrant`, you should also * mark it `external`. */ contract ReentrancyGuard { /// @dev counter to allow mutex lock with only one SSTORE operation uint256 private _guardCounter; constructor() internal { // The counter starts at one to prevent changing it from zero to a non-zero // value, which is a more expensive operation. _guardCounter = 1; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and make it call a * `private` function that does the actual work. */ modifier nonReentrant() { _guardCounter += 1; uint256 localCounter = _guardCounter; _; require(localCounter == _guardCounter, "reentrant call"); } }
/project:/contracts/governance/interfaces/IElection.sol
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.5.13 <0.9.0; interface IElection { function electValidatorSigners() external view returns (address[] memory); function electNValidatorSigners(uint256, uint256) external view returns (address[] memory); function vote(address, uint256, address, address) external returns (bool); function activate(address) external returns (bool); function revokeActive(address, uint256, address, address, uint256) external returns (bool); function revokeAllActive(address, address, address, uint256) external returns (bool); function revokePending(address, uint256, address, address, uint256) external returns (bool); function markGroupIneligible(address) external; function markGroupEligible(address, address, address) external; function allowedToVoteOverMaxNumberOfGroups(address) external returns (bool); function forceDecrementVotes( address, uint256, address[] calldata, address[] calldata, uint256[] calldata ) external returns (uint256); function setAllowedToVoteOverMaxNumberOfGroups(bool flag) external; // view functions function getElectableValidators() external view returns (uint256, uint256); function getElectabilityThreshold() external view returns (uint256); function getNumVotesReceivable(address) external view returns (uint256); function getTotalVotes() external view returns (uint256); function getActiveVotes() external view returns (uint256); function getTotalVotesByAccount(address) external view returns (uint256); function getPendingVotesForGroupByAccount(address, address) external view returns (uint256); function getActiveVotesForGroupByAccount(address, address) external view returns (uint256); function getTotalVotesForGroupByAccount(address, address) external view returns (uint256); function getActiveVoteUnitsForGroupByAccount(address, address) external view returns (uint256); function getTotalVotesForGroup(address) external view returns (uint256); function getActiveVotesForGroup(address) external view returns (uint256); function getPendingVotesForGroup(address) external view returns (uint256); function getGroupEligibility(address) external view returns (bool); function getGroupEpochRewards(address, uint256, uint256[] calldata) external view returns (uint256); function getGroupsVotedForByAccount(address) external view returns (address[] memory); function getEligibleValidatorGroups() external view returns (address[] memory); function getTotalVotesForEligibleValidatorGroups() external view returns (address[] memory, uint256[] memory); function getCurrentValidatorSigners() external view returns (address[] memory); function canReceiveVotes(address, uint256) external view returns (bool); function hasActivatablePendingVotes(address, address) external view returns (bool); function validatorSignerAddressFromCurrentSet(uint256 index) external view returns (address); function numberValidatorsInCurrentSet() external view returns (uint256); // only owner function setElectableValidators(uint256, uint256) external returns (bool); function setMaxNumGroupsVotedFor(uint256) external returns (bool); function setElectabilityThreshold(uint256) external returns (bool); // only VM function distributeEpochRewards(address, uint256, address, address) external; }
/project:/contracts/governance/interfaces/IGovernance.sol
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.5.13 <0.9.0; interface IGovernance { function removeVotesWhenRevokingDelegatedVotes(address account, uint256 maxAmountAllowed) external; function votePartially( uint256 proposalId, uint256 index, uint256 yesVotes, uint256 noVotes, uint256 abstainVotes ) external returns (bool); function isVoting(address) external view returns (bool); function getAmountOfGoldUsedForVoting(address account) external view returns (uint256); function getProposal(uint256 proposalId) external view returns (address, uint256, uint256, uint256, string memory, uint256, bool); function getReferendumStageDuration() external view returns (uint256); }
/project:/contracts/governance/interfaces/ILockedGold.sol
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.5.13 <0.9.0; interface ILockedGold { function lock() external payable; function incrementNonvotingAccountBalance(address, uint256) external; function decrementNonvotingAccountBalance(address, uint256) external; function getAccountTotalLockedGold(address) external view returns (uint256); function getTotalLockedGold() external view returns (uint256); function getPendingWithdrawals(address) external view returns (uint256[] memory, uint256[] memory); function getPendingWithdrawal(address account, uint256 index) external view returns (uint256, uint256); function getTotalPendingWithdrawals(address) external view returns (uint256); function unlock(uint256) external; function relock(uint256, uint256) external; function withdraw(uint256) external; function slash( address account, uint256 penalty, address reporter, uint256 reward, address[] calldata lessers, address[] calldata greaters, uint256[] calldata indices ) external; function isSlasher(address) external view returns (bool); function getAccountTotalDelegatedFraction(address account) external view returns (uint256); function getAccountTotalGovernanceVotingPower(address account) external view returns (uint256); function unlockingPeriod() external view returns (uint256); function getAccountNonvotingLockedGold(address account) external view returns (uint256); }
/project:/contracts/governance/interfaces/IValidators.sol
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.5.13 <0.9.0; interface IValidators { function registerValidator(bytes calldata, bytes calldata, bytes calldata) external returns (bool); function deregisterValidator(uint256) external returns (bool); function affiliate(address) external returns (bool); function deaffiliate() external returns (bool); function updateBlsPublicKey(bytes calldata, bytes calldata) external returns (bool); function registerValidatorGroup(uint256) external returns (bool); function deregisterValidatorGroup(uint256) external returns (bool); function addMember(address) external returns (bool); function addFirstMember(address, address, address) external returns (bool); function removeMember(address) external returns (bool); function reorderMember(address, address, address) external returns (bool); function updateCommission() external; function setNextCommissionUpdate(uint256) external; function resetSlashingMultiplier() external; // only owner function setCommissionUpdateDelay(uint256) external; function setMaxGroupSize(uint256) external returns (bool); function setMembershipHistoryLength(uint256) external returns (bool); function setValidatorScoreParameters(uint256, uint256) external returns (bool); function setGroupLockedGoldRequirements(uint256, uint256) external returns (bool); function setValidatorLockedGoldRequirements(uint256, uint256) external returns (bool); function setSlashingMultiplierResetPeriod(uint256) external; // view functions function getMaxGroupSize() external view returns (uint256); function getCommissionUpdateDelay() external view returns (uint256); function getValidatorScoreParameters() external view returns (uint256, uint256); function getMembershipHistory(address) external view returns (uint256[] memory, address[] memory, uint256, uint256); function calculateEpochScore(uint256) external view returns (uint256); function calculateGroupEpochScore(uint256[] calldata) external view returns (uint256); function getAccountLockedGoldRequirement(address) external view returns (uint256); function meetsAccountLockedGoldRequirements(address) external view returns (bool); function getValidatorBlsPublicKeyFromSigner(address) external view returns (bytes memory); function getValidator(address account) external view returns (bytes memory, bytes memory, address, uint256, address); function getValidatorGroup(address) external view returns (address[] memory, uint256, uint256, uint256, uint256[] memory, uint256, uint256); function getGroupNumMembers(address) external view returns (uint256); function getTopGroupValidators(address, uint256) external view returns (address[] memory); function getGroupsNumMembers(address[] calldata accounts) external view returns (uint256[] memory); function getNumRegisteredValidators() external view returns (uint256); function groupMembershipInEpoch(address, uint256, uint256) external view returns (address); // only registered contract function updateEcdsaPublicKey(address, address, bytes calldata) external returns (bool); function updatePublicKeys(address, address, bytes calldata, bytes calldata, bytes calldata) external returns (bool); function getValidatorLockedGoldRequirements() external view returns (uint256, uint256); function getGroupLockedGoldRequirements() external view returns (uint256, uint256); function getRegisteredValidators() external view returns (address[] memory); function getRegisteredValidatorSigners() external view returns (address[] memory); function getRegisteredValidatorGroups() external view returns (address[] memory); function isValidatorGroup(address) external view returns (bool); function isValidator(address) external view returns (bool); function getValidatorGroupSlashingMultiplier(address) external view returns (uint256); function getMembershipInLastEpoch(address) external view returns (address); function getMembershipInLastEpochFromSigner(address) external view returns (address); // only VM function updateValidatorScoreFromSigner(address, uint256) external; function distributeEpochPaymentsFromSigner(address, uint256) external returns (uint256); // only slasher function forceDeaffiliateIfValidator(address) external; function halveSlashingMultiplier(address) external; }
/project:/contracts/identity/interfaces/IAttestations.sol
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.5.13 <0.9.0; interface IAttestations { function revoke(bytes32, uint256) external; function withdraw(address) external; // view functions function getUnselectedRequest(bytes32, address) external view returns (uint32, uint32, address); function getAttestationIssuers(bytes32, address) external view returns (address[] memory); function getAttestationStats(bytes32, address) external view returns (uint32, uint32); function batchGetAttestationStats(bytes32[] calldata) external view returns (uint256[] memory, address[] memory, uint64[] memory, uint64[] memory); function getAttestationState(bytes32, address, address) external view returns (uint8, uint32, address); function getCompletableAttestations(bytes32, address) external view returns (uint32[] memory, address[] memory, uint256[] memory, bytes memory); function getAttestationRequestFee(address) external view returns (uint256); function getMaxAttestations() external view returns (uint256); function validateAttestationCode(bytes32, address, uint8, bytes32, bytes32) external view returns (address); function lookupAccountsForIdentifier(bytes32) external view returns (address[] memory); function requireNAttestationsRequested(bytes32, address, uint32) external view; // only owner function setAttestationRequestFee(address, uint256) external; function setAttestationExpiryBlocks(uint256) external; function setSelectIssuersWaitBlocks(uint256) external; function setMaxAttestations(uint256) external; }
/project:/contracts/identity/interfaces/IRandom.sol
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.5.13 <0.9.0; interface IRandom { function revealAndCommit(bytes32, bytes32, address) external; function randomnessBlockRetentionWindow() external view returns (uint256); function random() external view returns (bytes32); function getBlockRandomness(uint256) external view returns (bytes32); }
/project:/contracts/stability/interfaces/ISortedOracles.sol
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.5.13 <0.9.0; interface ISortedOracles { function addOracle(address, address) external; function removeOracle(address, address, uint256) external; function report(address, uint256, address, address) external; function removeExpiredReports(address, uint256) external; function isOldestReportExpired(address token) external view returns (bool, address); function numRates(address) external view returns (uint256); function medianRate(address) external view returns (uint256, uint256); function numTimestamps(address) external view returns (uint256); function medianTimestamp(address) external view returns (uint256); }
/project:/lib/mento-core/contracts/interfaces/IExchange.sol
pragma solidity ^0.5.13; interface IExchange { function buy( uint256, uint256, bool ) external returns (uint256); function sell( uint256, uint256, bool ) external returns (uint256); function exchange( uint256, uint256, bool ) external returns (uint256); function setUpdateFrequency(uint256) external; function getBuyTokenAmount(uint256, bool) external view returns (uint256); function getSellTokenAmount(uint256, bool) external view returns (uint256); function getBuyAndSellBuckets(bool) external view returns (uint256, uint256); }
/project:/lib/mento-core/contracts/interfaces/IReserve.sol
pragma solidity ^0.5.13; interface IReserve { function setTobinTaxStalenessThreshold(uint256) external; function addToken(address) external returns (bool); function removeToken(address, uint256) external returns (bool); function transferGold(address payable, uint256) external returns (bool); function transferExchangeGold(address payable, uint256) external returns (bool); function getReserveGoldBalance() external view returns (uint256); function getUnfrozenReserveGoldBalance() external view returns (uint256); function getOrComputeTobinTax() external returns (uint256, uint256); function getTokens() external view returns (address[] memory); function getReserveRatio() external view returns (uint256); function addExchangeSpender(address) external; function removeExchangeSpender(address, uint256) external; function addSpender(address) external; function removeSpender(address) external; }
/project:/lib/mento-core/contracts/interfaces/IStableToken.sol
pragma solidity ^0.5.13; /** * @title This interface describes the functions specific to Celo Stable Tokens, and in the * absence of interface inheritance is intended as a companion to IERC20.sol and ICeloToken.sol. */ interface IStableToken { function mint(address, uint256) external returns (bool); function burn(uint256) external returns (bool); function setInflationParameters(uint256, uint256) external; function valueToUnits(uint256) external view returns (uint256); function unitsToValue(uint256) external view returns (uint256); function getInflationParameters() external view returns ( uint256, uint256, uint256, uint256 ); // NOTE: duplicated with IERC20.sol, remove once interface inheritance is supported. function balanceOf(address) external view returns (uint256); }
Compiler Settings
{"remappings":[],"optimizer":{"runs":200,"enabled":false},"metadata":{"useLiteralContent":true},"libraries":{},"evmVersion":"istanbul","compilationTarget":{"project:/contracts/common/FeeHandler.sol":"FeeHandler"}}
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","payable":false,"inputs":[{"type":"bool","name":"test","internalType":"bool"}]},{"type":"event","name":"BurnFractionSet","inputs":[{"type":"uint256","name":"fraction","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"DailyLimitHit","inputs":[{"type":"address","name":"token","internalType":"address","indexed":false},{"type":"uint256","name":"burning","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"DailyLimitSet","inputs":[{"type":"address","name":"tokenAddress","internalType":"address","indexed":false},{"type":"uint256","name":"newLimit","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"DailySellLimitUpdated","inputs":[{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"FeeBeneficiarySet","inputs":[{"type":"address","name":"newBeneficiary","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"MaxSlippageSet","inputs":[{"type":"address","name":"token","internalType":"address","indexed":false},{"type":"uint256","name":"maxSlippage","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":"event","name":"RegistrySet","inputs":[{"type":"address","name":"registryAddress","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"SoldAndBurnedToken","inputs":[{"type":"address","name":"token","internalType":"address","indexed":false},{"type":"uint256","name":"value","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"TokenAdded","inputs":[{"type":"address","name":"tokenAddress","internalType":"address","indexed":false},{"type":"address","name":"handlerAddress","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"TokenRemoved","inputs":[{"type":"address","name":"tokenAddress","internalType":"address","indexed":false}],"anonymous":false},{"type":"fallback","stateMutability":"payable","payable":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"FIXED1_UINT","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"MIN_BURN","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"activateToken","inputs":[{"type":"address","name":"tokenAddress","internalType":"address"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"addToken","inputs":[{"type":"address","name":"tokenAddress","internalType":"address"},{"type":"address","name":"handlerAddress","internalType":"address"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"burnCelo","inputs":[],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"value","internalType":"uint256"}],"name":"burnFraction","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"celoToBeBurned","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"dailySellLimitHit","inputs":[{"type":"address","name":"token","internalType":"address"},{"type":"uint256","name":"amountToBurn","internalType":"uint256"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"deactivateToken","inputs":[{"type":"address","name":"tokenAddress","internalType":"address"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"distribute","inputs":[{"type":"address","name":"tokenAddress","internalType":"address"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"distributeAll","inputs":[],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"","internalType":"address"}],"name":"feeBeneficiary","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address[]","name":"","internalType":"address[]"}],"name":"getActiveTokens","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getPastBurnForToken","inputs":[{"type":"address","name":"token","internalType":"address"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"getTokenActive","inputs":[{"type":"address","name":"tokenAddress","internalType":"address"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getTokenCurrentDaySellLimit","inputs":[{"type":"address","name":"tokenAddress","internalType":"address"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getTokenDailySellLimit","inputs":[{"type":"address","name":"tokenAddress","internalType":"address"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"","internalType":"address"}],"name":"getTokenHandler","inputs":[{"type":"address","name":"tokenAddress","internalType":"address"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getTokenMaxSlippage","inputs":[{"type":"address","name":"tokenAddress","internalType":"address"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getTokenToDistribute","inputs":[{"type":"address","name":"tokenAddress","internalType":"address"}],"constant":true},{"type":"function","stateMutability":"pure","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"},{"type":"uint256","name":"","internalType":"uint256"},{"type":"uint256","name":"","internalType":"uint256"},{"type":"uint256","name":"","internalType":"uint256"}],"name":"getVersionNumber","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"handle","inputs":[{"type":"address","name":"tokenAddress","internalType":"address"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"handleAll","inputs":[],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"initialize","inputs":[{"type":"address","name":"_registryAddress","internalType":"address"},{"type":"address","name":"newFeeBeneficiary","internalType":"address"},{"type":"uint256","name":"newBurnFraction","internalType":"uint256"},{"type":"address[]","name":"tokens","internalType":"address[]"},{"type":"address[]","name":"handlers","internalType":"address[]"},{"type":"uint256[]","name":"newLimits","internalType":"uint256[]"},{"type":"uint256[]","name":"newMaxSlippages","internalType":"uint256[]"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"initialized","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isOwner","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"lastLimitDay","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"","internalType":"contract IRegistry"}],"name":"registry","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"removeToken","inputs":[{"type":"address","name":"tokenAddress","internalType":"address"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"renounceOwnership","inputs":[],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"sell","inputs":[{"type":"address","name":"tokenAddress","internalType":"address"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setBurnFraction","inputs":[{"type":"uint256","name":"fraction","internalType":"uint256"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setDailySellLimit","inputs":[{"type":"address","name":"token","internalType":"address"},{"type":"uint256","name":"newLimit","internalType":"uint256"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setFeeBeneficiary","inputs":[{"type":"address","name":"beneficiary","internalType":"address"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setHandler","inputs":[{"type":"address","name":"tokenAddress","internalType":"address"},{"type":"address","name":"handlerAddress","internalType":"address"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setMaxSplippage","inputs":[{"type":"address","name":"token","internalType":"address"},{"type":"uint256","name":"newMax","internalType":"uint256"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setRegistry","inputs":[{"type":"address","name":"registryAddress","internalType":"address"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"transfer","inputs":[{"type":"address","name":"token","internalType":"address"},{"type":"address","name":"recipient","internalType":"address"},{"type":"uint256","name":"value","internalType":"uint256"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}],"constant":false}]
Contract Creation Code
0x60806040523480156200001157600080fd5b506040516200540e3803806200540e833981810160405260208110156200003757600080fd5b81019080805190602001909291905050508060006200005b6200012b60201b60201c565b9050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350806200011b576001600060146101000a81548160ff0219169083151502179055505b5060016002819055505062000133565b600033905090565b6152cb80620001436000396000f3fe60806040526004361061023b5760003560e01c806368173bcf1161012e578063a91ee0dc116100ab578063df3712e41161006f578063df3712e414610e8a578063e9f1bbde14610eb5578063ec4bd8ae14610f26578063ee8df72d14610f8b578063f2fde38b14610fa25761023b565b8063a91ee0dc14610ccf578063b8b99e4d14610d20578063beabacc814610d37578063c558df3814610dca578063ce4773d314610e255761023b565b80638da5cb5b116100f25780638da5cb5b14610b685780638de065b614610bbf5780638f32d59b14610bea57806392f8bce314610c1957806394b6f9d414610c7e5761023b565b806368173bcf146109ef5780636c6c65ad14610a40578063715018a614610aa95780637b10399914610ac05780637b76314014610b175761023b565b806349844b1c116101bc5780635f5817e3116101805780635f5817e3146106ad5780635fa7b5841461071957806363453ae11461076a578063650a1605146107bb5780636654f4351461098a5761023b565b806349844b1c146105255780634e73db991461055057806354255be0146105ab5780635476bd72146105eb5780635a0a3d821461065c5761023b565b806331828a5b1161020357806331828a5b14610378578063384995cd146103eb5780633b9e3ad614610426578063436596c4146104b7578063492fb343146104ce5761023b565b8063036235a61461023d57806308906111146102685780630d1ce2d21461029357806313e33cea146102e4578063158ef93e14610349575b005b34801561024957600080fd5b50610252610ff3565b6040518082815260200191505060405180910390f35b34801561027457600080fd5b5061027d611001565b6040518082815260200191505060405180910390f35b34801561029f57600080fd5b506102e2600480360360208110156102b657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611007565b005b3480156102f057600080fd5b506103336004803603602081101561030757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061108d565b6040518082815260200191505060405180910390f35b34801561035557600080fd5b5061035e6110d9565b604051808215151515815260200191505060405180910390f35b34801561038457600080fd5b506103d16004803603604081101561039b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506110ec565b604051808215151515815260200191505060405180910390f35b3480156103f757600080fd5b506104246004803603602081101561040e57600080fd5b810190808035906020019092919050505061118a565b005b34801561043257600080fd5b506104756004803603602081101561044957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611210565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156104c357600080fd5b506104cc61127c565b005b3480156104da57600080fd5b506104e3611286565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561053157600080fd5b5061053a6112ac565b6040518082815260200191505060405180910390f35b34801561055c57600080fd5b506105a96004803603604081101561057357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506112b1565b005b3480156105b757600080fd5b506105c0611339565b6040518085815260200184815260200183815260200182815260200194505050505060405180910390f35b3480156105f757600080fd5b5061065a6004803603604081101561060e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061135f565b005b34801561066857600080fd5b506106ab6004803603602081101561067f57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506113e7565b005b3480156106b957600080fd5b506106c261146d565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156107055780820151818401526020810190506106ea565b505050509050019250505060405180910390f35b34801561072557600080fd5b506107686004803603602081101561073c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506114fe565b005b34801561077657600080fd5b506107b96004803603602081101561078d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611584565b005b3480156107c757600080fd5b50610988600480360360e08110156107de57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019064010000000081111561084557600080fd5b82018360208201111561085757600080fd5b8035906020019184602083028401116401000000008311171561087957600080fd5b90919293919293908035906020019064010000000081111561089a57600080fd5b8201836020820111156108ac57600080fd5b803590602001918460208302840111640100000000831117156108ce57600080fd5b9091929391929390803590602001906401000000008111156108ef57600080fd5b82018360208201111561090157600080fd5b8035906020019184602083028401116401000000008311171561092357600080fd5b90919293919293908035906020019064010000000081111561094457600080fd5b82018360208201111561095657600080fd5b8035906020019184602083028401116401000000008311171561097857600080fd5b9091929391929390505050611590565b005b34801561099657600080fd5b506109d9600480360360208110156109ad57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061187a565b6040518082815260200191505060405180910390f35b3480156109fb57600080fd5b50610a3e60048036036020811015610a1257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506118c6565b005b348015610a4c57600080fd5b50610a8f60048036036020811015610a6357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061194c565b604051808215151515815260200191505060405180910390f35b348015610ab557600080fd5b50610abe611969565b005b348015610acc57600080fd5b50610ad5611aa2565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b348015610b2357600080fd5b50610b6660048036036020811015610b3a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611ac8565b005b348015610b7457600080fd5b50610b7d611ad4565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b348015610bcb57600080fd5b50610bd4611afd565b6040518082815260200191505060405180910390f35b348015610bf657600080fd5b50610bff611b09565b604051808215151515815260200191505060405180910390f35b348015610c2557600080fd5b50610c6860048036036020811015610c3c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611b67565b6040518082815260200191505060405180910390f35b348015610c8a57600080fd5b50610ccd60048036036020811015610ca157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611bcf565b005b348015610cdb57600080fd5b50610d1e60048036036020811015610cf257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611bdb565b005b348015610d2c57600080fd5b50610d35611d7f565b005b348015610d4357600080fd5b50610db060048036036060811015610d5a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050611d89565b604051808215151515815260200191505060405180910390f35b348015610dd657600080fd5b50610e2360048036036040811015610ded57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050611ed0565b005b348015610e3157600080fd5b50610e7460048036036020811015610e4857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611f58565b6040518082815260200191505060405180910390f35b348015610e9657600080fd5b50610e9f611fa4565b6040518082815260200191505060405180910390f35b348015610ec157600080fd5b50610f2460048036036040811015610ed857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611faa565b005b348015610f3257600080fd5b50610f7560048036036020811015610f4957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612032565b6040518082815260200191505060405180910390f35b348015610f9757600080fd5b50610fa061207e565b005b348015610fae57600080fd5b50610ff160048036036020811015610fc557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612088565b005b69d3c21bcecceda100000081565b60065481565b61100f611b09565b611081576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b61108a8161210e565b50565b6000600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600301549050919050565b600060149054906101000a900460ff1681565b600080600760008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050600081600201541415611147576000915050611184565b600062015180428161115557fe5b0490506003548111156111775780600381905550816002015482600301819055505b8160030154841015925050505b92915050565b611192611b09565b611204576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b61120d8161233d565b50565b6000600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b611284612401565b565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60c881565b6112b9611b09565b61132b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6113358282612546565b5050565b600080600080600180600080839350829250819150809050935093509350935090919293565b611367611b09565b6113d9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6113e38282612708565b5050565b6113ef611b09565b611461576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b61146a816128e2565b50565b606060086001018054806020026020016040519081016040528092919081815260200182805480156114f457602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116114aa575b5050505050905090565b611506611b09565b611578576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b61158181612989565b50565b61158d81612a80565b50565b600060149054906101000a900460ff1615611613576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f636f6e747261637420616c726561647920696e697469616c697a65640000000081525060200191505060405180910390fd5b6001600060146101000a81548160ff02191690831515021790555085859050888890501461168c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180615080602a913960400191505060405180910390fd5b8383905088889050146116ea576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260288152602001806150f36028913960400191505060405180910390fd5b818190508888905014611748576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602d81526020018061511b602d913960400191505060405180910390fd5b611751336130d4565b61175a8b611bdb565b6117638a6128e2565b61176c8961233d565b60008090505b8888905081101561186c576117d789898381811061178c57fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff168888848181106117b557fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff16612708565b61181b8989838181106117e657fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff1686868481811061180f57fe5b90506020020135613218565b61185f89898381811061182a57fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff1684848481811061185357fe5b90506020020135612546565b8080600101915050611772565b505050505050505050505050565b6000600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600401549050919050565b6118ce611b09565b611940576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b611949816132d4565b50565b60006119628260086132ec90919063ffffffff16565b9050919050565b611971611b09565b6119e3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b611ad18161333b565b50565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60048060000154905081565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611b4b61357b565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b6000611bc8600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101604051806020016040529081600082015481525050613583565b9050919050565b611bd881613591565b50565b611be3611b09565b611c55576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611cf8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f43616e6e6f7420726567697374657220746865206e756c6c206164647265737381525060200191505060405180910390fd5b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f27fe5f0c1c3b1ed427cc63d0f05759ffdecf9aec9e18d31ef366fc8a6cb5dc3b60405160405180910390a250565b611d87613e62565b565b6000611d93611b09565b611e05576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b8373ffffffffffffffffffffffffffffffffffffffff1663a9059cbb84846040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b158015611e8c57600080fd5b505af1158015611ea0573d6000803e3d6000fd5b505050506040513d6020811015611eb657600080fd5b810190808051906020019092919050505090509392505050565b611ed8611b09565b611f4a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b611f548282613218565b5050565b6000600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600201549050919050565b60035481565b611fb2611b09565b612024576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b61202e82826141ea565b5050565b6000600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600501549050919050565b6120866142fb565b565b612090611b09565b612102576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b61210b816130d4565b50565b6000600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050600073ffffffffffffffffffffffffffffffffffffffff168160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415806122cf5750600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f476f6c64546f6b656e00000000000000000000000000000000000000000000008152506009019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561226557600080fd5b505afa158015612279573d6000803e3d6000fd5b505050506040513d602081101561228f57600080fd5b810190808051906020019092919050505073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b612324576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260278152602001806152706027913960400191505060405180910390fd5b61233882600861435490919063ffffffff16565b505050565b61234561506c565b61234e82614424565b90506123618161235c614442565b614468565b6123b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602d815260200180615243602d913960400191505060405180910390fd5b806004600082015181600001559050507f41c679f4bcdc2c95f79a3647e2237162d9763d86685ef6c667781230c8ba9157826040518082815260200191505060405180910390a15050565b60008090505b612411600861447e565b81101561244757600061242e82600861448f90919063ffffffff16565b905061243981612a80565b508080600101915050612407565b50612544600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f476f6c64546f6b656e00000000000000000000000000000000000000000000008152506009019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561250457600080fd5b505afa158015612518573d6000803e3d6000fd5b505050506040513d602081101561252e57600080fd5b8101908080519060200190929190505050612a80565b565b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000821415612600576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f43616e6e6f7420736574206d617820736c69707061676520746f207a65726f0081525060200191505060405180910390fd5b61260982614424565b81600101600082015181600001559050506126438160010160405180602001604052908160008201548152505061263e614442565b614468565b612698576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602981526020018061521a6029913960400191505060405180910390fd5b7fd8df93d785f3d0d4294fd7b61e5d749c20eec95a2fed5b6b502a4cad09199ca68383604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a1505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156127ab576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f43616e2774207365742068616e646c657220746f207a65726f0000000000000081525060200191505060405180910390fd5b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050818160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061284583600861435490919063ffffffff16565b507fdffbd9ded1c09446f09377de547142dcce7dc541c8b0b028142b1eba7026b9e78383604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a1505050565b80600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507ff7015098f8d6fa48f0560725ffd5f81bf687ee5ac45153b590bdcb04648bbdd381604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150565b612992816132d4565b6000600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060008160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f4c910b69fe65a61f7531b9c5042b2329ca7179c77290aa7e2eb3afa3c8511fd382604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a15050565b612a886144d3565b73ffffffffffffffffffffffffffffffffffffffff1663e5839836306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015612b0457600080fd5b505afa158015612b18573d6000803e3d6000fd5b505050506040513d6020811015612b2e57600080fd5b810190808051906020019092919050505015612b95576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602281526020018061516c6022913960400191505060405180910390fd5b600160026000828254019250508190555060006002549050600073ffffffffffffffffffffffffffffffffffffffff16600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415612c55576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806151486024913960400191505060405180910390fd5b600082905060008173ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015612cd957600080fd5b505afa158015612ced573d6000803e3d6000fd5b505050506040513d6020811015612d0357600080fd5b810190808051906020019092919050505090506000600760008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050600073ffffffffffffffffffffffffffffffffffffffff168160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141580612ed75750600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f476f6c64546f6b656e00000000000000000000000000000000000000000000008152506009019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015612e6d57600080fd5b505afa158015612e81573d6000803e3d6000fd5b505050506040513d6020811015612e9757600080fd5b810190808051906020019092919050505073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16145b612f2c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806150d06023913960400191505060405180910390fd5b6000612f3c8383600401546145ce565b90506000811415612f505750505050613059565b8373ffffffffffffffffffffffffffffffffffffffff1663a9059cbb600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b158015612ff957600080fd5b505af115801561300d573d6000803e3d6000fd5b505050506040513d602081101561302357600080fd5b81019080805190602001909291905050505061304c8183600401546145e790919063ffffffff16565b8260040181905550505050505b60025481146130d0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f7265656e7472616e742063616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b5050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561315a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806150aa6026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508181600201819055507fd3d22ffd28b02735cf411bd7f925bd8da01212c7028153e0d632e2953ac3088e8383604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a1505050565b6132e881600861463190919063ffffffff16565b5050565b6000808360000160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541415905092915050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f476f6c64546f6b656e00000000000000000000000000000000000000000000008152506009019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b1580156133f457600080fd5b505afa158015613408573d6000803e3d6000fd5b505050506040513d602081101561341e57600080fd5b810190808051906020019092919050505073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461346b5761346a81613591565b5b613473613e62565b61347c81612a80565b613578600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f476f6c64546f6b656e00000000000000000000000000000000000000000000008152506009019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561353857600080fd5b505afa15801561354c573d6000803e3d6000fd5b505050506040513d602081101561356257600080fd5b8101908080519060200190929190505050612a80565b50565b600033905090565b600081600001519050919050565b6135996144d3565b73ffffffffffffffffffffffffffffffffffffffff1663e5839836306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561361557600080fd5b505afa158015613629573d6000803e3d6000fd5b505050506040513d602081101561363f57600080fd5b8101908080519060200190929190505050156136a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602281526020018061516c6022913960400191505060405180910390fd5b60016002600082825401925050819055506000600254905060008290506000600760008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050600073ffffffffffffffffffffffffffffffffffffffff168160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614156137b0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806150d06023913960400191505060405180910390fd5b60006137d382600101604051806020016040529081600082015481525050613583565b141561382a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260288152602001806151c46028913960400191505060405180910390fd5b61383261506c565b61390861390383600401548573ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156138ba57600080fd5b505afa1580156138ce573d6000803e3d6000fd5b505050506040513d60208110156138e457600080fd5b81019080805190602001909291905050506145e790919063ffffffff16565b61481f565b9050600061393d6139388360046040518060200160405290816000820154815250506148a990919063ffffffff16565b614d08565b905061397061395d8261394f85614d08565b6145e790919063ffffffff16565b8460040154614d2990919063ffffffff16565b836004018190555060c881101561398a5750505050613de7565b61399486826110ec565b15613a0c57826003015490507fb1a68b0b66260ca392f760fd4dda4a94818d69c89a4eeb6610eb41db7bab8c378682604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a15b8373ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8460000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b158015613ab757600080fd5b505af1158015613acb573d6000803e3d6000fd5b505050506040513d6020811015613ae157600080fd5b81019080805190602001909291905050505060008360000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060008173ffffffffffffffffffffffffffffffffffffffff166331de7d1589600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f476f6c64546f6b656e00000000000000000000000000000000000000000000008152506009019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015613bf457600080fd5b505afa158015613c08573d6000803e3d6000fd5b505050506040513d6020811015613c1e57600080fd5b810190808051906020019092919050505086613c518a600101604051806020016040529081600082015481525050613583565b6040518563ffffffff1660e01b8152600401808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001838152602001828152602001945050505050602060405180830381600087803b158015613cf457600080fd5b505af1158015613d08573d6000803e3d6000fd5b505050506040513d6020811015613d1e57600080fd5b81019080805190602001909291905050509050613d4681600654614d2990919063ffffffff16565b600681905550613d63838660050154614d2990919063ffffffff16565b8560050181905550613d758884614db1565b7fac094032b4e9dccb3a000eedb94cf30146ca0d7c39be85229f478413fa21d1d88884604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a15050505050505b6002548114613e5e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f7265656e7472616e742063616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b5050565b600060076000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f476f6c64546f6b656e00000000000000000000000000000000000000000000008152506009019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015613f2157600080fd5b505afa158015613f35573d6000803e3d6000fd5b505050506040513d6020811015613f4b57600080fd5b810190808051906020019092919050505073ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f476f6c64546f6b656e00000000000000000000000000000000000000000000008152506009019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561405357600080fd5b505afa158015614067573d6000803e3d6000fd5b505050506040513d602081101561407d57600080fd5b81019080805190602001909291905050509050600047905060006140c26006546140b48660040154856145e790919063ffffffff16565b6145e790919063ffffffff16565b905060006140ff6140fa60046040518060200160405290816000820154815250506140ec8561481f565b6148a990919063ffffffff16565b614d08565b9050600061411860065483614d2990919063ffffffff16565b90508473ffffffffffffffffffffffffffffffffffffffff166342966c68826040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b15801561416d57600080fd5b505af1158015614181573d6000803e3d6000fd5b505050506040513d602081101561419757600080fd5b81019080805190602001909291905050505060006006819055506141da6141c783856145e790919063ffffffff16565b8760040154614d2990919063ffffffff16565b8660040181905550505050505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415614270576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e8152602001806151ec602e913960400191505060405180910390fd5b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050818160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505050565b60008090505b61430b600861447e565b81101561434157600061432882600861448f90919063ffffffff16565b905061433381613591565b508080600101915050614301565b5061434a612401565b614352613e62565b565b600061436083836132ec565b61441957826001018290806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508360000160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506001905061441e565b600090505b92915050565b61442c61506c565b6040518060200160405280838152509050919050565b61444a61506c565b604051806020016040528069d3c21bcecceda1000000815250905090565b6000816000015183600001511115905092915050565b600081600101805490509050919050565b60008260010182815481106144a057fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905092915050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f467265657a6572000000000000000000000000000000000000000000000000008152506007019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561458e57600080fd5b505afa1580156145a2573d6000803e3d6000fd5b505050506040513d60208110156145b857600080fd5b8101908080519060200190929190505050905090565b60008183106145dd57816145df565b825b905092915050565b600061462983836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250614e63565b905092915050565b600061463d83836132ec565b1561481457600060018460000160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020540390506000600185600101805490500390508181146147825760008560010182815481106146b257fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050808660010184815481106146ef57fe5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600183018660000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550505b8460000160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009055846001018054806147d457fe5b6001900381819060005260206000200160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690559055600192505050614819565b600090505b92915050565b61482761506c565b61482f614f23565b821115614887576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603681526020018061518e6036913960400191505060405180910390fd5b604051806020016040528069d3c21bcecceda100000084028152509050919050565b6148b161506c565b6000836000015114806148c8575060008260000151145b156148e457604051806020016040528060008152509050614d02565b69d3c21bcecceda10000008260000151141561490257829050614d02565b69d3c21bcecceda10000008360000151141561492057819050614d02565b600069d3c21bcecceda100000061493685614f42565b600001518161494157fe5b049050600061494f85614f79565b600001519050600069d3c21bcecceda100000061496b86614f42565b600001518161497657fe5b049050600061498486614f79565b6000015190506000828502905060008514614a1857828582816149a357fe5b0414614a17576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6f766572666c6f7720783179312064657465637465640000000000000000000081525060200191505060405180910390fd5b5b600069d3c21bcecceda10000008202905060008214614aba5769d3c21bcecceda1000000828281614a4557fe5b0414614ab9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f6f766572666c6f772078317931202a206669786564312064657465637465640081525060200191505060405180910390fd5b5b8091506000848602905060008614614b4b5784868281614ad657fe5b0414614b4a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6f766572666c6f7720783279312064657465637465640000000000000000000081525060200191505060405180910390fd5b5b6000848802905060008814614bd95784888281614b6457fe5b0414614bd8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6f766572666c6f7720783179322064657465637465640000000000000000000081525060200191505060405180910390fd5b5b614be1614fb6565b8781614be957fe5b049650614bf4614fb6565b8581614bfc57fe5b0494506000858802905060008814614c8d5785888281614c1857fe5b0414614c8c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6f766572666c6f7720783279322064657465637465640000000000000000000081525060200191505060405180910390fd5b5b614c9561506c565b6040518060200160405280878152509050614cbe81604051806020016040528087815250614fc3565b9050614cd881604051806020016040528086815250614fc3565b9050614cf281604051806020016040528085815250614fc3565b9050809a50505050505050505050505b92915050565b600069d3c21bcecceda1000000826000015181614d2157fe5b049050919050565b600080828401905083811015614da7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050600081600201541415614e075750614e5f565b614e1e8282600301546145e790919063ffffffff16565b81600301819055507fcdcea7139bd245b1c7468bc1cfb59ad732b3b0909bafa9f9436ad74c81d0aafb826040518082815260200191505060405180910390a1505b5050565b6000838311158290614f10576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015614ed5578082015181840152602081019050614eba565b50505050905090810190601f168015614f025780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b60007601357c299a88ea76a58924d52ce4f26a85af186c2b9e74905090565b614f4a61506c565b604051806020016040528069d3c21bcecceda100000080856000015181614f6d57fe5b04028152509050919050565b614f8161506c565b604051806020016040528069d3c21bcecceda100000080856000015181614fa457fe5b04028460000151038152509050919050565b600064e8d4a51000905090565b614fcb61506c565b6000826000015184600001510190508360000151811015615054576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f616464206f766572666c6f77206465746563746564000000000000000000000081525060200191505060405180910390fd5b60405180602001604052808281525091505092915050565b604051806020016040528060008152509056fe68616e646c657273206c656e6774682073686f756c64206d6174636820746f6b656e73206c656e6774684f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737348616e646c65722068617320746f2062652073657420746f2073656c6c20746f6b656e6c696d697473206c656e6774682073686f756c64206d6174636820746f6b656e73206c656e6774686d6178536c697070616765206c656e6774682073686f756c64206d6174636820746f6b656e73206c656e67746843616e2774206469737472696275746520746f20746865207a65726f206164647265737363616e27742063616c6c207768656e20636f6e74726163742069732066726f7a656e63616e277420637265617465206669786964697479206e756d626572206c6172676572207468616e206d61784e6577466978656428294d617820736c6970706167652068617320746f2062652073657420746f2073656c6c20746f6b656e43616e2774207365742068616e646c657220746f207a65726f2c207573652064656163746976617465546f6b656e53706c697070616765206d757374206265206c657373207468616e206f7220657175616c20746f20314275726e206672616374696f6e206d757374206265206c657373207468616e206f7220657175616c20746f203148616e646c65722068617320746f2062652073657420746f20616374697661746520746f6b656ea265627a7a72315820557f293af7575e78e686e68bb82eaf3b1ea1d7d79a767906b388ee207322cc7664736f6c634300050d00320000000000000000000000000000000000000000000000000000000000000000
Deployed ByteCode
0x60806040526004361061023b5760003560e01c806368173bcf1161012e578063a91ee0dc116100ab578063df3712e41161006f578063df3712e414610e8a578063e9f1bbde14610eb5578063ec4bd8ae14610f26578063ee8df72d14610f8b578063f2fde38b14610fa25761023b565b8063a91ee0dc14610ccf578063b8b99e4d14610d20578063beabacc814610d37578063c558df3814610dca578063ce4773d314610e255761023b565b80638da5cb5b116100f25780638da5cb5b14610b685780638de065b614610bbf5780638f32d59b14610bea57806392f8bce314610c1957806394b6f9d414610c7e5761023b565b806368173bcf146109ef5780636c6c65ad14610a40578063715018a614610aa95780637b10399914610ac05780637b76314014610b175761023b565b806349844b1c116101bc5780635f5817e3116101805780635f5817e3146106ad5780635fa7b5841461071957806363453ae11461076a578063650a1605146107bb5780636654f4351461098a5761023b565b806349844b1c146105255780634e73db991461055057806354255be0146105ab5780635476bd72146105eb5780635a0a3d821461065c5761023b565b806331828a5b1161020357806331828a5b14610378578063384995cd146103eb5780633b9e3ad614610426578063436596c4146104b7578063492fb343146104ce5761023b565b8063036235a61461023d57806308906111146102685780630d1ce2d21461029357806313e33cea146102e4578063158ef93e14610349575b005b34801561024957600080fd5b50610252610ff3565b6040518082815260200191505060405180910390f35b34801561027457600080fd5b5061027d611001565b6040518082815260200191505060405180910390f35b34801561029f57600080fd5b506102e2600480360360208110156102b657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611007565b005b3480156102f057600080fd5b506103336004803603602081101561030757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061108d565b6040518082815260200191505060405180910390f35b34801561035557600080fd5b5061035e6110d9565b604051808215151515815260200191505060405180910390f35b34801561038457600080fd5b506103d16004803603604081101561039b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506110ec565b604051808215151515815260200191505060405180910390f35b3480156103f757600080fd5b506104246004803603602081101561040e57600080fd5b810190808035906020019092919050505061118a565b005b34801561043257600080fd5b506104756004803603602081101561044957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611210565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156104c357600080fd5b506104cc61127c565b005b3480156104da57600080fd5b506104e3611286565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561053157600080fd5b5061053a6112ac565b6040518082815260200191505060405180910390f35b34801561055c57600080fd5b506105a96004803603604081101561057357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506112b1565b005b3480156105b757600080fd5b506105c0611339565b6040518085815260200184815260200183815260200182815260200194505050505060405180910390f35b3480156105f757600080fd5b5061065a6004803603604081101561060e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061135f565b005b34801561066857600080fd5b506106ab6004803603602081101561067f57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506113e7565b005b3480156106b957600080fd5b506106c261146d565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156107055780820151818401526020810190506106ea565b505050509050019250505060405180910390f35b34801561072557600080fd5b506107686004803603602081101561073c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506114fe565b005b34801561077657600080fd5b506107b96004803603602081101561078d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611584565b005b3480156107c757600080fd5b50610988600480360360e08110156107de57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019064010000000081111561084557600080fd5b82018360208201111561085757600080fd5b8035906020019184602083028401116401000000008311171561087957600080fd5b90919293919293908035906020019064010000000081111561089a57600080fd5b8201836020820111156108ac57600080fd5b803590602001918460208302840111640100000000831117156108ce57600080fd5b9091929391929390803590602001906401000000008111156108ef57600080fd5b82018360208201111561090157600080fd5b8035906020019184602083028401116401000000008311171561092357600080fd5b90919293919293908035906020019064010000000081111561094457600080fd5b82018360208201111561095657600080fd5b8035906020019184602083028401116401000000008311171561097857600080fd5b9091929391929390505050611590565b005b34801561099657600080fd5b506109d9600480360360208110156109ad57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061187a565b6040518082815260200191505060405180910390f35b3480156109fb57600080fd5b50610a3e60048036036020811015610a1257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506118c6565b005b348015610a4c57600080fd5b50610a8f60048036036020811015610a6357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061194c565b604051808215151515815260200191505060405180910390f35b348015610ab557600080fd5b50610abe611969565b005b348015610acc57600080fd5b50610ad5611aa2565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b348015610b2357600080fd5b50610b6660048036036020811015610b3a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611ac8565b005b348015610b7457600080fd5b50610b7d611ad4565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b348015610bcb57600080fd5b50610bd4611afd565b6040518082815260200191505060405180910390f35b348015610bf657600080fd5b50610bff611b09565b604051808215151515815260200191505060405180910390f35b348015610c2557600080fd5b50610c6860048036036020811015610c3c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611b67565b6040518082815260200191505060405180910390f35b348015610c8a57600080fd5b50610ccd60048036036020811015610ca157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611bcf565b005b348015610cdb57600080fd5b50610d1e60048036036020811015610cf257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611bdb565b005b348015610d2c57600080fd5b50610d35611d7f565b005b348015610d4357600080fd5b50610db060048036036060811015610d5a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050611d89565b604051808215151515815260200191505060405180910390f35b348015610dd657600080fd5b50610e2360048036036040811015610ded57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050611ed0565b005b348015610e3157600080fd5b50610e7460048036036020811015610e4857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611f58565b6040518082815260200191505060405180910390f35b348015610e9657600080fd5b50610e9f611fa4565b6040518082815260200191505060405180910390f35b348015610ec157600080fd5b50610f2460048036036040811015610ed857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611faa565b005b348015610f3257600080fd5b50610f7560048036036020811015610f4957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612032565b6040518082815260200191505060405180910390f35b348015610f9757600080fd5b50610fa061207e565b005b348015610fae57600080fd5b50610ff160048036036020811015610fc557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612088565b005b69d3c21bcecceda100000081565b60065481565b61100f611b09565b611081576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b61108a8161210e565b50565b6000600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600301549050919050565b600060149054906101000a900460ff1681565b600080600760008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050600081600201541415611147576000915050611184565b600062015180428161115557fe5b0490506003548111156111775780600381905550816002015482600301819055505b8160030154841015925050505b92915050565b611192611b09565b611204576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b61120d8161233d565b50565b6000600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b611284612401565b565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60c881565b6112b9611b09565b61132b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6113358282612546565b5050565b600080600080600180600080839350829250819150809050935093509350935090919293565b611367611b09565b6113d9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6113e38282612708565b5050565b6113ef611b09565b611461576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b61146a816128e2565b50565b606060086001018054806020026020016040519081016040528092919081815260200182805480156114f457602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116114aa575b5050505050905090565b611506611b09565b611578576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b61158181612989565b50565b61158d81612a80565b50565b600060149054906101000a900460ff1615611613576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f636f6e747261637420616c726561647920696e697469616c697a65640000000081525060200191505060405180910390fd5b6001600060146101000a81548160ff02191690831515021790555085859050888890501461168c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180615080602a913960400191505060405180910390fd5b8383905088889050146116ea576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260288152602001806150f36028913960400191505060405180910390fd5b818190508888905014611748576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602d81526020018061511b602d913960400191505060405180910390fd5b611751336130d4565b61175a8b611bdb565b6117638a6128e2565b61176c8961233d565b60008090505b8888905081101561186c576117d789898381811061178c57fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff168888848181106117b557fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff16612708565b61181b8989838181106117e657fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff1686868481811061180f57fe5b90506020020135613218565b61185f89898381811061182a57fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff1684848481811061185357fe5b90506020020135612546565b8080600101915050611772565b505050505050505050505050565b6000600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600401549050919050565b6118ce611b09565b611940576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b611949816132d4565b50565b60006119628260086132ec90919063ffffffff16565b9050919050565b611971611b09565b6119e3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b611ad18161333b565b50565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60048060000154905081565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611b4b61357b565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b6000611bc8600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101604051806020016040529081600082015481525050613583565b9050919050565b611bd881613591565b50565b611be3611b09565b611c55576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611cf8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f43616e6e6f7420726567697374657220746865206e756c6c206164647265737381525060200191505060405180910390fd5b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f27fe5f0c1c3b1ed427cc63d0f05759ffdecf9aec9e18d31ef366fc8a6cb5dc3b60405160405180910390a250565b611d87613e62565b565b6000611d93611b09565b611e05576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b8373ffffffffffffffffffffffffffffffffffffffff1663a9059cbb84846040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b158015611e8c57600080fd5b505af1158015611ea0573d6000803e3d6000fd5b505050506040513d6020811015611eb657600080fd5b810190808051906020019092919050505090509392505050565b611ed8611b09565b611f4a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b611f548282613218565b5050565b6000600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600201549050919050565b60035481565b611fb2611b09565b612024576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b61202e82826141ea565b5050565b6000600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600501549050919050565b6120866142fb565b565b612090611b09565b612102576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b61210b816130d4565b50565b6000600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050600073ffffffffffffffffffffffffffffffffffffffff168160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415806122cf5750600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f476f6c64546f6b656e00000000000000000000000000000000000000000000008152506009019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561226557600080fd5b505afa158015612279573d6000803e3d6000fd5b505050506040513d602081101561228f57600080fd5b810190808051906020019092919050505073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b612324576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260278152602001806152706027913960400191505060405180910390fd5b61233882600861435490919063ffffffff16565b505050565b61234561506c565b61234e82614424565b90506123618161235c614442565b614468565b6123b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602d815260200180615243602d913960400191505060405180910390fd5b806004600082015181600001559050507f41c679f4bcdc2c95f79a3647e2237162d9763d86685ef6c667781230c8ba9157826040518082815260200191505060405180910390a15050565b60008090505b612411600861447e565b81101561244757600061242e82600861448f90919063ffffffff16565b905061243981612a80565b508080600101915050612407565b50612544600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f476f6c64546f6b656e00000000000000000000000000000000000000000000008152506009019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561250457600080fd5b505afa158015612518573d6000803e3d6000fd5b505050506040513d602081101561252e57600080fd5b8101908080519060200190929190505050612a80565b565b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000821415612600576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f43616e6e6f7420736574206d617820736c69707061676520746f207a65726f0081525060200191505060405180910390fd5b61260982614424565b81600101600082015181600001559050506126438160010160405180602001604052908160008201548152505061263e614442565b614468565b612698576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602981526020018061521a6029913960400191505060405180910390fd5b7fd8df93d785f3d0d4294fd7b61e5d749c20eec95a2fed5b6b502a4cad09199ca68383604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a1505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156127ab576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f43616e2774207365742068616e646c657220746f207a65726f0000000000000081525060200191505060405180910390fd5b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050818160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061284583600861435490919063ffffffff16565b507fdffbd9ded1c09446f09377de547142dcce7dc541c8b0b028142b1eba7026b9e78383604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a1505050565b80600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507ff7015098f8d6fa48f0560725ffd5f81bf687ee5ac45153b590bdcb04648bbdd381604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150565b612992816132d4565b6000600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060008160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f4c910b69fe65a61f7531b9c5042b2329ca7179c77290aa7e2eb3afa3c8511fd382604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a15050565b612a886144d3565b73ffffffffffffffffffffffffffffffffffffffff1663e5839836306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015612b0457600080fd5b505afa158015612b18573d6000803e3d6000fd5b505050506040513d6020811015612b2e57600080fd5b810190808051906020019092919050505015612b95576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602281526020018061516c6022913960400191505060405180910390fd5b600160026000828254019250508190555060006002549050600073ffffffffffffffffffffffffffffffffffffffff16600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415612c55576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806151486024913960400191505060405180910390fd5b600082905060008173ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015612cd957600080fd5b505afa158015612ced573d6000803e3d6000fd5b505050506040513d6020811015612d0357600080fd5b810190808051906020019092919050505090506000600760008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050600073ffffffffffffffffffffffffffffffffffffffff168160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141580612ed75750600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f476f6c64546f6b656e00000000000000000000000000000000000000000000008152506009019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015612e6d57600080fd5b505afa158015612e81573d6000803e3d6000fd5b505050506040513d6020811015612e9757600080fd5b810190808051906020019092919050505073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16145b612f2c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806150d06023913960400191505060405180910390fd5b6000612f3c8383600401546145ce565b90506000811415612f505750505050613059565b8373ffffffffffffffffffffffffffffffffffffffff1663a9059cbb600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b158015612ff957600080fd5b505af115801561300d573d6000803e3d6000fd5b505050506040513d602081101561302357600080fd5b81019080805190602001909291905050505061304c8183600401546145e790919063ffffffff16565b8260040181905550505050505b60025481146130d0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f7265656e7472616e742063616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b5050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561315a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806150aa6026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508181600201819055507fd3d22ffd28b02735cf411bd7f925bd8da01212c7028153e0d632e2953ac3088e8383604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a1505050565b6132e881600861463190919063ffffffff16565b5050565b6000808360000160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541415905092915050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f476f6c64546f6b656e00000000000000000000000000000000000000000000008152506009019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b1580156133f457600080fd5b505afa158015613408573d6000803e3d6000fd5b505050506040513d602081101561341e57600080fd5b810190808051906020019092919050505073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461346b5761346a81613591565b5b613473613e62565b61347c81612a80565b613578600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f476f6c64546f6b656e00000000000000000000000000000000000000000000008152506009019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561353857600080fd5b505afa15801561354c573d6000803e3d6000fd5b505050506040513d602081101561356257600080fd5b8101908080519060200190929190505050612a80565b50565b600033905090565b600081600001519050919050565b6135996144d3565b73ffffffffffffffffffffffffffffffffffffffff1663e5839836306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561361557600080fd5b505afa158015613629573d6000803e3d6000fd5b505050506040513d602081101561363f57600080fd5b8101908080519060200190929190505050156136a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602281526020018061516c6022913960400191505060405180910390fd5b60016002600082825401925050819055506000600254905060008290506000600760008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050600073ffffffffffffffffffffffffffffffffffffffff168160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614156137b0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806150d06023913960400191505060405180910390fd5b60006137d382600101604051806020016040529081600082015481525050613583565b141561382a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260288152602001806151c46028913960400191505060405180910390fd5b61383261506c565b61390861390383600401548573ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156138ba57600080fd5b505afa1580156138ce573d6000803e3d6000fd5b505050506040513d60208110156138e457600080fd5b81019080805190602001909291905050506145e790919063ffffffff16565b61481f565b9050600061393d6139388360046040518060200160405290816000820154815250506148a990919063ffffffff16565b614d08565b905061397061395d8261394f85614d08565b6145e790919063ffffffff16565b8460040154614d2990919063ffffffff16565b836004018190555060c881101561398a5750505050613de7565b61399486826110ec565b15613a0c57826003015490507fb1a68b0b66260ca392f760fd4dda4a94818d69c89a4eeb6610eb41db7bab8c378682604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a15b8373ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8460000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b158015613ab757600080fd5b505af1158015613acb573d6000803e3d6000fd5b505050506040513d6020811015613ae157600080fd5b81019080805190602001909291905050505060008360000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060008173ffffffffffffffffffffffffffffffffffffffff166331de7d1589600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f476f6c64546f6b656e00000000000000000000000000000000000000000000008152506009019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015613bf457600080fd5b505afa158015613c08573d6000803e3d6000fd5b505050506040513d6020811015613c1e57600080fd5b810190808051906020019092919050505086613c518a600101604051806020016040529081600082015481525050613583565b6040518563ffffffff1660e01b8152600401808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001838152602001828152602001945050505050602060405180830381600087803b158015613cf457600080fd5b505af1158015613d08573d6000803e3d6000fd5b505050506040513d6020811015613d1e57600080fd5b81019080805190602001909291905050509050613d4681600654614d2990919063ffffffff16565b600681905550613d63838660050154614d2990919063ffffffff16565b8560050181905550613d758884614db1565b7fac094032b4e9dccb3a000eedb94cf30146ca0d7c39be85229f478413fa21d1d88884604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a15050505050505b6002548114613e5e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f7265656e7472616e742063616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b5050565b600060076000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f476f6c64546f6b656e00000000000000000000000000000000000000000000008152506009019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015613f2157600080fd5b505afa158015613f35573d6000803e3d6000fd5b505050506040513d6020811015613f4b57600080fd5b810190808051906020019092919050505073ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f476f6c64546f6b656e00000000000000000000000000000000000000000000008152506009019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561405357600080fd5b505afa158015614067573d6000803e3d6000fd5b505050506040513d602081101561407d57600080fd5b81019080805190602001909291905050509050600047905060006140c26006546140b48660040154856145e790919063ffffffff16565b6145e790919063ffffffff16565b905060006140ff6140fa60046040518060200160405290816000820154815250506140ec8561481f565b6148a990919063ffffffff16565b614d08565b9050600061411860065483614d2990919063ffffffff16565b90508473ffffffffffffffffffffffffffffffffffffffff166342966c68826040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b15801561416d57600080fd5b505af1158015614181573d6000803e3d6000fd5b505050506040513d602081101561419757600080fd5b81019080805190602001909291905050505060006006819055506141da6141c783856145e790919063ffffffff16565b8760040154614d2990919063ffffffff16565b8660040181905550505050505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415614270576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e8152602001806151ec602e913960400191505060405180910390fd5b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050818160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505050565b60008090505b61430b600861447e565b81101561434157600061432882600861448f90919063ffffffff16565b905061433381613591565b508080600101915050614301565b5061434a612401565b614352613e62565b565b600061436083836132ec565b61441957826001018290806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508360000160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506001905061441e565b600090505b92915050565b61442c61506c565b6040518060200160405280838152509050919050565b61444a61506c565b604051806020016040528069d3c21bcecceda1000000815250905090565b6000816000015183600001511115905092915050565b600081600101805490509050919050565b60008260010182815481106144a057fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905092915050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f467265657a6572000000000000000000000000000000000000000000000000008152506007019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561458e57600080fd5b505afa1580156145a2573d6000803e3d6000fd5b505050506040513d60208110156145b857600080fd5b8101908080519060200190929190505050905090565b60008183106145dd57816145df565b825b905092915050565b600061462983836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250614e63565b905092915050565b600061463d83836132ec565b1561481457600060018460000160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020540390506000600185600101805490500390508181146147825760008560010182815481106146b257fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050808660010184815481106146ef57fe5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600183018660000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550505b8460000160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009055846001018054806147d457fe5b6001900381819060005260206000200160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690559055600192505050614819565b600090505b92915050565b61482761506c565b61482f614f23565b821115614887576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603681526020018061518e6036913960400191505060405180910390fd5b604051806020016040528069d3c21bcecceda100000084028152509050919050565b6148b161506c565b6000836000015114806148c8575060008260000151145b156148e457604051806020016040528060008152509050614d02565b69d3c21bcecceda10000008260000151141561490257829050614d02565b69d3c21bcecceda10000008360000151141561492057819050614d02565b600069d3c21bcecceda100000061493685614f42565b600001518161494157fe5b049050600061494f85614f79565b600001519050600069d3c21bcecceda100000061496b86614f42565b600001518161497657fe5b049050600061498486614f79565b6000015190506000828502905060008514614a1857828582816149a357fe5b0414614a17576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6f766572666c6f7720783179312064657465637465640000000000000000000081525060200191505060405180910390fd5b5b600069d3c21bcecceda10000008202905060008214614aba5769d3c21bcecceda1000000828281614a4557fe5b0414614ab9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f6f766572666c6f772078317931202a206669786564312064657465637465640081525060200191505060405180910390fd5b5b8091506000848602905060008614614b4b5784868281614ad657fe5b0414614b4a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6f766572666c6f7720783279312064657465637465640000000000000000000081525060200191505060405180910390fd5b5b6000848802905060008814614bd95784888281614b6457fe5b0414614bd8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6f766572666c6f7720783179322064657465637465640000000000000000000081525060200191505060405180910390fd5b5b614be1614fb6565b8781614be957fe5b049650614bf4614fb6565b8581614bfc57fe5b0494506000858802905060008814614c8d5785888281614c1857fe5b0414614c8c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6f766572666c6f7720783279322064657465637465640000000000000000000081525060200191505060405180910390fd5b5b614c9561506c565b6040518060200160405280878152509050614cbe81604051806020016040528087815250614fc3565b9050614cd881604051806020016040528086815250614fc3565b9050614cf281604051806020016040528085815250614fc3565b9050809a50505050505050505050505b92915050565b600069d3c21bcecceda1000000826000015181614d2157fe5b049050919050565b600080828401905083811015614da7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050600081600201541415614e075750614e5f565b614e1e8282600301546145e790919063ffffffff16565b81600301819055507fcdcea7139bd245b1c7468bc1cfb59ad732b3b0909bafa9f9436ad74c81d0aafb826040518082815260200191505060405180910390a1505b5050565b6000838311158290614f10576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015614ed5578082015181840152602081019050614eba565b50505050905090810190601f168015614f025780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b60007601357c299a88ea76a58924d52ce4f26a85af186c2b9e74905090565b614f4a61506c565b604051806020016040528069d3c21bcecceda100000080856000015181614f6d57fe5b04028152509050919050565b614f8161506c565b604051806020016040528069d3c21bcecceda100000080856000015181614fa457fe5b04028460000151038152509050919050565b600064e8d4a51000905090565b614fcb61506c565b6000826000015184600001510190508360000151811015615054576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f616464206f766572666c6f77206465746563746564000000000000000000000081525060200191505060405180910390fd5b60405180602001604052808281525091505092915050565b604051806020016040528060008152509056fe68616e646c657273206c656e6774682073686f756c64206d6174636820746f6b656e73206c656e6774684f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737348616e646c65722068617320746f2062652073657420746f2073656c6c20746f6b656e6c696d697473206c656e6774682073686f756c64206d6174636820746f6b656e73206c656e6774686d6178536c697070616765206c656e6774682073686f756c64206d6174636820746f6b656e73206c656e67746843616e2774206469737472696275746520746f20746865207a65726f206164647265737363616e27742063616c6c207768656e20636f6e74726163742069732066726f7a656e63616e277420637265617465206669786964697479206e756d626572206c6172676572207468616e206d61784e6577466978656428294d617820736c6970706167652068617320746f2062652073657420746f2073656c6c20746f6b656e43616e2774207365742068616e646c657220746f207a65726f2c207573652064656163746976617465546f6b656e53706c697070616765206d757374206265206c657373207468616e206f7220657175616c20746f20314275726e206672616374696f6e206d757374206265206c657373207468616e206f7220657175616c20746f203148616e646c65722068617320746f2062652073657420746f20616374697661746520746f6b656ea265627a7a72315820557f293af7575e78e686e68bb82eaf3b1ea1d7d79a767906b388ee207322cc7664736f6c634300050d0032