Address Details
contract
0x303ED1df62Fa067659B586EbEe8De0EcE824Ab39
- Contract Name
- BreakerBox
- Creator
- 0x56fd3f–9b8d81 at 0x5fe76e–e522bc
- 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
- 1 Transactions
- Transfers
- 0 Transfers
- Gas Used
- 28,704
- Last Balance Update
- 27807789
This contract has been verified via Sourcify.
View contract in Sourcify repository
- Contract name:
- BreakerBox
- Optimization enabled
- true
- Compiler version
- v0.5.17+commit.d19bba13
- Optimization runs
- 10000
- Verified at
- 2024-03-09T11:11:08.967373Z
lib/mento-core-2.2.0/contracts/oracles/BreakerBox.sol
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.5.13; import { SafeMath } from "openzeppelin-solidity/contracts/math/SafeMath.sol"; import { Ownable } from "openzeppelin-solidity/contracts/ownership/Ownable.sol"; import { IBreakerBox } from "../interfaces/IBreakerBox.sol"; import { IBreaker } from "../interfaces/IBreaker.sol"; import { ISortedOracles } from "../interfaces/ISortedOracles.sol"; import { AddressLinkedList, LinkedList } from "../common/linkedlists/AddressLinkedList.sol"; import { Initializable } from "../common/Initializable.sol"; /** * @title BreakerBox * @notice The BreakerBox checks the criteria defined in separate breaker contracts * to determine whether or not buying or selling should be allowed for a * specified rateFeedIDs. The contract stores references to all breakers * that hold criteria to be checked, rateFeedIDs that * can make use of the BreakerBox & their current trading modes. */ contract BreakerBox is IBreakerBox, Ownable { using SafeMath for uint256; /* ==================== State Variables ==================== */ address[] public rateFeedIDs; // Maps a rate feed to a boolean indicating whether it has been added to the BreakerBox. mapping(address => bool) public rateFeedStatus; // Maps a rate feed to its breakers and their breaker status. (rateFeedID => (breaker => BreakerStatus) mapping(address => mapping(address => BreakerStatus)) public rateFeedBreakerStatus; // Maps a rate feed to the associated trading mode. mapping(address => uint8) public rateFeedTradingMode; // Maps a rate feed to its dependent rate feeds. mapping(address => address[]) public rateFeedDependencies; // Maps a breaker to the associated trading mode it should activate when triggered. mapping(address => uint8) public breakerTradingMode; // List of breakers to be checked. address[] public breakers; // Address of the Mento SortedOracles contract ISortedOracles public sortedOracles; modifier onlyValidBreaker(address breaker, uint64 tradingMode) { require(!isBreaker(breaker), "This breaker has already been added"); require(tradingMode != 0, "The default trading mode can not have a breaker"); _; } /* ==================== Constructor ==================== */ /** * @param _rateFeedIDs rateFeedIDs to be added. * @param _sortedOracles The address of the Celo sorted oracles contract. */ constructor(address[] memory _rateFeedIDs, ISortedOracles _sortedOracles) public { _transferOwnership(msg.sender); setSortedOracles(_sortedOracles); addRateFeeds(_rateFeedIDs); } /* ==================== Mutative Functions ==================== */ /** * @notice Sets the address of the sortedOracles contract. * @param _sortedOracles The new address of the sorted oracles contract. */ function setSortedOracles(ISortedOracles _sortedOracles) public onlyOwner { require(address(_sortedOracles) != address(0), "SortedOracles address must be set"); sortedOracles = _sortedOracles; emit SortedOraclesUpdated(address(_sortedOracles)); } /* ==================== Restricted Functions ==================== */ /* ---------- Breakers ---------- */ /** * @notice Adds a breaker to the end of the list of breakers & the breakerTradingMode mapping. * @param breaker The address of the breaker to be added. * @param tradingMode The trading mode of the breaker to be added. */ function addBreaker(address breaker, uint8 tradingMode) public onlyOwner onlyValidBreaker(breaker, tradingMode) { breakerTradingMode[breaker] = tradingMode; breakers.push(breaker); emit BreakerAdded(breaker); } /** * @notice Removes the specified breaker from the list of breakers * and resets breakerTradingMode mapping + BreakerStatus. * @param breaker The address of the breaker to be removed. */ function removeBreaker(address breaker) external onlyOwner { uint256 breakerIndex = 0; for (uint256 i = 0; i < breakers.length; i++) { if (breakers[i] == breaker) { breakerIndex = i; break; } } require(breakers[breakerIndex] == breaker, "Breaker has not been added"); for (uint256 i = 0; i < rateFeedIDs.length; i++) { if (rateFeedBreakerStatus[rateFeedIDs[i]][breaker].enabled) { toggleBreaker(breaker, rateFeedIDs[i], false); } } delete breakerTradingMode[breaker]; uint256 lastIndex = breakers.length.sub(1); if (breakerIndex != lastIndex) { breakers[breakerIndex] = breakers[lastIndex]; } breakers.pop(); emit BreakerRemoved(breaker); } /** * @notice Enables or disables a breaker for the specified rate feed. * @param breakerAddress The address of the breaker. * @param rateFeedID The address of the rateFeed to be toggled. * @param enable Boolean indicating whether the breaker should be * enabled or disabled for the given rateFeed. */ function toggleBreaker( address breakerAddress, address rateFeedID, bool enable ) public onlyOwner { require(rateFeedStatus[rateFeedID], "Rate feed ID has not been added"); require(isBreaker(breakerAddress), "This breaker has not been added to the BreakerBox"); require(rateFeedBreakerStatus[rateFeedID][breakerAddress].enabled != enable, "Breaker is already in this state"); if (enable) { rateFeedBreakerStatus[rateFeedID][breakerAddress].enabled = enable; _checkAndSetBreakers(rateFeedID); } else { delete rateFeedBreakerStatus[rateFeedID][breakerAddress]; uint8 tradingMode = calculateTradingMode(rateFeedID); setRateFeedTradingMode(rateFeedID, tradingMode); } emit BreakerStatusUpdated(breakerAddress, rateFeedID, enable); } /** * @dev Calculates the trading mode for a given rate feed by applying * a logical OR on the trading modes of all enabled breakers. * @param rateFeedId The address of the rate feed. */ function calculateTradingMode(address rateFeedId) internal view returns (uint8) { uint8 tradingMode = 0; for (uint256 i = 0; i < breakers.length; i++) { if (rateFeedBreakerStatus[rateFeedId][breakers[i]].enabled) { tradingMode = tradingMode | rateFeedBreakerStatus[rateFeedId][breakers[i]].tradingMode; } } return tradingMode; } /* ---------- rateFeedIDs ---------- */ /** * @notice Adds a rateFeedID to the mapping of monitored rateFeedIDs. * @param rateFeedID The address of the rateFeed to be added. */ function addRateFeed(address rateFeedID) public onlyOwner { require(!rateFeedStatus[rateFeedID], "Rate feed ID has already been added"); require(sortedOracles.getOracles(rateFeedID).length > 0, "Rate feed ID does not exist as it has 0 oracles"); rateFeedIDs.push(rateFeedID); rateFeedStatus[rateFeedID] = true; emit RateFeedAdded(rateFeedID); } /** * @notice Adds the specified rateFeedIDs to the mapping of monitored rateFeedIDs. * @param newRateFeedIDs The array of rateFeed addresses to be added. */ function addRateFeeds(address[] memory newRateFeedIDs) public onlyOwner { for (uint256 i = 0; i < newRateFeedIDs.length; i++) { addRateFeed(newRateFeedIDs[i]); } } /** * @notice Sets dependent rate feeds for a given rate feed. * @param rateFeedID The address of the rate feed. * @param dependencies The array of dependent rate feeds. */ function setRateFeedDependencies(address rateFeedID, address[] calldata dependencies) external onlyOwner { require(rateFeedStatus[rateFeedID], "Rate feed ID has not been added"); rateFeedDependencies[rateFeedID] = dependencies; emit RateFeedDependenciesSet(rateFeedID, dependencies); } /** * @notice Removes a rateFeed from the mapping of monitored rateFeeds * and resets all the BreakerStatus entries for that rateFeed. * @param rateFeedID The address of the rateFeed to be removed. */ function removeRateFeed(address rateFeedID) external onlyOwner { uint256 rateFeedIndex = 0; for (uint256 i = 0; i < rateFeedIDs.length; i++) { if (rateFeedIDs[i] == rateFeedID) { rateFeedIndex = i; break; } } require(rateFeedIDs[rateFeedIndex] == rateFeedID, "Rate feed ID has not been added"); uint256 lastIndex = rateFeedIDs.length.sub(1); if (rateFeedIndex != lastIndex) { rateFeedIDs[rateFeedIndex] = rateFeedIDs[lastIndex]; } rateFeedIDs.pop(); delete rateFeedDependencies[rateFeedID]; delete rateFeedTradingMode[rateFeedID]; deleteBreakerStatus(rateFeedID); rateFeedStatus[rateFeedID] = false; emit RateFeedRemoved(rateFeedID); } /** * @notice Sets the trading mode for the specified rateFeed. * @param rateFeedID The address of the rateFeed. * @param tradingMode The trading mode that should be set. */ function setRateFeedTradingMode(address rateFeedID, uint8 tradingMode) public onlyOwner { require(rateFeedStatus[rateFeedID], "Rate feed ID has not been added"); rateFeedTradingMode[rateFeedID] = tradingMode; emit TradingModeUpdated(rateFeedID, tradingMode); } /** * @notice Resets all the BreakerStatus entries for the specified rateFeed. * @param rateFeedID The address of the rateFeed. */ function deleteBreakerStatus(address rateFeedID) internal { for (uint256 i = 0; i < breakers.length; i++) { if (rateFeedBreakerStatus[rateFeedID][breakers[i]].enabled) { delete rateFeedBreakerStatus[rateFeedID][breakers[i]]; } } } /* ==================== View Functions ==================== */ /** * @notice Returns an array of breaker addresses from start to end. * @return An ordered list of breakers. */ function getBreakers() external view returns (address[] memory) { return breakers; } /** * @notice Checks whether a breaker with the specifed address has been added. */ function isBreaker(address breaker) public view returns (bool) { for (uint256 i = 0; i < breakers.length; i++) { if (breakers[i] == breaker) { return true; } } return false; } /** * @notice Returns addresses of rateFeedIDs that have been added. */ function getRateFeeds() external view returns (address[] memory) { return rateFeedIDs; } /** * @notice Returns the trading mode for the specified rateFeedID. * @param rateFeedID The address of the rateFeed to retrieve the trading mode for. */ function getRateFeedTradingMode(address rateFeedID) external view returns (uint8) { require(rateFeedStatus[rateFeedID], "Rate feed ID has not been added"); uint8 tradingMode = rateFeedTradingMode[rateFeedID]; for (uint256 i = 0; i < rateFeedDependencies[rateFeedID].length; i++) { tradingMode = tradingMode | rateFeedTradingMode[rateFeedDependencies[rateFeedID][i]]; } return tradingMode; } /** * @notice Checks if a breaker is enabled for a specific rate feed. * @param breaker The address of the breaker we're checking for. * @param rateFeedID The address of the rateFeed. */ function isBreakerEnabled(address breaker, address rateFeedID) external view returns (bool) { return rateFeedBreakerStatus[rateFeedID][breaker].enabled; } /* ==================== Check Breakers ==================== */ /** * @notice Checks breakers for the rateFeedID with the specified id and sets correct trading mode if any breakers are tripped or need to be reset. * @param rateFeedID The address of the rateFeed to run checks for. */ function checkAndSetBreakers(address rateFeedID) external { require(msg.sender == address(sortedOracles), "Caller must be the SortedOracles contract"); _checkAndSetBreakers(rateFeedID); } /** * @notice Checks breakers for the rateFeedID with the specified id and sets correct trading mode if any breakers are tripped or need to be reset. * @param rateFeedID The address of the rateFeed to run checks for. */ function _checkAndSetBreakers(address rateFeedID) internal { uint8 _tradingMode = 0; for (uint256 i = 0; i < breakers.length; i++) { if (rateFeedBreakerStatus[rateFeedID][breakers[i]].enabled) { uint8 _breakerTradingMode = updateBreaker(rateFeedID, breakers[i]); _tradingMode = _tradingMode | _breakerTradingMode; } } rateFeedTradingMode[rateFeedID] = _tradingMode; } /** * @notice Gets the updated breaker trading mode for a specific rateFeed. * @param rateFeedID The address of the rateFeed. * @param breaker The address of the breaker to update. */ function updateBreaker(address rateFeedID, address breaker) internal returns (uint8) { if (rateFeedBreakerStatus[rateFeedID][breaker].tradingMode != 0) { return tryResetBreaker(rateFeedID, breaker); } return checkBreaker(rateFeedID, breaker); } /** * @notice Tries to reset a breaker if the cooldown has passed. * @param rateFeedID The address of the rateFeed to run checks for. * @param _breaker The address of the breaker to reset. */ function tryResetBreaker(address rateFeedID, address _breaker) internal returns (uint8) { BreakerStatus memory _breakerStatus = rateFeedBreakerStatus[rateFeedID][_breaker]; IBreaker breaker = IBreaker(_breaker); uint256 cooldown = breaker.getCooldown(rateFeedID); // If the cooldown == 0, then a manual reset is required. if ((cooldown > 0) && (block.timestamp >= cooldown.add(_breakerStatus.lastUpdatedTime))) { if (breaker.shouldReset(rateFeedID)) { rateFeedBreakerStatus[rateFeedID][_breaker].tradingMode = 0; rateFeedBreakerStatus[rateFeedID][_breaker].lastUpdatedTime = uint64(block.timestamp); emit ResetSuccessful(rateFeedID, _breaker); } else { emit ResetAttemptCriteriaFail(rateFeedID, _breaker); } } else { emit ResetAttemptNotCool(rateFeedID, _breaker); } return rateFeedBreakerStatus[rateFeedID][_breaker].tradingMode; } /** * @notice Checks if a breaker tripped. * @param rateFeedID The address of the rateFeed to run checks for. * @param _breaker The address of the breaker to check. */ function checkBreaker(address rateFeedID, address _breaker) internal returns (uint8) { uint8 tradingMode = 0; IBreaker breaker = IBreaker(_breaker); if (breaker.shouldTrigger(rateFeedID)) { tradingMode = breakerTradingMode[_breaker]; rateFeedBreakerStatus[rateFeedID][_breaker].tradingMode = tradingMode; rateFeedBreakerStatus[rateFeedID][_breaker].lastUpdatedTime = uint64(block.timestamp); emit BreakerTripped(_breaker, rateFeedID); } return tradingMode; } }
/lib/mento-core-2.0.0/lib/openzeppelin-contracts/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; } }
/lib/mento-core-2.0.0/lib/openzeppelin-contracts/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; } }
/lib/mento-core-2.0.0/lib/openzeppelin-contracts/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; } }
/lib/mento-core-2.2.0/contracts/common/Initializable.sol
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.5.13; contract Initializable { bool public initialized; constructor(bool testingDeployment) public { if (!testingDeployment) { initialized = true; } } modifier initializer() { require(!initialized, "contract already initialized"); initialized = true; _; } }
/lib/mento-core-2.2.0/contracts/common/linkedlists/AddressLinkedList.sol
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.5.13; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; import "./LinkedList.sol"; /** * @title Maintains a doubly linked list keyed by address. * @dev Following the `next` pointers will lead you to the head, rather than the tail. */ library AddressLinkedList { using LinkedList for LinkedList.List; using SafeMath for uint256; function toBytes(address a) public pure returns (bytes32) { return bytes32(uint256(a) << 96); } function toAddress(bytes32 b) public pure returns (address) { return address(uint256(b) >> 96); } /** * @notice Inserts an element into a doubly linked list. * @param list A storage pointer to the underlying list. * @param key The key of the element to insert. * @param previousKey The key of the element that comes before the element to insert. * @param nextKey The key of the element that comes after the element to insert. */ function insert( LinkedList.List storage list, address key, address previousKey, address nextKey ) public { list.insert(toBytes(key), toBytes(previousKey), toBytes(nextKey)); } /** * @notice Inserts an element at the end of the doubly linked list. * @param list A storage pointer to the underlying list. * @param key The key of the element to insert. */ function push(LinkedList.List storage list, address key) public { list.insert(toBytes(key), bytes32(0), list.tail); } /** * @notice Removes an element from the doubly linked list. * @param list A storage pointer to the underlying list. * @param key The key of the element to remove. */ function remove(LinkedList.List storage list, address key) public { list.remove(toBytes(key)); } /** * @notice Updates an element in the list. * @param list A storage pointer to the underlying list. * @param key The element key. * @param previousKey The key of the element that comes before the updated element. * @param nextKey The key of the element that comes after the updated element. */ function update( LinkedList.List storage list, address key, address previousKey, address nextKey ) public { list.update(toBytes(key), toBytes(previousKey), toBytes(nextKey)); } /** * @notice Returns whether or not a particular key is present in the sorted list. * @param list A storage pointer to the underlying list. * @param key The element key. * @return Whether or not the key is in the sorted list. */ function contains(LinkedList.List storage list, address key) public view returns (bool) { return list.elements[toBytes(key)].exists; } /** * @notice Returns the N greatest elements of the list. * @param list A storage pointer to the underlying list. * @param n The number of elements to return. * @return The keys of the greatest elements. * @dev Reverts if n is greater than the number of elements in the list. */ function headN(LinkedList.List storage list, uint256 n) public view returns (address[] memory) { bytes32[] memory byteKeys = list.headN(n); address[] memory keys = new address[](n); for (uint256 i = 0; i < n; i = i.add(1)) { keys[i] = toAddress(byteKeys[i]); } return keys; } /** * @notice Gets all element keys from the doubly linked list. * @param list A storage pointer to the underlying list. * @return All element keys from head to tail. */ function getKeys(LinkedList.List storage list) public view returns (address[] memory) { return headN(list, list.numElements); } }
/lib/mento-core-2.2.0/contracts/common/linkedlists/LinkedList.sol
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.5.13; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; /** * @title Maintains a doubly linked list keyed by bytes32. * @dev Following the `next` pointers will lead you to the head, rather than the tail. */ library LinkedList { using SafeMath for uint256; struct Element { bytes32 previousKey; bytes32 nextKey; bool exists; } struct List { bytes32 head; bytes32 tail; uint256 numElements; mapping(bytes32 => Element) elements; } /** * @notice Inserts an element into a doubly linked list. * @param list A storage pointer to the underlying list. * @param key The key of the element to insert. * @param previousKey The key of the element that comes before the element to insert. * @param nextKey The key of the element that comes after the element to insert. */ function insert( List storage list, bytes32 key, bytes32 previousKey, bytes32 nextKey ) internal { require(key != bytes32(0), "Key must be defined"); require(!contains(list, key), "Can't insert an existing element"); require(previousKey != key && nextKey != key, "Key cannot be the same as previousKey or nextKey"); Element storage element = list.elements[key]; element.exists = true; if (list.numElements == 0) { list.tail = key; list.head = key; } else { require(previousKey != bytes32(0) || nextKey != bytes32(0), "Either previousKey or nextKey must be defined"); element.previousKey = previousKey; element.nextKey = nextKey; if (previousKey != bytes32(0)) { require(contains(list, previousKey), "If previousKey is defined, it must exist in the list"); Element storage previousElement = list.elements[previousKey]; require(previousElement.nextKey == nextKey, "previousKey must be adjacent to nextKey"); previousElement.nextKey = key; } else { list.tail = key; } if (nextKey != bytes32(0)) { require(contains(list, nextKey), "If nextKey is defined, it must exist in the list"); Element storage nextElement = list.elements[nextKey]; require(nextElement.previousKey == previousKey, "previousKey must be adjacent to nextKey"); nextElement.previousKey = key; } else { list.head = key; } } list.numElements = list.numElements.add(1); } /** * @notice Inserts an element at the tail of the doubly linked list. * @param list A storage pointer to the underlying list. * @param key The key of the element to insert. */ function push(List storage list, bytes32 key) internal { insert(list, key, bytes32(0), list.tail); } /** * @notice Removes an element from the doubly linked list. * @param list A storage pointer to the underlying list. * @param key The key of the element to remove. */ function remove(List storage list, bytes32 key) internal { Element storage element = list.elements[key]; require(key != bytes32(0) && contains(list, key), "key not in list"); if (element.previousKey != bytes32(0)) { Element storage previousElement = list.elements[element.previousKey]; previousElement.nextKey = element.nextKey; } else { list.tail = element.nextKey; } if (element.nextKey != bytes32(0)) { Element storage nextElement = list.elements[element.nextKey]; nextElement.previousKey = element.previousKey; } else { list.head = element.previousKey; } delete list.elements[key]; list.numElements = list.numElements.sub(1); } /** * @notice Updates an element in the list. * @param list A storage pointer to the underlying list. * @param key The element key. * @param previousKey The key of the element that comes before the updated element. * @param nextKey The key of the element that comes after the updated element. */ function update( List storage list, bytes32 key, bytes32 previousKey, bytes32 nextKey ) internal { require(key != bytes32(0) && key != previousKey && key != nextKey && contains(list, key), "key on in list"); remove(list, key); insert(list, key, previousKey, nextKey); } /** * @notice Returns whether or not a particular key is present in the sorted list. * @param list A storage pointer to the underlying list. * @param key The element key. * @return Whether or not the key is in the sorted list. */ function contains(List storage list, bytes32 key) internal view returns (bool) { return list.elements[key].exists; } /** * @notice Returns the keys of the N elements at the head of the list. * @param list A storage pointer to the underlying list. * @param n The number of elements to return. * @return The keys of the N elements at the head of the list. * @dev Reverts if n is greater than the number of elements in the list. */ function headN(List storage list, uint256 n) internal view returns (bytes32[] memory) { require(n <= list.numElements, "not enough elements"); bytes32[] memory keys = new bytes32[](n); bytes32 key = list.head; for (uint256 i = 0; i < n; i = i.add(1)) { keys[i] = key; key = list.elements[key].previousKey; } return keys; } /** * @notice Gets all element keys from the doubly linked list. * @param list A storage pointer to the underlying list. * @return All element keys from head to tail. */ function getKeys(List storage list) internal view returns (bytes32[] memory) { return headN(list, list.numElements); } }
/lib/mento-core-2.2.0/contracts/common/linkedlists/SortedLinkedList.sol
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.5.13; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; import "./LinkedList.sol"; /** * @title Maintains a sorted list of unsigned ints keyed by bytes32. */ library SortedLinkedList { using SafeMath for uint256; using LinkedList for LinkedList.List; struct List { LinkedList.List list; mapping(bytes32 => uint256) values; } /** * @notice Inserts an element into a doubly linked list. * @param list A storage pointer to the underlying list. * @param key The key of the element to insert. * @param value The element value. * @param lesserKey The key of the element less than the element to insert. * @param greaterKey The key of the element greater than the element to insert. */ function insert( List storage list, bytes32 key, uint256 value, bytes32 lesserKey, bytes32 greaterKey ) internal { require(key != bytes32(0) && key != lesserKey && key != greaterKey && !contains(list, key), "invalid key"); require( (lesserKey != bytes32(0) || greaterKey != bytes32(0)) || list.list.numElements == 0, "greater and lesser key zero" ); require(contains(list, lesserKey) || lesserKey == bytes32(0), "invalid lesser key"); require(contains(list, greaterKey) || greaterKey == bytes32(0), "invalid greater key"); (lesserKey, greaterKey) = getLesserAndGreater(list, value, lesserKey, greaterKey); list.list.insert(key, lesserKey, greaterKey); list.values[key] = value; } /** * @notice Removes an element from the doubly linked list. * @param list A storage pointer to the underlying list. * @param key The key of the element to remove. */ function remove(List storage list, bytes32 key) internal { list.list.remove(key); list.values[key] = 0; } /** * @notice Updates an element in the list. * @param list A storage pointer to the underlying list. * @param key The element key. * @param value The element value. * @param lesserKey The key of the element will be just left of `key` after the update. * @param greaterKey The key of the element will be just right of `key` after the update. * @dev Note that only one of "lesserKey" or "greaterKey" needs to be correct to reduce friction. */ function update( List storage list, bytes32 key, uint256 value, bytes32 lesserKey, bytes32 greaterKey ) internal { remove(list, key); insert(list, key, value, lesserKey, greaterKey); } /** * @notice Inserts an element at the tail of the doubly linked list. * @param list A storage pointer to the underlying list. * @param key The key of the element to insert. */ function push(List storage list, bytes32 key) internal { insert(list, key, 0, bytes32(0), list.list.tail); } /** * @notice Removes N elements from the head of the list and returns their keys. * @param list A storage pointer to the underlying list. * @param n The number of elements to pop. * @return The keys of the popped elements. */ function popN(List storage list, uint256 n) internal returns (bytes32[] memory) { require(n <= list.list.numElements, "not enough elements"); bytes32[] memory keys = new bytes32[](n); for (uint256 i = 0; i < n; i = i.add(1)) { bytes32 key = list.list.head; keys[i] = key; remove(list, key); } return keys; } /** * @notice Returns whether or not a particular key is present in the sorted list. * @param list A storage pointer to the underlying list. * @param key The element key. * @return Whether or not the key is in the sorted list. */ function contains(List storage list, bytes32 key) internal view returns (bool) { return list.list.contains(key); } /** * @notice Returns the value for a particular key in the sorted list. * @param list A storage pointer to the underlying list. * @param key The element key. * @return The element value. */ function getValue(List storage list, bytes32 key) internal view returns (uint256) { return list.values[key]; } /** * @notice Gets all elements from the doubly linked list. * @param list A storage pointer to the underlying list. * @return Array of all keys in the list. * @return Values corresponding to keys, which will be ordered largest to smallest. */ function getElements(List storage list) internal view returns (bytes32[] memory, uint256[] memory) { bytes32[] memory keys = getKeys(list); uint256[] memory values = new uint256[](keys.length); for (uint256 i = 0; i < keys.length; i = i.add(1)) { values[i] = list.values[keys[i]]; } return (keys, values); } /** * @notice Gets all element keys from the doubly linked list. * @param list A storage pointer to the underlying list. * @return All element keys from head to tail. */ function getKeys(List storage list) internal view returns (bytes32[] memory) { return list.list.getKeys(); } /** * @notice Returns first N greatest elements of the list. * @param list A storage pointer to the underlying list. * @param n The number of elements to return. * @return The keys of the first n elements. * @dev Reverts if n is greater than the number of elements in the list. */ function headN(List storage list, uint256 n) internal view returns (bytes32[] memory) { return list.list.headN(n); } /** * @notice Returns the keys of the elements greaterKey than and less than the provided value. * @param list A storage pointer to the underlying list. * @param value The element value. * @param lesserKey The key of the element which could be just left of the new value. * @param greaterKey The key of the element which could be just right of the new value. * @return The correct lesserKey keys. * @return The correct greaterKey keys. */ function getLesserAndGreater( List storage list, uint256 value, bytes32 lesserKey, bytes32 greaterKey ) private view returns (bytes32, bytes32) { // Check for one of the following conditions and fail if none are met: // 1. The value is less than the current lowest value // 2. The value is greater than the current greatest value // 3. The value is just greater than the value for `lesserKey` // 4. The value is just less than the value for `greaterKey` if (lesserKey == bytes32(0) && isValueBetween(list, value, lesserKey, list.list.tail)) { return (lesserKey, list.list.tail); } else if (greaterKey == bytes32(0) && isValueBetween(list, value, list.list.head, greaterKey)) { return (list.list.head, greaterKey); } else if ( lesserKey != bytes32(0) && isValueBetween(list, value, lesserKey, list.list.elements[lesserKey].nextKey) ) { return (lesserKey, list.list.elements[lesserKey].nextKey); } else if ( greaterKey != bytes32(0) && isValueBetween(list, value, list.list.elements[greaterKey].previousKey, greaterKey) ) { return (list.list.elements[greaterKey].previousKey, greaterKey); } else { require(false, "get lesser and greater failure"); } } /** * @notice Returns whether or not a given element is between two other elements. * @param list A storage pointer to the underlying list. * @param value The element value. * @param lesserKey The key of the element whose value should be lesserKey. * @param greaterKey The key of the element whose value should be greaterKey. * @return True if the given element is between the two other elements. */ function isValueBetween( List storage list, uint256 value, bytes32 lesserKey, bytes32 greaterKey ) private view returns (bool) { bool isLesser = lesserKey == bytes32(0) || list.values[lesserKey] <= value; bool isGreater = greaterKey == bytes32(0) || list.values[greaterKey] >= value; return isLesser && isGreater; } }
/lib/mento-core-2.2.0/contracts/common/linkedlists/SortedLinkedListWithMedian.sol
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.5.13; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; import "./LinkedList.sol"; import "./SortedLinkedList.sol"; /** * @title Maintains a sorted list of unsigned ints keyed by bytes32. */ library SortedLinkedListWithMedian { using SafeMath for uint256; using SortedLinkedList for SortedLinkedList.List; enum MedianAction { None, Lesser, Greater } enum MedianRelation { Undefined, Lesser, Greater, Equal } struct List { SortedLinkedList.List list; bytes32 median; mapping(bytes32 => MedianRelation) relation; } /** * @notice Inserts an element into a doubly linked list. * @param list A storage pointer to the underlying list. * @param key The key of the element to insert. * @param value The element value. * @param lesserKey The key of the element less than the element to insert. * @param greaterKey The key of the element greater than the element to insert. */ function insert( List storage list, bytes32 key, uint256 value, bytes32 lesserKey, bytes32 greaterKey ) internal { list.list.insert(key, value, lesserKey, greaterKey); LinkedList.Element storage element = list.list.list.elements[key]; MedianAction action = MedianAction.None; if (list.list.list.numElements == 1) { list.median = key; list.relation[key] = MedianRelation.Equal; } else if (list.list.list.numElements % 2 == 1) { // When we have an odd number of elements, and the element that we inserted is less than // the previous median, we need to slide the median down one element, since we had previously // selected the greater of the two middle elements. if (element.previousKey == bytes32(0) || list.relation[element.previousKey] == MedianRelation.Lesser) { action = MedianAction.Lesser; list.relation[key] = MedianRelation.Lesser; } else { list.relation[key] = MedianRelation.Greater; } } else { // When we have an even number of elements, and the element that we inserted is greater than // the previous median, we need to slide the median up one element, since we always select // the greater of the two middle elements. if (element.nextKey == bytes32(0) || list.relation[element.nextKey] == MedianRelation.Greater) { action = MedianAction.Greater; list.relation[key] = MedianRelation.Greater; } else { list.relation[key] = MedianRelation.Lesser; } } updateMedian(list, action); } /** * @notice Removes an element from the doubly linked list. * @param list A storage pointer to the underlying list. * @param key The key of the element to remove. */ function remove(List storage list, bytes32 key) internal { MedianAction action = MedianAction.None; if (list.list.list.numElements == 0) { list.median = bytes32(0); } else if (list.list.list.numElements % 2 == 0) { // When we have an even number of elements, we always choose the higher of the two medians. // Thus, if the element we're removing is greaterKey than or equal to the median we need to // slide the median left by one. if (list.relation[key] == MedianRelation.Greater || list.relation[key] == MedianRelation.Equal) { action = MedianAction.Lesser; } } else { // When we don't have an even number of elements, we just choose the median value. // Thus, if the element we're removing is less than or equal to the median, we need to slide // median right by one. if (list.relation[key] == MedianRelation.Lesser || list.relation[key] == MedianRelation.Equal) { action = MedianAction.Greater; } } updateMedian(list, action); list.list.remove(key); } /** * @notice Updates an element in the list. * @param list A storage pointer to the underlying list. * @param key The element key. * @param value The element value. * @param lesserKey The key of the element will be just left of `key` after the update. * @param greaterKey The key of the element will be just right of `key` after the update. * @dev Note that only one of "lesserKey" or "greaterKey" needs to be correct to reduce friction. */ function update( List storage list, bytes32 key, uint256 value, bytes32 lesserKey, bytes32 greaterKey ) internal { remove(list, key); insert(list, key, value, lesserKey, greaterKey); } /** * @notice Inserts an element at the tail of the doubly linked list. * @param list A storage pointer to the underlying list. * @param key The key of the element to insert. */ function push(List storage list, bytes32 key) internal { insert(list, key, 0, bytes32(0), list.list.list.tail); } /** * @notice Removes N elements from the head of the list and returns their keys. * @param list A storage pointer to the underlying list. * @param n The number of elements to pop. * @return The keys of the popped elements. */ function popN(List storage list, uint256 n) internal returns (bytes32[] memory) { require(n <= list.list.list.numElements, "not enough elements"); bytes32[] memory keys = new bytes32[](n); for (uint256 i = 0; i < n; i = i.add(1)) { bytes32 key = list.list.list.head; keys[i] = key; remove(list, key); } return keys; } /** * @notice Returns whether or not a particular key is present in the sorted list. * @param list A storage pointer to the underlying list. * @param key The element key. * @return Whether or not the key is in the sorted list. */ function contains(List storage list, bytes32 key) internal view returns (bool) { return list.list.contains(key); } /** * @notice Returns the value for a particular key in the sorted list. * @param list A storage pointer to the underlying list. * @param key The element key. * @return The element value. */ function getValue(List storage list, bytes32 key) internal view returns (uint256) { return list.list.values[key]; } /** * @notice Returns the median value of the sorted list. * @param list A storage pointer to the underlying list. * @return The median value. */ function getMedianValue(List storage list) internal view returns (uint256) { return getValue(list, list.median); } /** * @notice Returns the key of the first element in the list. * @param list A storage pointer to the underlying list. * @return The key of the first element in the list. */ function getHead(List storage list) internal view returns (bytes32) { return list.list.list.head; } /** * @notice Returns the key of the median element in the list. * @param list A storage pointer to the underlying list. * @return The key of the median element in the list. */ function getMedian(List storage list) internal view returns (bytes32) { return list.median; } /** * @notice Returns the key of the last element in the list. * @param list A storage pointer to the underlying list. * @return The key of the last element in the list. */ function getTail(List storage list) internal view returns (bytes32) { return list.list.list.tail; } /** * @notice Returns the number of elements in the list. * @param list A storage pointer to the underlying list. * @return The number of elements in the list. */ function getNumElements(List storage list) internal view returns (uint256) { return list.list.list.numElements; } /** * @notice Gets all elements from the doubly linked list. * @param list A storage pointer to the underlying list. * @return Array of all keys in the list. * @return Values corresponding to keys, which will be ordered largest to smallest. * @return Array of relations to median of corresponding list elements. */ function getElements(List storage list) internal view returns ( bytes32[] memory, uint256[] memory, MedianRelation[] memory ) { bytes32[] memory keys = getKeys(list); uint256[] memory values = new uint256[](keys.length); MedianRelation[] memory relations = new MedianRelation[](keys.length); for (uint256 i = 0; i < keys.length; i = i.add(1)) { values[i] = list.list.values[keys[i]]; relations[i] = list.relation[keys[i]]; } return (keys, values, relations); } /** * @notice Gets all element keys from the doubly linked list. * @param list A storage pointer to the underlying list. * @return All element keys from head to tail. */ function getKeys(List storage list) internal view returns (bytes32[] memory) { return list.list.getKeys(); } /** * @notice Moves the median pointer right or left of its current value. * @param list A storage pointer to the underlying list. * @param action Which direction to move the median pointer. */ function updateMedian(List storage list, MedianAction action) private { LinkedList.Element storage previousMedian = list.list.list.elements[list.median]; if (action == MedianAction.Lesser) { list.relation[list.median] = MedianRelation.Greater; list.median = previousMedian.previousKey; } else if (action == MedianAction.Greater) { list.relation[list.median] = MedianRelation.Lesser; list.median = previousMedian.nextKey; } list.relation[list.median] = MedianRelation.Equal; } }
/lib/mento-core-2.2.0/contracts/interfaces/IBreaker.sol
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.5.13; /** * @title Breaker Interface * @notice Defines the basic interface for a Breaker */ interface IBreaker { /** * @notice Emitted when the sortedOracles address is updated. * @param newSortedOracles The address of the new sortedOracles. */ event SortedOraclesUpdated(address newSortedOracles); /** * @notice Retrieve the cooldown time for the breaker. * @param rateFeedID The rate feed to get the cooldown for * @return cooldown The amount of time that must pass before the breaker can reset. * @dev when cooldown is 0 auto reset will not be attempted. */ function getCooldown(address rateFeedID) external view returns (uint256 cooldown); /** * @notice Check if the criteria have been met, by a specified rateFeedID, to trigger the breaker. * @param rateFeedID The address of the rate feed to run the check against. * @return triggerBreaker A boolean indicating whether or not the breaker * should be triggered for the given rate feed. */ function shouldTrigger(address rateFeedID) external returns (bool triggerBreaker); /** * @notice Check if the criteria to automatically reset the breaker have been met. * @param rateFeedID The address of rate feed the criteria should be checked against. * @return resetBreaker A boolean indicating whether the breaker * should be reset for the given rate feed. * @dev Allows the definition of additional critera to check before reset. * If no additional criteria is needed set to !shouldTrigger(); */ function shouldReset(address rateFeedID) external returns (bool resetBreaker); }
/lib/mento-core-2.2.0/contracts/interfaces/IBreakerBox.sol
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.5.13; /** * @title Breaker Box Interface * @notice Defines the basic interface for the Breaker Box */ interface IBreakerBox { /** * @dev Used to keep track of the status of a breaker for a specific rate feed. * * - TradingMode: Represents the trading mode the breaker is in for a rate feed. * This uses a bitmask approach, meaning each bit represents a * different trading mode. The final trading mode of the rate feed * is obtained by applying a logical OR operation to the TradingMode * of all breakers associated with that rate feed. This allows multiple * breakers to contribute to the final trading mode simultaneously. * Possible values: * 0: bidirectional trading. * 1: inflow only. * 2: outflow only. * 3: trading halted. * * - LastUpdatedTime: Records the last time the breaker status was updated. This is * used to manage cooldown periods before the breaker can be reset. * * - Enabled: Indicates whether the breaker is enabled for the associated rate feed. */ struct BreakerStatus { uint8 tradingMode; uint64 lastUpdatedTime; bool enabled; } /** * @notice Emitted when a new breaker is added to the breaker box. * @param breaker The address of the breaker. */ event BreakerAdded(address indexed breaker); /** * @notice Emitted when a breaker is removed from the breaker box. * @param breaker The address of the breaker. */ event BreakerRemoved(address indexed breaker); /** * @notice Emitted when a breaker is tripped by a rate feed. * @param breaker The address of the breaker. * @param rateFeedID The address of the rate feed. */ event BreakerTripped(address indexed breaker, address indexed rateFeedID); /** * @notice Emitted when a new rate feed is added to the breaker box. * @param rateFeedID The address of the rate feed. */ event RateFeedAdded(address indexed rateFeedID); /** * @notice Emitted when dependencies for a rate feed are set. * @param rateFeedID The address of the rate feed. * @param dependencies The addresses of the dependendent rate feeds. */ event RateFeedDependenciesSet(address indexed rateFeedID, address[] indexed dependencies); /** * @notice Emitted when a rate feed is removed from the breaker box. * @param rateFeedID The address of the rate feed. */ event RateFeedRemoved(address indexed rateFeedID); /** * @notice Emitted when the trading mode for a rate feed is updated * @param rateFeedID The address of the rate feed. * @param tradingMode The new trading mode. */ event TradingModeUpdated(address indexed rateFeedID, uint256 tradingMode); /** * @notice Emitted after a reset attempt is successful. * @param rateFeedID The address of the rate feed. * @param breaker The address of the breaker. */ event ResetSuccessful(address indexed rateFeedID, address indexed breaker); /** * @notice Emitted after a reset attempt fails when the * rate feed fails the breakers reset criteria. * @param rateFeedID The address of the rate feed. * @param breaker The address of the breaker. */ event ResetAttemptCriteriaFail(address indexed rateFeedID, address indexed breaker); /** * @notice Emitted after a reset attempt fails when cooldown time has not elapsed. * @param rateFeedID The address of the rate feed. * @param breaker The address of the breaker. */ event ResetAttemptNotCool(address indexed rateFeedID, address indexed breaker); /** * @notice Emitted when the sortedOracles address is updated. * @param newSortedOracles The address of the new sortedOracles. */ event SortedOraclesUpdated(address indexed newSortedOracles); /** * @notice Emitted when the breaker is enabled or disabled for a rate feed. * @param breaker The address of the breaker. * @param rateFeedID The address of the rate feed. * @param status Indicating the status. */ event BreakerStatusUpdated(address breaker, address rateFeedID, bool status); /** * @notice Retrives an array of all breaker addresses. */ function getBreakers() external view returns (address[] memory); /** * @notice Checks if a breaker with the specified address has been added to the breaker box. * @param breaker The address of the breaker to check; * @return A bool indicating whether or not the breaker has been added. */ function isBreaker(address breaker) external view returns (bool); /** * @notice Checks breakers for the rateFeedID and sets correct trading mode * if any breakers are tripped or need to be reset. * @param rateFeedID The address of the rate feed to run checks for. */ function checkAndSetBreakers(address rateFeedID) external; /** * @notice Gets the trading mode for the specified rateFeedID. * @param rateFeedID The address of the rate feed to retrieve the trading mode for. */ function getRateFeedTradingMode(address rateFeedID) external view returns (uint8 tradingMode); }
/lib/mento-core-2.2.0/contracts/interfaces/ISortedOracles.sol
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.5.13; import "../common/linkedlists/SortedLinkedListWithMedian.sol"; 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); function getOracles(address) external view returns (address[] memory); function getTimestamps(address token) external view returns ( address[] memory, uint256[] memory, SortedLinkedListWithMedian.MedianRelation[] memory ); }
Compiler Settings
{"remappings":[":celo-foundry/=lib/celo-foundry/src/",":contracts/=contracts/",":ds-test/=lib/celo-foundry/lib/forge-std/lib/ds-test/src/",":forge-std-next/=lib/mento-core-2.2.0/lib/forge-std-next/src/",":forge-std/=lib/celo-foundry/lib/forge-std/src/",":mento-core-2.0.0/=lib/mento-core-2.0.0/contracts/",":mento-core-2.1.0/=lib/mento-core-2.1.0/contracts/",":mento-core-2.2.0/=lib/mento-core-2.2.0/contracts/",":openzeppelin-contracts-next/=lib/mento-core-2.2.0/lib/openzeppelin-contracts-next/",":openzeppelin-contracts-upgradeable/=lib/mento-core-2.2.0/lib/openzeppelin-contracts-upgradeable/",":openzeppelin-contracts/=lib/mento-core-2.0.0/lib/openzeppelin-contracts/contracts/",":openzeppelin-solidity/=lib/mento-core-2.0.0/lib/openzeppelin-contracts/",":test/=lib/mento-core-2.0.0/test/"],"optimizer":{"runs":10000,"enabled":true},"libraries":{"AddressSortedLinkedListWithMedian":"0xed477a99035d0c1e11369f1d7a4e587893cc002b","AddressLinkedList":"0x6200f54d73491d56b8d7a975c9ee18efb4d518df"},"compilationTarget":{"lib/mento-core-2.2.0/contracts/oracles/BreakerBox.sol":"BreakerBox"}}
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address[]","name":"_rateFeedIDs","internalType":"address[]"},{"type":"address","name":"_sortedOracles","internalType":"contract ISortedOracles"}]},{"type":"event","name":"BreakerAdded","inputs":[{"type":"address","name":"breaker","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"BreakerRemoved","inputs":[{"type":"address","name":"breaker","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"BreakerStatusUpdated","inputs":[{"type":"address","name":"breaker","internalType":"address","indexed":false},{"type":"address","name":"rateFeedID","internalType":"address","indexed":false},{"type":"bool","name":"status","internalType":"bool","indexed":false}],"anonymous":false},{"type":"event","name":"BreakerTripped","inputs":[{"type":"address","name":"breaker","internalType":"address","indexed":true},{"type":"address","name":"rateFeedID","internalType":"address","indexed":true}],"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":"RateFeedAdded","inputs":[{"type":"address","name":"rateFeedID","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"RateFeedDependenciesSet","inputs":[{"type":"address","name":"rateFeedID","internalType":"address","indexed":true},{"type":"address[]","name":"dependencies","internalType":"address[]","indexed":true}],"anonymous":false},{"type":"event","name":"RateFeedRemoved","inputs":[{"type":"address","name":"rateFeedID","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"ResetAttemptCriteriaFail","inputs":[{"type":"address","name":"rateFeedID","internalType":"address","indexed":true},{"type":"address","name":"breaker","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"ResetAttemptNotCool","inputs":[{"type":"address","name":"rateFeedID","internalType":"address","indexed":true},{"type":"address","name":"breaker","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"ResetSuccessful","inputs":[{"type":"address","name":"rateFeedID","internalType":"address","indexed":true},{"type":"address","name":"breaker","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"SortedOraclesUpdated","inputs":[{"type":"address","name":"newSortedOracles","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"TradingModeUpdated","inputs":[{"type":"address","name":"rateFeedID","internalType":"address","indexed":true},{"type":"uint256","name":"tradingMode","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"nonpayable","name":"addBreaker","inputs":[{"type":"address","name":"breaker","internalType":"address"},{"type":"uint8","name":"tradingMode","internalType":"uint8"}]},{"type":"function","stateMutability":"nonpayable","name":"addRateFeed","inputs":[{"type":"address","name":"rateFeedID","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","name":"addRateFeeds","inputs":[{"type":"address[]","name":"newRateFeedIDs","internalType":"address[]"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"breakerTradingMode","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"breakers","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","name":"checkAndSetBreakers","inputs":[{"type":"address","name":"rateFeedID","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address[]","name":"","internalType":"address[]"}],"name":"getBreakers","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"getRateFeedTradingMode","inputs":[{"type":"address","name":"rateFeedID","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address[]","name":"","internalType":"address[]"}],"name":"getRateFeeds","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isBreaker","inputs":[{"type":"address","name":"breaker","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isBreakerEnabled","inputs":[{"type":"address","name":"breaker","internalType":"address"},{"type":"address","name":"rateFeedID","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isOwner","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"tradingMode","internalType":"uint8"},{"type":"uint64","name":"lastUpdatedTime","internalType":"uint64"},{"type":"bool","name":"enabled","internalType":"bool"}],"name":"rateFeedBreakerStatus","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"rateFeedDependencies","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"rateFeedIDs","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"rateFeedStatus","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"rateFeedTradingMode","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","name":"removeBreaker","inputs":[{"type":"address","name":"breaker","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","name":"removeRateFeed","inputs":[{"type":"address","name":"rateFeedID","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"nonpayable","name":"setRateFeedDependencies","inputs":[{"type":"address","name":"rateFeedID","internalType":"address"},{"type":"address[]","name":"dependencies","internalType":"address[]"}]},{"type":"function","stateMutability":"nonpayable","name":"setRateFeedTradingMode","inputs":[{"type":"address","name":"rateFeedID","internalType":"address"},{"type":"uint8","name":"tradingMode","internalType":"uint8"}]},{"type":"function","stateMutability":"nonpayable","name":"setSortedOracles","inputs":[{"type":"address","name":"_sortedOracles","internalType":"contract ISortedOracles"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract ISortedOracles"}],"name":"sortedOracles","inputs":[]},{"type":"function","stateMutability":"nonpayable","name":"toggleBreaker","inputs":[{"type":"address","name":"breakerAddress","internalType":"address"},{"type":"address","name":"rateFeedID","internalType":"address"},{"type":"bool","name":"enable","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]}]
Contract Creation Code
0x60806040523480156200001157600080fd5b5060405162002f5438038062002f54833981810160405260408110156200003757600080fd5b81019080805160405193929190846401000000008211156200005857600080fd5b9083019060208201858111156200006e57600080fd5b82518660208202830111640100000000821117156200008c57600080fd5b82525081516020918201928201910280838360005b83811015620000bb578181015183820152602001620000a1565b50505050919091016040525060200151915060009050620000e46001600160e01b036200016116565b600080546001600160a01b0319166001600160a01b03831690811782556040519293509160008051602062002ec1833981519152908290a35062000131336001600160e01b036200016516565b62000145816001600160e01b03620001f616565b62000159826001600160e01b03620002db16565b505062000637565b3390565b6001600160a01b038116620001ac5760405162461bcd60e51b815260040180806020018281038252602681526020018062002e7b6026913960400191505060405180910390fd5b600080546040516001600160a01b038085169392169160008051602062002ec183398151915291a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b620002096001600160e01b036200036e16565b6200024a576040805162461bcd60e51b8152602060048201819052602482015260008051602062002ea1833981519152604482015290519081900360640190fd5b6001600160a01b038116620002915760405162461bcd60e51b815260040180806020018281038252602181526020018062002f046021913960400191505060405180910390fd5b600880546001600160a01b0319166001600160a01b0383169081179091556040517f590fd633a008765ce9e65e8081adfba311e99e11b958a5ecb5000ea3355f735390600090a250565b620002ee6001600160e01b036200036e16565b6200032f576040805162461bcd60e51b8152602060048201819052602482015260008051602062002ea1833981519152604482015290519081900360640190fd5b60005b81518110156200036a57620003618282815181106200034d57fe5b60200260200101516200039d60201b60201c565b60010162000332565b5050565b600080546001600160a01b03166200038e6001600160e01b036200016116565b6001600160a01b031614905090565b620003b06001600160e01b036200036e16565b620003f1576040805162461bcd60e51b8152602060048201819052602482015260008051602062002ea1833981519152604482015290519081900360640190fd5b6001600160a01b03811660009081526002602052604090205460ff16156200044b5760405162461bcd60e51b815260040180806020018281038252602381526020018062002ee16023913960400191505060405180910390fd5b60085460408051638e74928160e01b81526001600160a01b03848116600483015291516000939290921691638e749281916024808201928692909190829003018186803b1580156200049c57600080fd5b505afa158015620004b1573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015620004db57600080fd5b8101908080516040519392919084640100000000821115620004fc57600080fd5b9083019060208201858111156200051257600080fd5b82518660208202830111640100000000821117156200053057600080fd5b82525081516020918201928201910280838360005b838110156200055f57818101518382015260200162000545565b505050509050016040525050505111620005ab5760405162461bcd60e51b815260040180806020018281038252602f81526020018062002f25602f913960400191505060405180910390fd5b6001805480820182557fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60180546001600160a01b0319166001600160a01b038416908117909155600081815260026020526040808220805460ff1916909417909355915190917fa1bccd87833fab06528ad8412cd349ff6ec2f1b851f48592a05ff995e4e7347d91a250565b61283480620006476000396000f3fe608060405234801561001057600080fd5b50600436106101b95760003560e01c8063607e4569116100f95780638f32d59b11610097578063c0b05da011610071578063c0b05da014610630578063c4bb759b14610656578063f2fde38b1461067c578063ff7bffa1146106a2576101b9565b80638f32d59b146105a7578063ab02e6c0146105af578063b5b01283146105d5576101b9565b806385c89866116100d357806385c89866146104d657806387efb0b5146104f35780638c892d3d146105735780638da5cb5b1461059f576101b9565b8063607e456914610405578063715018a61461042b578063793cef5114610433576101b9565b806327fd631111610166578063360e10ae11610140578063360e10ae146103595780633ed739c31461037f5780634afb215e146103a55780635727caef146103cb576101b9565b806327fd6311146102e65780632e730a8e146103225780632eeae9961461032a576101b9565b8063132e8aa711610197578063132e8aa71461024d5780631d82c3a31461027157806321a2d9d01461028e576101b9565b80630308422e146101be57806309833c3e146101ef5780630c60714614610215575b600080fd5b6101ed600480360360408110156101d457600080fd5b5080356001600160a01b0316906020013560ff166106d0565b005b6101ed6004803603602081101561020557600080fd5b50356001600160a01b03166107f7565b6101ed6004803603606081101561022b57600080fd5b506001600160a01b038135811691602081013590911690604001351515610ad9565b610255610d95565b604080516001600160a01b039092168252519081900360200190f35b6102556004803603602081101561028757600080fd5b5035610da4565b610296610dcb565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156102d25781810151838201526020016102ba565b505050509050019250505060405180910390f35b61030c600480360360208110156102fc57600080fd5b50356001600160a01b0316610e2e565b6040805160ff9092168252519081900360200190f35b610296610e43565b6101ed6004803603604081101561034057600080fd5b5080356001600160a01b0316906020013560ff16610ea3565b6101ed6004803603602081101561036f57600080fd5b50356001600160a01b0316611034565b61030c6004803603602081101561039557600080fd5b50356001600160a01b03166112d6565b6101ed600480360360208110156103bb57600080fd5b50356001600160a01b03166112eb565b6103f1600480360360208110156103e157600080fd5b50356001600160a01b03166113eb565b604080519115158252519081900360200190f35b6103f16004803603602081101561041b57600080fd5b50356001600160a01b0316611400565b6101ed61145d565b6101ed6004803603602081101561044957600080fd5b81019060208101813564010000000081111561046457600080fd5b82018360208201111561047657600080fd5b8035906020019184602083028401116401000000008311171561049857600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550611518945050505050565b610255600480360360208110156104ec57600080fd5b50356115a5565b6101ed6004803603604081101561050957600080fd5b6001600160a01b03823516919081019060408101602082013564010000000081111561053457600080fd5b82018360208201111561054657600080fd5b8035906020019184602083028401116401000000008311171561056857600080fd5b5090925090506115b2565b6102556004803603604081101561058957600080fd5b506001600160a01b0381351690602001356116f0565b610255611725565b6103f1611734565b6101ed600480360360208110156105c557600080fd5b50356001600160a01b0316611758565b610603600480360360408110156105eb57600080fd5b506001600160a01b03813581169160200135166117ad565b6040805160ff909416845267ffffffffffffffff9092166020840152151582820152519081900360600190f35b61030c6004803603602081101561064657600080fd5b50356001600160a01b03166117ef565b6101ed6004803603602081101561066c57600080fd5b50356001600160a01b03166118ff565b6101ed6004803603602081101561069257600080fd5b50356001600160a01b0316611bff565b6103f1600480360360408110156106b857600080fd5b506001600160a01b0381358116916020013516611c61565b6106d8611734565b610729576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b03821660009081526002602052604090205460ff16610796576040805162461bcd60e51b815260206004820152601f60248201527f52617465206665656420494420686173206e6f74206265656e20616464656400604482015290519081900360640190fd5b6001600160a01b038216600081815260046020908152604091829020805460ff191660ff8616908117909155825190815291517fb64ea6f0b71eb82019a4e1cb18612c962bf400a2333377020f4a9ab71eeeeb529281900390910190a25050565b6107ff611734565b610850576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b03811660009081526002602052604090205460ff16156108a85760405162461bcd60e51b815260040180806020018281038252602381526020018061278d6023913960400191505060405180910390fd5b600854604080517f8e7492810000000000000000000000000000000000000000000000000000000081526001600160a01b03848116600483015291516000939290921691638e749281916024808201928692909190829003018186803b15801561091157600080fd5b505afa158015610925573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052602081101561096c57600080fd5b810190808051604051939291908464010000000082111561098c57600080fd5b9083019060208201858111156109a157600080fd5b82518660208202830111640100000000821117156109be57600080fd5b82525081516020918201928201910280838360005b838110156109eb5781810151838201526020016109d3565b505050509050016040525050505111610a355760405162461bcd60e51b815260040180806020018281038252602f8152602001806127d1602f913960400191505060405180910390fd5b6001805480820182557fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038416908117909155600081815260026020526040808220805460ff1916909417909355915190917fa1bccd87833fab06528ad8412cd349ff6ec2f1b851f48592a05ff995e4e7347d91a250565b610ae1611734565b610b32576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b03821660009081526002602052604090205460ff16610b9f576040805162461bcd60e51b815260206004820152601f60248201527f52617465206665656420494420686173206e6f74206265656e20616464656400604482015290519081900360640190fd5b610ba883611400565b610be35760405162461bcd60e51b81526004018080602001828103825260318152602001806127396031913960400191505060405180910390fd5b6001600160a01b0380831660009081526003602090815260408083209387168352929052205460ff69010000000000000000009091041615158115151415610c72576040805162461bcd60e51b815260206004820181905260248201527f427265616b657220697320616c726561647920696e2074686973207374617465604482015290519081900360640190fd5b8015610ce1576001600160a01b03828116600090815260036020908152604080832093871683529290522080547fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff16690100000000000000000083151502179055610cdc82611c9e565b610d45565b6001600160a01b038083166000908152600360209081526040808320938716835292905290812080547fffffffffffffffffffffffffffffffffffffffffffff00000000000000000000169055610d3783611d7a565b9050610d4383826106d0565b505b604080516001600160a01b038086168252841660208201528215158183015290517f292d7648986a4abc017bc2a39852a675c1e325e24afd18fad659810792d5e4059181900360600190a1505050565b6008546001600160a01b031681565b60018181548110610db157fe5b6000918252602090912001546001600160a01b0316905081565b60606007805480602002602001604051908101604052809291908181526020018280548015610e2357602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610e05575b505050505090505b90565b60046020526000908152604090205460ff1681565b60606001805480602002602001604051908101604052809291908181526020018280548015610e23576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311610e05575050505050905090565b610eab611734565b610efc576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b818160ff16610f0a82611400565b15610f465760405162461bcd60e51b815260040180806020018281038252602381526020018061276a6023913960400191505060405180910390fd5b67ffffffffffffffff8116610f8c5760405162461bcd60e51b815260040180806020018281038252602f8152602001806126bb602f913960400191505060405180910390fd5b6001600160a01b038416600081815260066020526040808220805460ff191660ff8816179055600780546001810182559083527fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6880180547fffffffffffffffffffffffff00000000000000000000000000000000000000001684179055517fb41d9a8e03d4798a0a905017e377ecae53ebc5ca694c8fccaeabb5a08c0d333f9190a250505050565b61103c611734565b61108d576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6000805b6001548110156110dd57826001600160a01b0316600182815481106110b257fe5b6000918252602090912001546001600160a01b031614156110d5578091506110dd565b600101611091565b50816001600160a01b0316600182815481106110f557fe5b6000918252602090912001546001600160a01b03161461115c576040805162461bcd60e51b815260206004820152601f60248201527f52617465206665656420494420686173206e6f74206265656e20616464656400604482015290519081900360640190fd5b60018054600091611173919063ffffffff611e4c16565b90508082146111de576001818154811061118957fe5b600091825260209091200154600180546001600160a01b0390921691849081106111af57fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055505b60018054806111e957fe5b6000828152602080822083017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690559092019092556001600160a01b03851682526005905260408120611262916125ab565b6001600160a01b0383166000908152600460205260409020805460ff1916905561128b83611e95565b6001600160a01b038316600081815260026020526040808220805460ff19169055517f2646cbfbc7a17246cd5998517025a987bbdc416a91f2482601aeb30045d388199190a2505050565b60066020526000908152604090205460ff1681565b6112f3611734565b611344576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166113895760405162461bcd60e51b81526004018080602001828103825260218152602001806127b06021913960400191505060405180910390fd5b600880547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040517f590fd633a008765ce9e65e8081adfba311e99e11b958a5ecb5000ea3355f735390600090a250565b60026020526000908152604090205460ff1681565b6000805b60075481101561145257826001600160a01b03166007828154811061142557fe5b6000918252602090912001546001600160a01b0316141561144a576001915050611458565b600101611404565b50600090505b919050565b611465611734565b6114b6576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b611520611734565b611571576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60005b81518110156115a15761159982828151811061158c57fe5b60200260200101516107f7565b600101611574565b5050565b60078181548110610db157fe5b6115ba611734565b61160b576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b03831660009081526002602052604090205460ff16611678576040805162461bcd60e51b815260206004820152601f60248201527f52617465206665656420494420686173206e6f74206265656e20616464656400604482015290519081900360640190fd5b6001600160a01b038316600090815260056020526040902061169b9083836125c9565b50818160405180838360200280828437604051920182900382209450506001600160a01b03871692507f01ebc358c2c8d23692013d9ef4f803f9e0f60486a319faa591e1f84fd08fcd529150600090a3505050565b6005602052816000526040600020818154811061170957fe5b6000918252602090912001546001600160a01b03169150829050565b6000546001600160a01b031690565b600080546001600160a01b0316611749611f82565b6001600160a01b031614905090565b6008546001600160a01b031633146117a15760405162461bcd60e51b81526004018080602001828103825260298152602001806127106029913960400191505060405180910390fd5b6117aa81611c9e565b50565b600360209081526000928352604080842090915290825290205460ff8082169167ffffffffffffffff6101008204169169010000000000000000009091041683565b6001600160a01b03811660009081526002602052604081205460ff1661185c576040805162461bcd60e51b815260206004820152601f60248201527f52617465206665656420494420686173206e6f74206265656e20616464656400604482015290519081900360640190fd5b6001600160a01b03821660009081526004602052604081205460ff16905b6001600160a01b0384166000908152600560205260409020548110156118f8576001600160a01b038416600090815260056020526040812080546004929190849081106118c357fe5b60009182526020808320909101546001600160a01b0316835282019290925260400190205460ff16919091179060010161187a565b5092915050565b611907611734565b611958576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6000805b6007548110156119a857826001600160a01b03166007828154811061197d57fe5b6000918252602090912001546001600160a01b031614156119a0578091506119a8565b60010161195c565b50816001600160a01b0316600782815481106119c057fe5b6000918252602090912001546001600160a01b031614611a27576040805162461bcd60e51b815260206004820152601a60248201527f427265616b657220686173206e6f74206265656e206164646564000000000000604482015290519081900360640190fd5b60005b600154811015611ac3576003600060018381548110611a4557fe5b60009182526020808320909101546001600160a01b039081168452838201949094526040928301822093871682529290925290205460ff69010000000000000000009091041615611abb57611abb8360018381548110611aa157fe5b60009182526020822001546001600160a01b031690610ad9565b600101611a2a565b506001600160a01b0382166000908152600660205260408120805460ff19169055600754611af890600163ffffffff611e4c16565b9050808214611b635760078181548110611b0e57fe5b600091825260209091200154600780546001600160a01b039092169184908110611b3457fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055505b6007805480611b6e57fe5b60008281526020812082017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690559091019091556040516001600160a01b038516917f25d0fcab10ffc3ea7a197ec99e51df0362a1485e3a020caa618dbf72f92bb9f391a2505050565b611c07611734565b611c58576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6117aa81611f86565b6001600160a01b038181166000908152600360209081526040808320938616835292905220546901000000000000000000900460ff165b92915050565b6000805b600754811015611d4c576001600160a01b03831660009081526003602052604081206007805491929184908110611cd557fe5b60009182526020808320909101546001600160a01b0316835282019290925260400190205460ff69010000000000000000009091041615611d44576000611d3d8460078481548110611d2357fe5b6000918252602090912001546001600160a01b031661203e565b9290921791505b600101611ca2565b506001600160a01b03919091166000908152600460205260409020805460ff191660ff909216919091179055565b600080805b6007548110156118f8576001600160a01b03841660009081526003602052604081206007805491929184908110611db257fe5b60009182526020808320909101546001600160a01b0316835282019290925260400190205460ff69010000000000000000009091041615611e44576001600160a01b03841660009081526003602052604081206007805491929184908110611e1657fe5b60009182526020808320909101546001600160a01b0316835282019290925260400190205460ff1691909117905b600101611d7f565b6000611e8e83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612089565b9392505050565b60005b6007548110156115a1576001600160a01b03821660009081526003602052604081206007805491929184908110611ecb57fe5b60009182526020808320909101546001600160a01b0316835282019290925260400190205460ff69010000000000000000009091041615611f7a576001600160a01b03821660009081526003602052604081206007805491929184908110611f2f57fe5b60009182526020808320909101546001600160a01b03168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffff000000000000000000001690555b600101611e98565b3390565b6001600160a01b038116611fcb5760405162461bcd60e51b81526004018080602001828103825260268152602001806126ea6026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6001600160a01b03808316600090815260036020908152604080832093851683529290529081205460ff161561207f576120788383612120565b9050611c98565b611e8e838361240d565b600081848411156121185760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156120dd5781810151838201526020016120c5565b50505050905090810190601f16801561210a5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600061212a612644565b506001600160a01b0380841660008181526003602090815260408083209487168084529482528083208151606081018352905460ff808216835267ffffffffffffffff6101008304168386015269010000000000000000009091041615158183015281517f39b84ecf000000000000000000000000000000000000000000000000000000008152600481019590955290519094879490926339b84ecf92602480840193829003018186803b1580156121e157600080fd5b505afa1580156121f5573d6000803e3d6000fd5b505050506040513d602081101561220b57600080fd5b50519050801580159061223d5750602083015161223990829067ffffffffffffffff1663ffffffff61255116565b4210155b1561239a57816001600160a01b03166368b89d58876040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b03168152602001915050602060405180830381600087803b15801561229a57600080fd5b505af11580156122ae573d6000803e3d6000fd5b505050506040513d60208110156122c457600080fd5b505115612354576001600160a01b038681166000818152600360209081526040808320948a168084529490915280822080547fffffffffffffffffffffffffffffffffffffffffffffff000000000000000000166101004267ffffffffffffffff1602179055517fd45bd915ab99a070b980cdf13e671da6b79cc32e66eff6dc12c83a92071e6ab39190a3612395565b846001600160a01b0316866001600160a01b03167f90ca142474a3987fe4ec5cb24a254e13086fb998251070b5c9fc8ab70d78b8af60405160405180910390a35b6123db565b846001600160a01b0316866001600160a01b03167f636207d0069f1a3500c8d1676c804bc9d9a9d27e9add85139022a1757edf552260405160405180910390a35b505050506001600160a01b03918216600090815260036020908152604080832093909416825291909152205460ff1690565b604080517ffd165f530000000000000000000000000000000000000000000000000000000081526001600160a01b0384811660048301529151600092839285929183169163fd165f539160248082019260209290919082900301818887803b15801561247857600080fd5b505af115801561248c573d6000803e3d6000fd5b505050506040513d60208110156124a257600080fd5b505115612549576001600160a01b03848116600081815260066020908152604080832054948a1680845260038352818420858552909252808320805460ff90961660ff1990961686177fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000ff166101004267ffffffffffffffff160217905551939550927fe59f00019fc03badf2caa7d5de220ccfa5a411564a41f3b15906c02fd20150d59190a35b509392505050565b600082820183811015611e8e576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b50805460008255906000526020600020908101906117aa9190612664565b828054828255906000526020600020908101928215612634579160200282015b828111156126345781547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038435161782556020909201916001909101906125e9565b5061264092915061267e565b5090565b604080516060810182526000808252602082018190529181019190915290565b610e2b91905b80821115612640576000815560010161266a565b610e2b91905b808211156126405780547fffffffffffffffffffffffff000000000000000000000000000000000000000016815560010161268456fe5468652064656661756c742074726164696e67206d6f64652063616e206e6f742068617665206120627265616b65724f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737343616c6c6572206d7573742062652074686520536f727465644f7261636c657320636f6e74726163745468697320627265616b657220686173206e6f74206265656e20616464656420746f2074686520427265616b6572426f785468697320627265616b65722068617320616c7265616479206265656e2061646465645261746520666565642049442068617320616c7265616479206265656e206164646564536f727465644f7261636c65732061646472657373206d7573742062652073657452617465206665656420494420646f6573206e6f74206578697374206173206974206861732030206f7261636c6573a265627a7a72315820a44b654637a2e08898c6b04b446a387029bd8baa2d22c01229d12dfa536fb23464736f6c634300051100324f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573734f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65728be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05261746520666565642049442068617320616c7265616479206265656e206164646564536f727465644f7261636c65732061646472657373206d7573742062652073657452617465206665656420494420646f6573206e6f74206578697374206173206974206861732030206f7261636c65730000000000000000000000000000000000000000000000000000000000000040000000000000000000000000efb84935239dacdecf7c5ba76d8de40b077b7b330000000000000000000000000000000000000000000000000000000000000000
Deployed ByteCode
0x608060405234801561001057600080fd5b50600436106101b95760003560e01c8063607e4569116100f95780638f32d59b11610097578063c0b05da011610071578063c0b05da014610630578063c4bb759b14610656578063f2fde38b1461067c578063ff7bffa1146106a2576101b9565b80638f32d59b146105a7578063ab02e6c0146105af578063b5b01283146105d5576101b9565b806385c89866116100d357806385c89866146104d657806387efb0b5146104f35780638c892d3d146105735780638da5cb5b1461059f576101b9565b8063607e456914610405578063715018a61461042b578063793cef5114610433576101b9565b806327fd631111610166578063360e10ae11610140578063360e10ae146103595780633ed739c31461037f5780634afb215e146103a55780635727caef146103cb576101b9565b806327fd6311146102e65780632e730a8e146103225780632eeae9961461032a576101b9565b8063132e8aa711610197578063132e8aa71461024d5780631d82c3a31461027157806321a2d9d01461028e576101b9565b80630308422e146101be57806309833c3e146101ef5780630c60714614610215575b600080fd5b6101ed600480360360408110156101d457600080fd5b5080356001600160a01b0316906020013560ff166106d0565b005b6101ed6004803603602081101561020557600080fd5b50356001600160a01b03166107f7565b6101ed6004803603606081101561022b57600080fd5b506001600160a01b038135811691602081013590911690604001351515610ad9565b610255610d95565b604080516001600160a01b039092168252519081900360200190f35b6102556004803603602081101561028757600080fd5b5035610da4565b610296610dcb565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156102d25781810151838201526020016102ba565b505050509050019250505060405180910390f35b61030c600480360360208110156102fc57600080fd5b50356001600160a01b0316610e2e565b6040805160ff9092168252519081900360200190f35b610296610e43565b6101ed6004803603604081101561034057600080fd5b5080356001600160a01b0316906020013560ff16610ea3565b6101ed6004803603602081101561036f57600080fd5b50356001600160a01b0316611034565b61030c6004803603602081101561039557600080fd5b50356001600160a01b03166112d6565b6101ed600480360360208110156103bb57600080fd5b50356001600160a01b03166112eb565b6103f1600480360360208110156103e157600080fd5b50356001600160a01b03166113eb565b604080519115158252519081900360200190f35b6103f16004803603602081101561041b57600080fd5b50356001600160a01b0316611400565b6101ed61145d565b6101ed6004803603602081101561044957600080fd5b81019060208101813564010000000081111561046457600080fd5b82018360208201111561047657600080fd5b8035906020019184602083028401116401000000008311171561049857600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550611518945050505050565b610255600480360360208110156104ec57600080fd5b50356115a5565b6101ed6004803603604081101561050957600080fd5b6001600160a01b03823516919081019060408101602082013564010000000081111561053457600080fd5b82018360208201111561054657600080fd5b8035906020019184602083028401116401000000008311171561056857600080fd5b5090925090506115b2565b6102556004803603604081101561058957600080fd5b506001600160a01b0381351690602001356116f0565b610255611725565b6103f1611734565b6101ed600480360360208110156105c557600080fd5b50356001600160a01b0316611758565b610603600480360360408110156105eb57600080fd5b506001600160a01b03813581169160200135166117ad565b6040805160ff909416845267ffffffffffffffff9092166020840152151582820152519081900360600190f35b61030c6004803603602081101561064657600080fd5b50356001600160a01b03166117ef565b6101ed6004803603602081101561066c57600080fd5b50356001600160a01b03166118ff565b6101ed6004803603602081101561069257600080fd5b50356001600160a01b0316611bff565b6103f1600480360360408110156106b857600080fd5b506001600160a01b0381358116916020013516611c61565b6106d8611734565b610729576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b03821660009081526002602052604090205460ff16610796576040805162461bcd60e51b815260206004820152601f60248201527f52617465206665656420494420686173206e6f74206265656e20616464656400604482015290519081900360640190fd5b6001600160a01b038216600081815260046020908152604091829020805460ff191660ff8616908117909155825190815291517fb64ea6f0b71eb82019a4e1cb18612c962bf400a2333377020f4a9ab71eeeeb529281900390910190a25050565b6107ff611734565b610850576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b03811660009081526002602052604090205460ff16156108a85760405162461bcd60e51b815260040180806020018281038252602381526020018061278d6023913960400191505060405180910390fd5b600854604080517f8e7492810000000000000000000000000000000000000000000000000000000081526001600160a01b03848116600483015291516000939290921691638e749281916024808201928692909190829003018186803b15801561091157600080fd5b505afa158015610925573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052602081101561096c57600080fd5b810190808051604051939291908464010000000082111561098c57600080fd5b9083019060208201858111156109a157600080fd5b82518660208202830111640100000000821117156109be57600080fd5b82525081516020918201928201910280838360005b838110156109eb5781810151838201526020016109d3565b505050509050016040525050505111610a355760405162461bcd60e51b815260040180806020018281038252602f8152602001806127d1602f913960400191505060405180910390fd5b6001805480820182557fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038416908117909155600081815260026020526040808220805460ff1916909417909355915190917fa1bccd87833fab06528ad8412cd349ff6ec2f1b851f48592a05ff995e4e7347d91a250565b610ae1611734565b610b32576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b03821660009081526002602052604090205460ff16610b9f576040805162461bcd60e51b815260206004820152601f60248201527f52617465206665656420494420686173206e6f74206265656e20616464656400604482015290519081900360640190fd5b610ba883611400565b610be35760405162461bcd60e51b81526004018080602001828103825260318152602001806127396031913960400191505060405180910390fd5b6001600160a01b0380831660009081526003602090815260408083209387168352929052205460ff69010000000000000000009091041615158115151415610c72576040805162461bcd60e51b815260206004820181905260248201527f427265616b657220697320616c726561647920696e2074686973207374617465604482015290519081900360640190fd5b8015610ce1576001600160a01b03828116600090815260036020908152604080832093871683529290522080547fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff16690100000000000000000083151502179055610cdc82611c9e565b610d45565b6001600160a01b038083166000908152600360209081526040808320938716835292905290812080547fffffffffffffffffffffffffffffffffffffffffffff00000000000000000000169055610d3783611d7a565b9050610d4383826106d0565b505b604080516001600160a01b038086168252841660208201528215158183015290517f292d7648986a4abc017bc2a39852a675c1e325e24afd18fad659810792d5e4059181900360600190a1505050565b6008546001600160a01b031681565b60018181548110610db157fe5b6000918252602090912001546001600160a01b0316905081565b60606007805480602002602001604051908101604052809291908181526020018280548015610e2357602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610e05575b505050505090505b90565b60046020526000908152604090205460ff1681565b60606001805480602002602001604051908101604052809291908181526020018280548015610e23576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311610e05575050505050905090565b610eab611734565b610efc576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b818160ff16610f0a82611400565b15610f465760405162461bcd60e51b815260040180806020018281038252602381526020018061276a6023913960400191505060405180910390fd5b67ffffffffffffffff8116610f8c5760405162461bcd60e51b815260040180806020018281038252602f8152602001806126bb602f913960400191505060405180910390fd5b6001600160a01b038416600081815260066020526040808220805460ff191660ff8816179055600780546001810182559083527fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6880180547fffffffffffffffffffffffff00000000000000000000000000000000000000001684179055517fb41d9a8e03d4798a0a905017e377ecae53ebc5ca694c8fccaeabb5a08c0d333f9190a250505050565b61103c611734565b61108d576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6000805b6001548110156110dd57826001600160a01b0316600182815481106110b257fe5b6000918252602090912001546001600160a01b031614156110d5578091506110dd565b600101611091565b50816001600160a01b0316600182815481106110f557fe5b6000918252602090912001546001600160a01b03161461115c576040805162461bcd60e51b815260206004820152601f60248201527f52617465206665656420494420686173206e6f74206265656e20616464656400604482015290519081900360640190fd5b60018054600091611173919063ffffffff611e4c16565b90508082146111de576001818154811061118957fe5b600091825260209091200154600180546001600160a01b0390921691849081106111af57fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055505b60018054806111e957fe5b6000828152602080822083017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690559092019092556001600160a01b03851682526005905260408120611262916125ab565b6001600160a01b0383166000908152600460205260409020805460ff1916905561128b83611e95565b6001600160a01b038316600081815260026020526040808220805460ff19169055517f2646cbfbc7a17246cd5998517025a987bbdc416a91f2482601aeb30045d388199190a2505050565b60066020526000908152604090205460ff1681565b6112f3611734565b611344576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b0381166113895760405162461bcd60e51b81526004018080602001828103825260218152602001806127b06021913960400191505060405180910390fd5b600880547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040517f590fd633a008765ce9e65e8081adfba311e99e11b958a5ecb5000ea3355f735390600090a250565b60026020526000908152604090205460ff1681565b6000805b60075481101561145257826001600160a01b03166007828154811061142557fe5b6000918252602090912001546001600160a01b0316141561144a576001915050611458565b600101611404565b50600090505b919050565b611465611734565b6114b6576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b611520611734565b611571576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60005b81518110156115a15761159982828151811061158c57fe5b60200260200101516107f7565b600101611574565b5050565b60078181548110610db157fe5b6115ba611734565b61160b576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b03831660009081526002602052604090205460ff16611678576040805162461bcd60e51b815260206004820152601f60248201527f52617465206665656420494420686173206e6f74206265656e20616464656400604482015290519081900360640190fd5b6001600160a01b038316600090815260056020526040902061169b9083836125c9565b50818160405180838360200280828437604051920182900382209450506001600160a01b03871692507f01ebc358c2c8d23692013d9ef4f803f9e0f60486a319faa591e1f84fd08fcd529150600090a3505050565b6005602052816000526040600020818154811061170957fe5b6000918252602090912001546001600160a01b03169150829050565b6000546001600160a01b031690565b600080546001600160a01b0316611749611f82565b6001600160a01b031614905090565b6008546001600160a01b031633146117a15760405162461bcd60e51b81526004018080602001828103825260298152602001806127106029913960400191505060405180910390fd5b6117aa81611c9e565b50565b600360209081526000928352604080842090915290825290205460ff8082169167ffffffffffffffff6101008204169169010000000000000000009091041683565b6001600160a01b03811660009081526002602052604081205460ff1661185c576040805162461bcd60e51b815260206004820152601f60248201527f52617465206665656420494420686173206e6f74206265656e20616464656400604482015290519081900360640190fd5b6001600160a01b03821660009081526004602052604081205460ff16905b6001600160a01b0384166000908152600560205260409020548110156118f8576001600160a01b038416600090815260056020526040812080546004929190849081106118c357fe5b60009182526020808320909101546001600160a01b0316835282019290925260400190205460ff16919091179060010161187a565b5092915050565b611907611734565b611958576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6000805b6007548110156119a857826001600160a01b03166007828154811061197d57fe5b6000918252602090912001546001600160a01b031614156119a0578091506119a8565b60010161195c565b50816001600160a01b0316600782815481106119c057fe5b6000918252602090912001546001600160a01b031614611a27576040805162461bcd60e51b815260206004820152601a60248201527f427265616b657220686173206e6f74206265656e206164646564000000000000604482015290519081900360640190fd5b60005b600154811015611ac3576003600060018381548110611a4557fe5b60009182526020808320909101546001600160a01b039081168452838201949094526040928301822093871682529290925290205460ff69010000000000000000009091041615611abb57611abb8360018381548110611aa157fe5b60009182526020822001546001600160a01b031690610ad9565b600101611a2a565b506001600160a01b0382166000908152600660205260408120805460ff19169055600754611af890600163ffffffff611e4c16565b9050808214611b635760078181548110611b0e57fe5b600091825260209091200154600780546001600160a01b039092169184908110611b3457fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055505b6007805480611b6e57fe5b60008281526020812082017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690559091019091556040516001600160a01b038516917f25d0fcab10ffc3ea7a197ec99e51df0362a1485e3a020caa618dbf72f92bb9f391a2505050565b611c07611734565b611c58576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6117aa81611f86565b6001600160a01b038181166000908152600360209081526040808320938616835292905220546901000000000000000000900460ff165b92915050565b6000805b600754811015611d4c576001600160a01b03831660009081526003602052604081206007805491929184908110611cd557fe5b60009182526020808320909101546001600160a01b0316835282019290925260400190205460ff69010000000000000000009091041615611d44576000611d3d8460078481548110611d2357fe5b6000918252602090912001546001600160a01b031661203e565b9290921791505b600101611ca2565b506001600160a01b03919091166000908152600460205260409020805460ff191660ff909216919091179055565b600080805b6007548110156118f8576001600160a01b03841660009081526003602052604081206007805491929184908110611db257fe5b60009182526020808320909101546001600160a01b0316835282019290925260400190205460ff69010000000000000000009091041615611e44576001600160a01b03841660009081526003602052604081206007805491929184908110611e1657fe5b60009182526020808320909101546001600160a01b0316835282019290925260400190205460ff1691909117905b600101611d7f565b6000611e8e83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612089565b9392505050565b60005b6007548110156115a1576001600160a01b03821660009081526003602052604081206007805491929184908110611ecb57fe5b60009182526020808320909101546001600160a01b0316835282019290925260400190205460ff69010000000000000000009091041615611f7a576001600160a01b03821660009081526003602052604081206007805491929184908110611f2f57fe5b60009182526020808320909101546001600160a01b03168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffff000000000000000000001690555b600101611e98565b3390565b6001600160a01b038116611fcb5760405162461bcd60e51b81526004018080602001828103825260268152602001806126ea6026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6001600160a01b03808316600090815260036020908152604080832093851683529290529081205460ff161561207f576120788383612120565b9050611c98565b611e8e838361240d565b600081848411156121185760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156120dd5781810151838201526020016120c5565b50505050905090810190601f16801561210a5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600061212a612644565b506001600160a01b0380841660008181526003602090815260408083209487168084529482528083208151606081018352905460ff808216835267ffffffffffffffff6101008304168386015269010000000000000000009091041615158183015281517f39b84ecf000000000000000000000000000000000000000000000000000000008152600481019590955290519094879490926339b84ecf92602480840193829003018186803b1580156121e157600080fd5b505afa1580156121f5573d6000803e3d6000fd5b505050506040513d602081101561220b57600080fd5b50519050801580159061223d5750602083015161223990829067ffffffffffffffff1663ffffffff61255116565b4210155b1561239a57816001600160a01b03166368b89d58876040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b03168152602001915050602060405180830381600087803b15801561229a57600080fd5b505af11580156122ae573d6000803e3d6000fd5b505050506040513d60208110156122c457600080fd5b505115612354576001600160a01b038681166000818152600360209081526040808320948a168084529490915280822080547fffffffffffffffffffffffffffffffffffffffffffffff000000000000000000166101004267ffffffffffffffff1602179055517fd45bd915ab99a070b980cdf13e671da6b79cc32e66eff6dc12c83a92071e6ab39190a3612395565b846001600160a01b0316866001600160a01b03167f90ca142474a3987fe4ec5cb24a254e13086fb998251070b5c9fc8ab70d78b8af60405160405180910390a35b6123db565b846001600160a01b0316866001600160a01b03167f636207d0069f1a3500c8d1676c804bc9d9a9d27e9add85139022a1757edf552260405160405180910390a35b505050506001600160a01b03918216600090815260036020908152604080832093909416825291909152205460ff1690565b604080517ffd165f530000000000000000000000000000000000000000000000000000000081526001600160a01b0384811660048301529151600092839285929183169163fd165f539160248082019260209290919082900301818887803b15801561247857600080fd5b505af115801561248c573d6000803e3d6000fd5b505050506040513d60208110156124a257600080fd5b505115612549576001600160a01b03848116600081815260066020908152604080832054948a1680845260038352818420858552909252808320805460ff90961660ff1990961686177fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000ff166101004267ffffffffffffffff160217905551939550927fe59f00019fc03badf2caa7d5de220ccfa5a411564a41f3b15906c02fd20150d59190a35b509392505050565b600082820183811015611e8e576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b50805460008255906000526020600020908101906117aa9190612664565b828054828255906000526020600020908101928215612634579160200282015b828111156126345781547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038435161782556020909201916001909101906125e9565b5061264092915061267e565b5090565b604080516060810182526000808252602082018190529181019190915290565b610e2b91905b80821115612640576000815560010161266a565b610e2b91905b808211156126405780547fffffffffffffffffffffffff000000000000000000000000000000000000000016815560010161268456fe5468652064656661756c742074726164696e67206d6f64652063616e206e6f742068617665206120627265616b65724f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737343616c6c6572206d7573742062652074686520536f727465644f7261636c657320636f6e74726163745468697320627265616b657220686173206e6f74206265656e20616464656420746f2074686520427265616b6572426f785468697320627265616b65722068617320616c7265616479206265656e2061646465645261746520666565642049442068617320616c7265616479206265656e206164646564536f727465644f7261636c65732061646472657373206d7573742062652073657452617465206665656420494420646f6573206e6f74206578697374206173206974206861732030206f7261636c6573a265627a7a72315820a44b654637a2e08898c6b04b446a387029bd8baa2d22c01229d12dfa536fb23464736f6c63430005110032
External libraries
AddressLinkedList : 0x6200f54d73491d56b8d7a975c9ee18efb4d518df
AddressSortedLinkedListWithMedian : 0xed477a99035d0c1e11369f1d7a4e587893cc002b