Address Details
contract
0xFF5F884291EB111D1B7fb25E6099a736D4fdA52c
- Contract Name
- BreakerBox
- Creator
- 0x56fd3f–9b8d81 at 0xed8922–2272d8
- 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,715
- Last Balance Update
- 27367880
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
- EVM Version
- istanbul
- Verified at
- 2023-05-25T18:34:29.828492Z
lib/mento-core/contracts/BreakerBox.sol
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.5.13; import { IBreakerBox } from "./interfaces/IBreakerBox.sol"; import { IBreaker } from "./interfaces/IBreaker.sol"; import { ISortedOracles } from "./interfaces/ISortedOracles.sol"; import { SafeMath } from "openzeppelin-solidity/contracts/math/SafeMath.sol"; import { Ownable } from "openzeppelin-solidity/contracts/ownership/Ownable.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. */ contract BreakerBox is IBreakerBox, Initializable, Ownable { using AddressLinkedList for LinkedList.List; using SafeMath for uint256; /* ==================== State Variables ==================== */ address[] public rateFeedIDs; // Maps rate feed ID to its current trading mode info. mapping(address => TradingModeInfo) public rateFeedTradingModes; // Maps a trading mode to the associated breaker. mapping(uint64 => address) public tradingModeBreaker; // Maps a breaker to the associated trading mode. mapping(address => uint64) public breakerTradingMode; // Ordered list of breakers to be checked. LinkedList.List private breakers; // Maps a breaker with rate feed id and bool to check if it's enabled. mapping(address => mapping(address => bool)) public breakerEnabled; // 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( tradingModeBreaker[tradingMode] == address(0), "There is already a breaker added with the same trading mode" ); require(tradingMode != 0, "The default trading mode can not have a breaker"); _; } /* ==================== Constructor ==================== */ /** * @notice Sets initialized == true on implementation contracts. * @param test Set to true to skip implementation initialization. */ constructor(bool test) public Initializable(test) {} /** * @param _rateFeedIDs rateFeedIDs to be added. * @param _sortedOracles The address of the Celo sorted oracles contract. */ function initialize(address[] calldata _rateFeedIDs, ISortedOracles _sortedOracles) external initializer { _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 tradingMode-Breaker 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, uint64 tradingMode) public onlyOwner onlyValidBreaker(breaker, tradingMode) { tradingModeBreaker[tradingMode] = breaker; breakerTradingMode[breaker] = tradingMode; breakers.push(breaker); emit BreakerAdded(breaker); } /** * @notice Adds a breaker to the list of breakers at a specified position. * @param breaker The address of the breaker to be added. * @param tradingMode The trading mode of the breaker to be added. * @param prevBreaker The address of the breaker that should come before the new breaker. * @param nextBreaker The address of the breaker that should come after the new breaker. */ function insertBreaker( address breaker, uint64 tradingMode, address prevBreaker, address nextBreaker ) external onlyOwner onlyValidBreaker(breaker, tradingMode) { tradingModeBreaker[tradingMode] = breaker; breakerTradingMode[breaker] = tradingMode; breakers.insert(breaker, prevBreaker, nextBreaker); emit BreakerAdded(breaker); } /** * @notice Removes the specified breaker from the list of breakers. * @param breaker The address of the breaker to be removed. * @dev Will set any rateFeedID using this breakers trading mode to the default trading mode * because if its tripped and if we remove it rateFeed will be stuck in the trading mode. */ function removeBreaker(address breaker) external onlyOwner { require(isBreaker(breaker), "This breaker has not been added"); uint64 tradingMode = breakerTradingMode[breaker]; // Set any refenceRateIDs using this breakers trading mode to the default mode. // Disable a breaker on this address address[] memory activeRateFeeds = rateFeedIDs; TradingModeInfo memory tradingModeInfo; for (uint256 i = 0; i < activeRateFeeds.length; i++) { tradingModeInfo = rateFeedTradingModes[activeRateFeeds[i]]; if (tradingModeInfo.tradingMode == tradingMode) { setRateFeedTradingMode(activeRateFeeds[i], 0); } if (breakerEnabled[breaker][activeRateFeeds[i]]) { breakerEnabled[breaker][activeRateFeeds[i]] = false; } } delete tradingModeBreaker[tradingMode]; delete breakerTradingMode[breaker]; breakers.remove(breaker); emit BreakerRemoved(breaker); } /** * @notice Enables or disables a breaker for the specified rate feed. * @param breakerAddress The address of the breaker. * @param rateFeedId The id of the rate feed. * @param isEnabled Boolean indicating whether the breaker should be * enabled or disabled for the given rateFeed. * @dev If the breaker is being disabled and the rateFeed is using the same trading mode * as the breaker, the rateFeed will be set to the default trading mode. */ function toggleBreaker( address breakerAddress, address rateFeedId, bool isEnabled ) public onlyOwner { TradingModeInfo memory info = rateFeedTradingModes[rateFeedId]; require(info.lastUpdatedTime != 0, "This rate feed has not been added to the BreakerBox"); require(isBreaker(breakerAddress), "This breaker has not been added to the BreakerBox"); // Check if we are disabling the breaker for this rateFeedID. // If so, set the rateFeed to the default trading mode, // before disabling the breaker. if (!isEnabled && tradingModeBreaker[info.tradingMode] == breakerAddress) { setRateFeedTradingMode(rateFeedId, 0); } breakerEnabled[breakerAddress][rateFeedId] = isEnabled; emit BreakerStatusUpdated(breakerAddress, rateFeedId, isEnabled); } /* ---------- rateFeedIDs ---------- */ /** * @notice Adds a rateFeedID to the mapping of monitored rateFeedIDs. * @param rateFeedID The address of the rateFeedID to be added. */ function addRateFeed(address rateFeedID) public onlyOwner { TradingModeInfo memory info = rateFeedTradingModes[rateFeedID]; require(info.lastUpdatedTime == 0, "Rate feed ID has already been added"); require(sortedOracles.getOracles(rateFeedID).length > 0, "Rate feed ID does not exist as it has 0 oracles"); info.tradingMode = 0; // Default trading mode (Bi-directional). info.lastUpdatedTime = uint64(block.timestamp); info.lastUpdatedBlock = uint128(block.number); rateFeedTradingModes[rateFeedID] = info; rateFeedIDs.push(rateFeedID); emit RateFeedAdded(rateFeedID); } /** * @notice Adds the specified rateFeedIDs to the mapping of monitored rateFeedIDs. * @param newRateFeedIDs The array of rateFeedID addresses to be added. */ function addRateFeeds(address[] memory newRateFeedIDs) public onlyOwner { for (uint256 i = 0; i < newRateFeedIDs.length; i++) { addRateFeed(newRateFeedIDs[i]); } } /** * @notice Removes a rateFeedID from the mapping of monitored rateFeedIDs. * @param rateFeedID The address of the rateFeedID 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 rateFeedTradingModes[rateFeedID]; address[] memory _breakers = breakers.getKeys(); // remove configured rate feed for the breaker for (uint256 i = 0; i < _breakers.length; i++) { if (breakerEnabled[_breakers[i]][rateFeedID]) { breakerEnabled[_breakers[i]][rateFeedID] = false; } } emit RateFeedRemoved(rateFeedID); } /** * @notice Sets the trading mode for the specified rateFeedID. * @param rateFeedID The address of the rateFeedID. * @param tradingMode The trading mode that should be set. */ function setRateFeedTradingMode(address rateFeedID, uint64 tradingMode) public onlyOwner { require( tradingMode == 0 || tradingModeBreaker[tradingMode] != address(0), "Trading mode must be default or have a breaker set" ); TradingModeInfo memory info = rateFeedTradingModes[rateFeedID]; require(info.lastUpdatedTime > 0, "Rate feed ID has not been added"); info.tradingMode = tradingMode; info.lastUpdatedTime = uint64(block.timestamp); info.lastUpdatedBlock = uint128(block.number); rateFeedTradingModes[rateFeedID] = info; emit TradingModeUpdated(rateFeedID, tradingMode); } /* ==================== 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.getKeys(); } /** * @notice Checks whether a breaker with the specifed address has been added. */ function isBreaker(address breaker) public view returns (bool) { return breakers.contains(breaker); } /** * @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 rateFeedID to retrieve the trading mode for. */ function getRateFeedTradingMode(address rateFeedID) external view returns (uint256 tradingMode) { TradingModeInfo memory info = rateFeedTradingModes[rateFeedID]; return info.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 rateFeedID. */ function isBreakerEnabled(address breaker, address rateFeedID) external view returns (bool) { return breakerEnabled[breaker][rateFeedID]; } /* ==================== 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 registryId of the rateFeedID to run checks for. */ function checkAndSetBreakers(address rateFeedID) external { TradingModeInfo memory info = rateFeedTradingModes[rateFeedID]; // This rateFeedID has not been added. So do nothing. if (info.lastUpdatedTime == 0) { return; } // Check if a breaker has non default trading mode and reset if we should. if (info.tradingMode != 0) { IBreaker breaker = IBreaker(tradingModeBreaker[info.tradingMode]); uint256 cooldown = breaker.getCooldown(rateFeedID); // If the cooldown == 0, then a manual reset is required. if (((cooldown > 0) && (cooldown.add(info.lastUpdatedTime)) <= block.timestamp)) { if (breaker.shouldReset(rateFeedID)) { info.tradingMode = 0; info.lastUpdatedTime = uint64(block.timestamp); info.lastUpdatedBlock = uint128(block.number); rateFeedTradingModes[rateFeedID] = info; emit ResetSuccessful(rateFeedID, address(breaker)); } else { emit ResetAttemptCriteriaFail(rateFeedID, address(breaker)); return; } } else { emit ResetAttemptNotCool(rateFeedID, address(breaker)); return; } } address[] memory _breakers = breakers.getKeys(); // Check all breakers. for (uint256 i = 0; i < _breakers.length; i++) { if (breakerEnabled[_breakers[i]][rateFeedID]) { IBreaker breaker = IBreaker(_breakers[i]); bool tripBreaker = breaker.shouldTrigger(rateFeedID); if (tripBreaker) { info.tradingMode = breakerTradingMode[address(breaker)]; info.lastUpdatedTime = uint64(block.timestamp); info.lastUpdatedBlock = uint128(block.number); rateFeedTradingModes[rateFeedID] = info; emit BreakerTripped(address(breaker), rateFeedID); } } } } }
/lib/mento-core/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/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/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/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/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/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/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 track additional info about * the current trading mode a specific rate feed ID is in. * LastUpdatedTime helps to check cooldown. * LastUpdatedBlock helps to determine if check should be executed. */ struct TradingModeInfo { uint64 tradingMode; uint64 lastUpdatedTime; uint128 lastUpdatedBlock; } /** * @notice Emitted when a new breaker is added to the breaker box. * @param breaker The address of the new breaker. */ event BreakerAdded(address indexed breaker); /** * @notice Emitted when a breaker is removed from the breaker box. * @param breaker The address of the breaker that was removed. */ event BreakerRemoved(address indexed breaker); /** * @notice Emitted when a breaker is tripped by a rate feed. * @param breaker The address of the breaker that was tripped. * @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 that was added. */ event RateFeedAdded(address indexed rateFeedID); /** * @notice Emitted when a rate feed is removed from the breaker box. * @param rateFeedID The rate feed that was removed. */ event RateFeedRemoved(address indexed rateFeedID); /** * @notice Emitted when the trading mode for a rate feed is updated * @param rateFeedID The address of the rataFeedID. * @param tradingMode The new trading mode of the rate feed. */ 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 ordered 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 registryId of the rateFeedID to run checks for. */ function checkAndSetBreakers(address rateFeedID) external; /** * @notice Gets the trading mode for the specified rateFeedID. * @param rateFeedID The address of the rateFeedID to retrieve the trading mode for. */ function getRateFeedTradingMode(address rateFeedID) external view returns (uint256 tradingMode); }
/lib/mento-core/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 ); }
/lib/mento-core/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/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/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; } }
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","payable":false,"inputs":[{"type":"bool","name":"test","internalType":"bool"}]},{"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":"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","payable":false,"outputs":[],"name":"addBreaker","inputs":[{"type":"address","name":"breaker","internalType":"address"},{"type":"uint64","name":"tradingMode","internalType":"uint64"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"addRateFeed","inputs":[{"type":"address","name":"rateFeedID","internalType":"address"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"addRateFeeds","inputs":[{"type":"address[]","name":"newRateFeedIDs","internalType":"address[]"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"breakerEnabled","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"address","name":"","internalType":"address"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint64","name":"","internalType":"uint64"}],"name":"breakerTradingMode","inputs":[{"type":"address","name":"","internalType":"address"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"checkAndSetBreakers","inputs":[{"type":"address","name":"rateFeedID","internalType":"address"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address[]","name":"","internalType":"address[]"}],"name":"getBreakers","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"tradingMode","internalType":"uint256"}],"name":"getRateFeedTradingMode","inputs":[{"type":"address","name":"rateFeedID","internalType":"address"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address[]","name":"","internalType":"address[]"}],"name":"getRateFeeds","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"initialize","inputs":[{"type":"address[]","name":"_rateFeedIDs","internalType":"address[]"},{"type":"address","name":"_sortedOracles","internalType":"contract ISortedOracles"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"initialized","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"insertBreaker","inputs":[{"type":"address","name":"breaker","internalType":"address"},{"type":"uint64","name":"tradingMode","internalType":"uint64"},{"type":"address","name":"prevBreaker","internalType":"address"},{"type":"address","name":"nextBreaker","internalType":"address"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isBreaker","inputs":[{"type":"address","name":"breaker","internalType":"address"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isBreakerEnabled","inputs":[{"type":"address","name":"breaker","internalType":"address"},{"type":"address","name":"rateFeedID","internalType":"address"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isOwner","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"","internalType":"address"}],"name":"rateFeedIDs","inputs":[{"type":"uint256","name":"","internalType":"uint256"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint64","name":"tradingMode","internalType":"uint64"},{"type":"uint64","name":"lastUpdatedTime","internalType":"uint64"},{"type":"uint128","name":"lastUpdatedBlock","internalType":"uint128"}],"name":"rateFeedTradingModes","inputs":[{"type":"address","name":"","internalType":"address"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"removeBreaker","inputs":[{"type":"address","name":"breaker","internalType":"address"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"removeRateFeed","inputs":[{"type":"address","name":"rateFeedID","internalType":"address"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"renounceOwnership","inputs":[],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setRateFeedTradingMode","inputs":[{"type":"address","name":"rateFeedID","internalType":"address"},{"type":"uint64","name":"tradingMode","internalType":"uint64"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setSortedOracles","inputs":[{"type":"address","name":"_sortedOracles","internalType":"contract ISortedOracles"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"","internalType":"contract ISortedOracles"}],"name":"sortedOracles","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"toggleBreaker","inputs":[{"type":"address","name":"breakerAddress","internalType":"address"},{"type":"address","name":"rateFeedId","internalType":"address"},{"type":"bool","name":"isEnabled","internalType":"bool"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"","internalType":"address"}],"name":"tradingModeBreaker","inputs":[{"type":"uint64","name":"","internalType":"uint64"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}],"constant":false}]
Contract Creation Code
0x60806040523480156200001157600080fd5b506040516200307938038062003079833981810160405260208110156200003757600080fd5b505180806200004e576000805460ff191660011790555b506000620000646001600160e01b03620000bd16565b60008054610100600160a81b0319166101006001600160a01b038416908102919091178255604051929350917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a35050620000c1565b3390565b612fa880620000d16000396000f3fe608060405234801561001057600080fd5b50600436106101b95760003560e01c80634afb215e116100f9578063ab02e6c011610097578063e0d8bc1811610071578063e0d8bc1814610609578063f2fde38b1461066c578063fab07b6314610692578063ff7bffa1146106d8576101b9565b8063ab02e6c014610585578063c0b05da0146105ab578063c4bb759b146105e3576101b9565b8063715018a6116100d3578063715018a6146104ca578063793cef51146104d25780638da5cb5b146105755780638f32d59b1461057d576101b9565b80634afb215e14610457578063607e45691461047d57806367c0c689146104a3576101b9565b806321a2d9d011610166578063360e10ae11610140578063360e10ae1461033f5780633b2d10e8146103655780633ed739c31461039b578063462d0b2e146103de576101b9565b806321a2d9d0146102b15780632e730a8e14610309578063320836a814610311576101b9565b8063132e8aa711610197578063132e8aa714610254578063158ef93e146102785780631d82c3a314610294576101b9565b806307437f6c146101be57806309833c3e146101f65780630c6071461461021c575b600080fd5b6101f4600480360360408110156101d457600080fd5b5080356001600160a01b0316906020013567ffffffffffffffff16610706565b005b6101f46004803603602081101561020c57600080fd5b50356001600160a01b031661097c565b6101f46004803603606081101561023257600080fd5b506001600160a01b038135811691602081013590911690604001351515610d57565b61025c610f8b565b604080516001600160a01b039092168252519081900360200190f35b610280610f9a565b604080519115158252519081900360200190f35b61025c600480360360208110156102aa57600080fd5b5035610fa3565b6102b9610fca565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156102f55781810151838201526020016102dd565b505050509050019250505060405180910390f35b6102b961110a565b6102806004803603604081101561032757600080fd5b506001600160a01b038135811691602001351661116c565b6101f46004803603602081101561035557600080fd5b50356001600160a01b031661118c565b6101f46004803603604081101561037b57600080fd5b5080356001600160a01b0316906020013567ffffffffffffffff1661161a565b6103c1600480360360208110156103b157600080fd5b50356001600160a01b03166118a6565b6040805167ffffffffffffffff9092168252519081900360200190f35b6101f4600480360360408110156103f457600080fd5b81019060208101813564010000000081111561040f57600080fd5b82018360208201111561042157600080fd5b8035906020019184602083028401116401000000008311171561044357600080fd5b9193509150356001600160a01b03166118c2565b6101f46004803603602081101561046d57600080fd5b50356001600160a01b0316611998565b6102806004803603602081101561049357600080fd5b50356001600160a01b0316611a98565b61025c600480360360208110156104b957600080fd5b503567ffffffffffffffff16611b48565b6101f4611b63565b6101f4600480360360208110156104e857600080fd5b81019060208101813564010000000081111561050357600080fd5b82018360208201111561051557600080fd5b8035906020019184602083028401116401000000008311171561053757600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550611c22945050505050565b61025c611caf565b610280611cc3565b6101f46004803603602081101561059b57600080fd5b50356001600160a01b0316611cec565b6105d1600480360360208110156105c157600080fd5b50356001600160a01b03166123b6565b60408051918252519081900360200190f35b6101f4600480360360208110156105f957600080fd5b50356001600160a01b031661243b565b61062f6004803603602081101561061f57600080fd5b50356001600160a01b0316612829565b6040805167ffffffffffffffff94851681529290931660208301526fffffffffffffffffffffffffffffffff168183015290519081900360600190f35b6101f46004803603602081101561068257600080fd5b50356001600160a01b031661287e565b6101f4600480360360808110156106a857600080fd5b506001600160a01b03813581169167ffffffffffffffff60208201351691604082013581169160600135166128e0565b610280600480360360408110156106ee57600080fd5b506001600160a01b0381358116916020013516612b69565b61070e611cc3565b61075f576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b818161076a82611a98565b156107a65760405162461bcd60e51b8152600401808060200182810382526023815260200180612ede6023913960400191505060405180910390fd5b67ffffffffffffffff81166000908152600360205260409020546001600160a01b0316156108055760405162461bcd60e51b815260040180806020018281038252603b815260200180612e72603b913960400191505060405180910390fd5b67ffffffffffffffff811661084b5760405162461bcd60e51b815260040180806020018281038252602f815260200180612db8602f913960400191505060405180910390fd5b67ffffffffffffffff8316600081815260036020908152604080832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038a16908117909155808452600492839052818420805467ffffffffffffffff191690951790945580517f26afac4900000000000000000000000000000000000000000000000000000000815260059281019290925260248201939093529151736200f54d73491d56b8d7a975c9ee18efb4d518df926326afac49926044808301939192829003018186803b15801561092a57600080fd5b505af415801561093e573d6000803e3d6000fd5b50506040516001600160a01b03871692507fb41d9a8e03d4798a0a905017e377ecae53ebc5ca694c8fccaeabb5a08c0d333f9150600090a250505050565b610984611cc3565b6109d5576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6109dd612d97565b506001600160a01b0381166000908152600260209081526040918290208251606081018452905467ffffffffffffffff80821683526801000000000000000082041692820183905270010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff169281019290925215610a8e5760405162461bcd60e51b8152600401808060200182810382526023815260200180612f016023913960400191505060405180910390fd5b600a54604080517f8e7492810000000000000000000000000000000000000000000000000000000081526001600160a01b03858116600483015291516000939290921691638e749281916024808201928692909190829003018186803b158015610af757600080fd5b505afa158015610b0b573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526020811015610b5257600080fd5b8101908080516040519392919084640100000000821115610b7257600080fd5b908301906020820185811115610b8757600080fd5b8251866020820283011164010000000082111715610ba457600080fd5b82525081516020918201928201910280838360005b83811015610bd1578181015183820152602001610bb9565b505050509050016040525050505111610c1b5760405162461bcd60e51b815260040180806020018281038252602f815260200180612f45602f913960400191505060405180910390fd5b60008082524267ffffffffffffffff90811660208085019182526fffffffffffffffffffffffffffffffff43811660408088019182526001600160a01b0389168088526002909452808720885181549651935185167001000000000000000000000000000000000293881668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff9190981667ffffffffffffffff19909716969096179590951695909517909116179091556001805480820182559084527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60180547fffffffffffffffffffffffff00000000000000000000000000000000000000001682179055905190917fa1bccd87833fab06528ad8412cd349ff6ec2f1b851f48592a05ff995e4e7347d91a25050565b610d5f611cc3565b610db0576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b610db8612d97565b506001600160a01b0382166000908152600260209081526040918290208251606081018452905467ffffffffffffffff80821683526801000000000000000082041692820183905270010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1692810192909252610e685760405162461bcd60e51b8152600401808060200182810382526033815260200180612e3f6033913960400191505060405180910390fd5b610e7184611a98565b610eac5760405162461bcd60e51b8152600401808060200182810382526031815260200180612ead6031913960400191505060405180910390fd5b81158015610edf5750805167ffffffffffffffff166000908152600360205260409020546001600160a01b038581169116145b15610eef57610eef83600061161a565b6001600160a01b0380851660008181526009602090815260408083209488168084529482529182902080548715157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090911681179091558251938452908301939093528181019290925290517f292d7648986a4abc017bc2a39852a675c1e325e24afd18fad659810792d5e4059181900360600190a150505050565b600a546001600160a01b031681565b60005460ff1681565b60018181548110610fb057fe5b6000918252602090912001546001600160a01b0316905081565b60606005736200f54d73491d56b8d7a975c9ee18efb4d518df63fe3c7a8e90916040518263ffffffff1660e01b81526004018082815260200191505060006040518083038186803b15801561101e57600080fd5b505af4158015611032573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052602081101561107957600080fd5b810190808051604051939291908464010000000082111561109957600080fd5b9083019060208201858111156110ae57600080fd5b82518660208202830111640100000000821117156110cb57600080fd5b82525081516020918201928201910280838360005b838110156110f85781810151838201526020016110e0565b50505050905001604052505050905090565b6060600180548060200260200160405190810160405280929190818152602001828054801561116257602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611144575b5050505050905090565b600960209081526000928352604080842090915290825290205460ff1681565b611194611cc3565b6111e5576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6000805b60015481101561123557826001600160a01b03166001828154811061120a57fe5b6000918252602090912001546001600160a01b0316141561122d57809150611235565b6001016111e9565b50816001600160a01b03166001828154811061124d57fe5b6000918252602090912001546001600160a01b0316146112b4576040805162461bcd60e51b815260206004820152601f60248201527f52617465206665656420494420686173206e6f74206265656e20616464656400604482015290519081900360640190fd5b600180546000916112cb919063ffffffff612b9716565b905080821461133657600181815481106112e157fe5b600091825260209091200154600180546001600160a01b03909216918490811061130757fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055505b600180548061134157fe5b6000828152602080822083017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690559092019092556001600160a01b038516825260029052604080822082905580517ffe3c7a8e000000000000000000000000000000000000000000000000000000008152600560048201529051606092736200f54d73491d56b8d7a975c9ee18efb4d518df9263fe3c7a8e9260248083019392829003018186803b15801561141d57600080fd5b505af4158015611431573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052602081101561147857600080fd5b810190808051604051939291908464010000000082111561149857600080fd5b9083019060208201858111156114ad57600080fd5b82518660208202830111640100000000821117156114ca57600080fd5b82525081516020918201928201910280838360005b838110156114f75781810151838201526020016114df565b50505050905001604052505050905060008090505b81518110156115df576009600083838151811061152557fe5b6020908102919091018101516001600160a01b0390811683528282019390935260409182016000908120938916815292905290205460ff16156115d75760006009600084848151811061157457fe5b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000876001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff0219169083151502179055505b60010161150c565b506040516001600160a01b038516907f2646cbfbc7a17246cd5998517025a987bbdc416a91f2482601aeb30045d3881990600090a250505050565b611622611cc3565b611673576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b67ffffffffffffffff811615806116ab575067ffffffffffffffff81166000908152600360205260409020546001600160a01b031615155b6116e65760405162461bcd60e51b8152600401808060200182810382526032815260200180612de76032913960400191505060405180910390fd5b6116ee612d97565b506001600160a01b0382166000908152600260209081526040918290208251606081018452905467ffffffffffffffff80821683526801000000000000000082041692820183905270010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16928101929092526117b4576040805162461bcd60e51b815260206004820152601f60248201527f52617465206665656420494420686173206e6f74206265656e20616464656400604482015290519081900360640190fd5b67ffffffffffffffff80831680835242821660208085019182526fffffffffffffffffffffffffffffffff43811660408088019182526001600160a01b038a166000818152600286528290208951815497519451861670010000000000000000000000000000000002948a1668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff91909a1667ffffffffffffffff1990981697909717969096169790971790921617909255815192835290517fb64ea6f0b71eb82019a4e1cb18612c962bf400a2333377020f4a9ab71eeeeb529281900390910190a2505050565b60046020526000908152604090205467ffffffffffffffff1681565b60005460ff161561191a576040805162461bcd60e51b815260206004820152601c60248201527f636f6e747261637420616c726561647920696e697469616c697a656400000000604482015290519081900360640190fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905561194e33612be0565b61195781611998565b611993838380806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250611c2292505050565b505050565b6119a0611cc3565b6119f1576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b038116611a365760405162461bcd60e51b8152600401808060200182810382526021815260200180612f246021913960400191505060405180910390fd5b600a80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040517f590fd633a008765ce9e65e8081adfba311e99e11b958a5ecb5000ea3355f735390600090a250565b604080517f542424fb000000000000000000000000000000000000000000000000000000008152600560048201526001600160a01b03831660248201529051600091736200f54d73491d56b8d7a975c9ee18efb4d518df9163542424fb91604480820192602092909190829003018186803b158015611b1657600080fd5b505af4158015611b2a573d6000803e3d6000fd5b505050506040513d6020811015611b4057600080fd5b505192915050565b6003602052600090815260409020546001600160a01b031681565b611b6b611cc3565b611bbc576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600080546040516101009091046001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080547fffffffffffffffffffffff0000000000000000000000000000000000000000ff169055565b611c2a611cc3565b611c7b576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60005b8151811015611cab57611ca3828281518110611c9657fe5b602002602001015161097c565b600101611c7e565b5050565b60005461010090046001600160a01b031690565b6000805461010090046001600160a01b0316611cdd612ca2565b6001600160a01b031614905090565b611cf4612d97565b506001600160a01b0381166000908152600260209081526040918290208251606081018452905467ffffffffffffffff80821683526801000000000000000082041692820183905270010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1692810192909252611d7357506123b3565b805167ffffffffffffffff161561207357805167ffffffffffffffff1660009081526003602090815260408083205481517f39b84ecf0000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152925192909116939284926339b84ecf926024808201939291829003018186803b158015611e0357600080fd5b505afa158015611e17573d6000803e3d6000fd5b505050506040513d6020811015611e2d57600080fd5b505190508015801590611e60575042611e5d846020015167ffffffffffffffff1683612ca690919063ffffffff16565b11155b1561202857816001600160a01b03166368b89d58856040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b03168152602001915050602060405180830381600087803b158015611ebd57600080fd5b505af1158015611ed1573d6000803e3d6000fd5b505050506040513d6020811015611ee757600080fd5b505115611fdb5760008084524267ffffffffffffffff90811660208087019182526fffffffffffffffffffffffffffffffff4381166040808a019182526001600160a01b03808c1680895260029095528188208b5181549751945186167001000000000000000000000000000000000294891668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff9190991667ffffffffffffffff199098169790971796909616969096179092161790925590519185169290917fd45bd915ab99a070b980cdf13e671da6b79cc32e66eff6dc12c83a92071e6ab39190a3612023565b816001600160a01b0316846001600160a01b03167f90ca142474a3987fe4ec5cb24a254e13086fb998251070b5c9fc8ab70d78b8af60405160405180910390a35050506123b3565b612070565b816001600160a01b0316846001600160a01b03167f636207d0069f1a3500c8d1676c804bc9d9a9d27e9add85139022a1757edf552260405160405180910390a35050506123b3565b50505b60606005736200f54d73491d56b8d7a975c9ee18efb4d518df63fe3c7a8e90916040518263ffffffff1660e01b81526004018082815260200191505060006040518083038186803b1580156120c757600080fd5b505af41580156120db573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052602081101561212257600080fd5b810190808051604051939291908464010000000082111561214257600080fd5b90830190602082018581111561215757600080fd5b825186602082028301116401000000008211171561217457600080fd5b82525081516020918201928201910280838360005b838110156121a1578181015183820152602001612189565b50505050905001604052505050905060008090505b81518110156123af57600960008383815181106121cf57fe5b6020908102919091018101516001600160a01b0390811683528282019390935260409182016000908120938816815292905290205460ff16156123a757600082828151811061221a57fe5b602002602001015190506000816001600160a01b031663fd165f53876040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b03168152602001915050602060405180830381600087803b15801561227e57600080fd5b505af1158015612292573d6000803e3d6000fd5b505050506040513d60208110156122a857600080fd5b5051905080156123a4576001600160a01b0382811660008181526004602090815260408083205467ffffffffffffffff9081168b524281168b8401908152436fffffffffffffffffffffffffffffffff9081168d8501908152978e1680875260029095528386208d5181549351995167ffffffffffffffff19909416908516177fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff1668010000000000000000999094169890980292909217821670010000000000000000000000000000000091909216021790945592517fe59f00019fc03badf2caa7d5de220ccfa5a411564a41f3b15906c02fd20150d59190a35b50505b6001016121b6565b5050505b50565b60006123c0612d97565b50506001600160a01b03166000908152600260209081526040918290208251606081018452905467ffffffffffffffff8082168084526801000000000000000083049091169383019390935270010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1692019190915290565b612443611cc3565b612494576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b61249d81611a98565b6124ee576040805162461bcd60e51b815260206004820152601f60248201527f5468697320627265616b657220686173206e6f74206265656e20616464656400604482015290519081900360640190fd5b6001600160a01b038116600090815260046020908152604091829020546001805484518185028101850190955280855267ffffffffffffffff9092169360609390929083018282801561256a57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161254c575b50505050509050612579612d97565b60005b8251811015612704576002600084838151811061259557fe5b6020908102919091018101516001600160a01b031682528181019290925260409081016000208151606081018352905467ffffffffffffffff8082168084526801000000000000000083048216958401959095527001000000000000000000000000000000009091046fffffffffffffffffffffffffffffffff169282019290925293508516141561263f5761263f83828151811061263057fe5b6020026020010151600061161a565b6001600160a01b0385166000908152600960205260408120845190919085908490811061266857fe5b6020908102919091018101516001600160a01b031682528101919091526040016000205460ff16156126fc576001600160a01b0385166000908152600960205260408120845182908690859081106126bc57fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff0219169083151502179055505b60010161257c565b5067ffffffffffffffff8316600090815260036020908152604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001690556001600160a01b038716808452600492839052818420805467ffffffffffffffff1916905581517fe2c0c56a000000000000000000000000000000000000000000000000000000008152600593810193909352602483015251736200f54d73491d56b8d7a975c9ee18efb4d518df9263e2c0c56a9260448082019391829003018186803b1580156127d757600080fd5b505af41580156127eb573d6000803e3d6000fd5b50506040516001600160a01b03871692507f25d0fcab10ffc3ea7a197ec99e51df0362a1485e3a020caa618dbf72f92bb9f39150600090a250505050565b60026020526000908152604090205467ffffffffffffffff808216916801000000000000000081049091169070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1683565b612886611cc3565b6128d7576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6123b381612be0565b6128e8611cc3565b612939576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b838361294482611a98565b156129805760405162461bcd60e51b8152600401808060200182810382526023815260200180612ede6023913960400191505060405180910390fd5b67ffffffffffffffff81166000908152600360205260409020546001600160a01b0316156129df5760405162461bcd60e51b815260040180806020018281038252603b815260200180612e72603b913960400191505060405180910390fd5b67ffffffffffffffff8116612a255760405162461bcd60e51b815260040180806020018281038252602f815260200180612db8602f913960400191505060405180910390fd5b67ffffffffffffffff8516600081815260036020908152604080832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038c8116918217909255808552600493849052828520805467ffffffffffffffff191690961790955581517f07debf7c0000000000000000000000000000000000000000000000000000000081526005938101939093526024830194909452878416604483015292861660648201529151736200f54d73491d56b8d7a975c9ee18efb4d518df926307debf7c926084808301939192829003018186803b158015612b1557600080fd5b505af4158015612b29573d6000803e3d6000fd5b50506040516001600160a01b03891692507fb41d9a8e03d4798a0a905017e377ecae53ebc5ca694c8fccaeabb5a08c0d333f9150600090a2505050505050565b6001600160a01b03918216600090815260096020908152604080832093909416825291909152205460ff1690565b6000612bd983836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612d00565b9392505050565b6001600160a01b038116612c255760405162461bcd60e51b8152600401808060200182810382526026815260200180612e196026913960400191505060405180910390fd5b600080546040516001600160a01b038085169361010090930416917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b03909216610100027fffffffffffffffffffffff0000000000000000000000000000000000000000ff909216919091179055565b3390565b600082820183811015612bd9576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60008184841115612d8f5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612d54578181015183820152602001612d3c565b50505050905090810190601f168015612d815780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b60408051606081018252600080825260208201819052918101919091529056fe5468652064656661756c742074726164696e67206d6f64652063616e206e6f742068617665206120627265616b657254726164696e67206d6f6465206d7573742062652064656661756c74206f722068617665206120627265616b6572207365744f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373546869732072617465206665656420686173206e6f74206265656e20616464656420746f2074686520427265616b6572426f78546865726520697320616c7265616479206120627265616b65722061646465642077697468207468652073616d652074726164696e67206d6f64655468697320627265616b657220686173206e6f74206265656e20616464656420746f2074686520427265616b6572426f785468697320627265616b65722068617320616c7265616479206265656e2061646465645261746520666565642049442068617320616c7265616479206265656e206164646564536f727465644f7261636c65732061646472657373206d7573742062652073657452617465206665656420494420646f6573206e6f74206578697374206173206974206861732030206f7261636c6573a265627a7a723158201f19e4ba64c3acb116b113470f105c5af2bc8ef653c39ffe9240af5bf24349af64736f6c634300051100320000000000000000000000000000000000000000000000000000000000000000
Deployed ByteCode
0x608060405234801561001057600080fd5b50600436106101b95760003560e01c80634afb215e116100f9578063ab02e6c011610097578063e0d8bc1811610071578063e0d8bc1814610609578063f2fde38b1461066c578063fab07b6314610692578063ff7bffa1146106d8576101b9565b8063ab02e6c014610585578063c0b05da0146105ab578063c4bb759b146105e3576101b9565b8063715018a6116100d3578063715018a6146104ca578063793cef51146104d25780638da5cb5b146105755780638f32d59b1461057d576101b9565b80634afb215e14610457578063607e45691461047d57806367c0c689146104a3576101b9565b806321a2d9d011610166578063360e10ae11610140578063360e10ae1461033f5780633b2d10e8146103655780633ed739c31461039b578063462d0b2e146103de576101b9565b806321a2d9d0146102b15780632e730a8e14610309578063320836a814610311576101b9565b8063132e8aa711610197578063132e8aa714610254578063158ef93e146102785780631d82c3a314610294576101b9565b806307437f6c146101be57806309833c3e146101f65780630c6071461461021c575b600080fd5b6101f4600480360360408110156101d457600080fd5b5080356001600160a01b0316906020013567ffffffffffffffff16610706565b005b6101f46004803603602081101561020c57600080fd5b50356001600160a01b031661097c565b6101f46004803603606081101561023257600080fd5b506001600160a01b038135811691602081013590911690604001351515610d57565b61025c610f8b565b604080516001600160a01b039092168252519081900360200190f35b610280610f9a565b604080519115158252519081900360200190f35b61025c600480360360208110156102aa57600080fd5b5035610fa3565b6102b9610fca565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156102f55781810151838201526020016102dd565b505050509050019250505060405180910390f35b6102b961110a565b6102806004803603604081101561032757600080fd5b506001600160a01b038135811691602001351661116c565b6101f46004803603602081101561035557600080fd5b50356001600160a01b031661118c565b6101f46004803603604081101561037b57600080fd5b5080356001600160a01b0316906020013567ffffffffffffffff1661161a565b6103c1600480360360208110156103b157600080fd5b50356001600160a01b03166118a6565b6040805167ffffffffffffffff9092168252519081900360200190f35b6101f4600480360360408110156103f457600080fd5b81019060208101813564010000000081111561040f57600080fd5b82018360208201111561042157600080fd5b8035906020019184602083028401116401000000008311171561044357600080fd5b9193509150356001600160a01b03166118c2565b6101f46004803603602081101561046d57600080fd5b50356001600160a01b0316611998565b6102806004803603602081101561049357600080fd5b50356001600160a01b0316611a98565b61025c600480360360208110156104b957600080fd5b503567ffffffffffffffff16611b48565b6101f4611b63565b6101f4600480360360208110156104e857600080fd5b81019060208101813564010000000081111561050357600080fd5b82018360208201111561051557600080fd5b8035906020019184602083028401116401000000008311171561053757600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550611c22945050505050565b61025c611caf565b610280611cc3565b6101f46004803603602081101561059b57600080fd5b50356001600160a01b0316611cec565b6105d1600480360360208110156105c157600080fd5b50356001600160a01b03166123b6565b60408051918252519081900360200190f35b6101f4600480360360208110156105f957600080fd5b50356001600160a01b031661243b565b61062f6004803603602081101561061f57600080fd5b50356001600160a01b0316612829565b6040805167ffffffffffffffff94851681529290931660208301526fffffffffffffffffffffffffffffffff168183015290519081900360600190f35b6101f46004803603602081101561068257600080fd5b50356001600160a01b031661287e565b6101f4600480360360808110156106a857600080fd5b506001600160a01b03813581169167ffffffffffffffff60208201351691604082013581169160600135166128e0565b610280600480360360408110156106ee57600080fd5b506001600160a01b0381358116916020013516612b69565b61070e611cc3565b61075f576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b818161076a82611a98565b156107a65760405162461bcd60e51b8152600401808060200182810382526023815260200180612ede6023913960400191505060405180910390fd5b67ffffffffffffffff81166000908152600360205260409020546001600160a01b0316156108055760405162461bcd60e51b815260040180806020018281038252603b815260200180612e72603b913960400191505060405180910390fd5b67ffffffffffffffff811661084b5760405162461bcd60e51b815260040180806020018281038252602f815260200180612db8602f913960400191505060405180910390fd5b67ffffffffffffffff8316600081815260036020908152604080832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038a16908117909155808452600492839052818420805467ffffffffffffffff191690951790945580517f26afac4900000000000000000000000000000000000000000000000000000000815260059281019290925260248201939093529151736200f54d73491d56b8d7a975c9ee18efb4d518df926326afac49926044808301939192829003018186803b15801561092a57600080fd5b505af415801561093e573d6000803e3d6000fd5b50506040516001600160a01b03871692507fb41d9a8e03d4798a0a905017e377ecae53ebc5ca694c8fccaeabb5a08c0d333f9150600090a250505050565b610984611cc3565b6109d5576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6109dd612d97565b506001600160a01b0381166000908152600260209081526040918290208251606081018452905467ffffffffffffffff80821683526801000000000000000082041692820183905270010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff169281019290925215610a8e5760405162461bcd60e51b8152600401808060200182810382526023815260200180612f016023913960400191505060405180910390fd5b600a54604080517f8e7492810000000000000000000000000000000000000000000000000000000081526001600160a01b03858116600483015291516000939290921691638e749281916024808201928692909190829003018186803b158015610af757600080fd5b505afa158015610b0b573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526020811015610b5257600080fd5b8101908080516040519392919084640100000000821115610b7257600080fd5b908301906020820185811115610b8757600080fd5b8251866020820283011164010000000082111715610ba457600080fd5b82525081516020918201928201910280838360005b83811015610bd1578181015183820152602001610bb9565b505050509050016040525050505111610c1b5760405162461bcd60e51b815260040180806020018281038252602f815260200180612f45602f913960400191505060405180910390fd5b60008082524267ffffffffffffffff90811660208085019182526fffffffffffffffffffffffffffffffff43811660408088019182526001600160a01b0389168088526002909452808720885181549651935185167001000000000000000000000000000000000293881668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff9190981667ffffffffffffffff19909716969096179590951695909517909116179091556001805480820182559084527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60180547fffffffffffffffffffffffff00000000000000000000000000000000000000001682179055905190917fa1bccd87833fab06528ad8412cd349ff6ec2f1b851f48592a05ff995e4e7347d91a25050565b610d5f611cc3565b610db0576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b610db8612d97565b506001600160a01b0382166000908152600260209081526040918290208251606081018452905467ffffffffffffffff80821683526801000000000000000082041692820183905270010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1692810192909252610e685760405162461bcd60e51b8152600401808060200182810382526033815260200180612e3f6033913960400191505060405180910390fd5b610e7184611a98565b610eac5760405162461bcd60e51b8152600401808060200182810382526031815260200180612ead6031913960400191505060405180910390fd5b81158015610edf5750805167ffffffffffffffff166000908152600360205260409020546001600160a01b038581169116145b15610eef57610eef83600061161a565b6001600160a01b0380851660008181526009602090815260408083209488168084529482529182902080548715157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090911681179091558251938452908301939093528181019290925290517f292d7648986a4abc017bc2a39852a675c1e325e24afd18fad659810792d5e4059181900360600190a150505050565b600a546001600160a01b031681565b60005460ff1681565b60018181548110610fb057fe5b6000918252602090912001546001600160a01b0316905081565b60606005736200f54d73491d56b8d7a975c9ee18efb4d518df63fe3c7a8e90916040518263ffffffff1660e01b81526004018082815260200191505060006040518083038186803b15801561101e57600080fd5b505af4158015611032573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052602081101561107957600080fd5b810190808051604051939291908464010000000082111561109957600080fd5b9083019060208201858111156110ae57600080fd5b82518660208202830111640100000000821117156110cb57600080fd5b82525081516020918201928201910280838360005b838110156110f85781810151838201526020016110e0565b50505050905001604052505050905090565b6060600180548060200260200160405190810160405280929190818152602001828054801561116257602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611144575b5050505050905090565b600960209081526000928352604080842090915290825290205460ff1681565b611194611cc3565b6111e5576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6000805b60015481101561123557826001600160a01b03166001828154811061120a57fe5b6000918252602090912001546001600160a01b0316141561122d57809150611235565b6001016111e9565b50816001600160a01b03166001828154811061124d57fe5b6000918252602090912001546001600160a01b0316146112b4576040805162461bcd60e51b815260206004820152601f60248201527f52617465206665656420494420686173206e6f74206265656e20616464656400604482015290519081900360640190fd5b600180546000916112cb919063ffffffff612b9716565b905080821461133657600181815481106112e157fe5b600091825260209091200154600180546001600160a01b03909216918490811061130757fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055505b600180548061134157fe5b6000828152602080822083017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690559092019092556001600160a01b038516825260029052604080822082905580517ffe3c7a8e000000000000000000000000000000000000000000000000000000008152600560048201529051606092736200f54d73491d56b8d7a975c9ee18efb4d518df9263fe3c7a8e9260248083019392829003018186803b15801561141d57600080fd5b505af4158015611431573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052602081101561147857600080fd5b810190808051604051939291908464010000000082111561149857600080fd5b9083019060208201858111156114ad57600080fd5b82518660208202830111640100000000821117156114ca57600080fd5b82525081516020918201928201910280838360005b838110156114f75781810151838201526020016114df565b50505050905001604052505050905060008090505b81518110156115df576009600083838151811061152557fe5b6020908102919091018101516001600160a01b0390811683528282019390935260409182016000908120938916815292905290205460ff16156115d75760006009600084848151811061157457fe5b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000206000876001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff0219169083151502179055505b60010161150c565b506040516001600160a01b038516907f2646cbfbc7a17246cd5998517025a987bbdc416a91f2482601aeb30045d3881990600090a250505050565b611622611cc3565b611673576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b67ffffffffffffffff811615806116ab575067ffffffffffffffff81166000908152600360205260409020546001600160a01b031615155b6116e65760405162461bcd60e51b8152600401808060200182810382526032815260200180612de76032913960400191505060405180910390fd5b6116ee612d97565b506001600160a01b0382166000908152600260209081526040918290208251606081018452905467ffffffffffffffff80821683526801000000000000000082041692820183905270010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16928101929092526117b4576040805162461bcd60e51b815260206004820152601f60248201527f52617465206665656420494420686173206e6f74206265656e20616464656400604482015290519081900360640190fd5b67ffffffffffffffff80831680835242821660208085019182526fffffffffffffffffffffffffffffffff43811660408088019182526001600160a01b038a166000818152600286528290208951815497519451861670010000000000000000000000000000000002948a1668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff91909a1667ffffffffffffffff1990981697909717969096169790971790921617909255815192835290517fb64ea6f0b71eb82019a4e1cb18612c962bf400a2333377020f4a9ab71eeeeb529281900390910190a2505050565b60046020526000908152604090205467ffffffffffffffff1681565b60005460ff161561191a576040805162461bcd60e51b815260206004820152601c60248201527f636f6e747261637420616c726561647920696e697469616c697a656400000000604482015290519081900360640190fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905561194e33612be0565b61195781611998565b611993838380806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250611c2292505050565b505050565b6119a0611cc3565b6119f1576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b038116611a365760405162461bcd60e51b8152600401808060200182810382526021815260200180612f246021913960400191505060405180910390fd5b600a80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040517f590fd633a008765ce9e65e8081adfba311e99e11b958a5ecb5000ea3355f735390600090a250565b604080517f542424fb000000000000000000000000000000000000000000000000000000008152600560048201526001600160a01b03831660248201529051600091736200f54d73491d56b8d7a975c9ee18efb4d518df9163542424fb91604480820192602092909190829003018186803b158015611b1657600080fd5b505af4158015611b2a573d6000803e3d6000fd5b505050506040513d6020811015611b4057600080fd5b505192915050565b6003602052600090815260409020546001600160a01b031681565b611b6b611cc3565b611bbc576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600080546040516101009091046001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080547fffffffffffffffffffffff0000000000000000000000000000000000000000ff169055565b611c2a611cc3565b611c7b576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b60005b8151811015611cab57611ca3828281518110611c9657fe5b602002602001015161097c565b600101611c7e565b5050565b60005461010090046001600160a01b031690565b6000805461010090046001600160a01b0316611cdd612ca2565b6001600160a01b031614905090565b611cf4612d97565b506001600160a01b0381166000908152600260209081526040918290208251606081018452905467ffffffffffffffff80821683526801000000000000000082041692820183905270010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1692810192909252611d7357506123b3565b805167ffffffffffffffff161561207357805167ffffffffffffffff1660009081526003602090815260408083205481517f39b84ecf0000000000000000000000000000000000000000000000000000000081526001600160a01b038781166004830152925192909116939284926339b84ecf926024808201939291829003018186803b158015611e0357600080fd5b505afa158015611e17573d6000803e3d6000fd5b505050506040513d6020811015611e2d57600080fd5b505190508015801590611e60575042611e5d846020015167ffffffffffffffff1683612ca690919063ffffffff16565b11155b1561202857816001600160a01b03166368b89d58856040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b03168152602001915050602060405180830381600087803b158015611ebd57600080fd5b505af1158015611ed1573d6000803e3d6000fd5b505050506040513d6020811015611ee757600080fd5b505115611fdb5760008084524267ffffffffffffffff90811660208087019182526fffffffffffffffffffffffffffffffff4381166040808a019182526001600160a01b03808c1680895260029095528188208b5181549751945186167001000000000000000000000000000000000294891668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff9190991667ffffffffffffffff199098169790971796909616969096179092161790925590519185169290917fd45bd915ab99a070b980cdf13e671da6b79cc32e66eff6dc12c83a92071e6ab39190a3612023565b816001600160a01b0316846001600160a01b03167f90ca142474a3987fe4ec5cb24a254e13086fb998251070b5c9fc8ab70d78b8af60405160405180910390a35050506123b3565b612070565b816001600160a01b0316846001600160a01b03167f636207d0069f1a3500c8d1676c804bc9d9a9d27e9add85139022a1757edf552260405160405180910390a35050506123b3565b50505b60606005736200f54d73491d56b8d7a975c9ee18efb4d518df63fe3c7a8e90916040518263ffffffff1660e01b81526004018082815260200191505060006040518083038186803b1580156120c757600080fd5b505af41580156120db573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052602081101561212257600080fd5b810190808051604051939291908464010000000082111561214257600080fd5b90830190602082018581111561215757600080fd5b825186602082028301116401000000008211171561217457600080fd5b82525081516020918201928201910280838360005b838110156121a1578181015183820152602001612189565b50505050905001604052505050905060008090505b81518110156123af57600960008383815181106121cf57fe5b6020908102919091018101516001600160a01b0390811683528282019390935260409182016000908120938816815292905290205460ff16156123a757600082828151811061221a57fe5b602002602001015190506000816001600160a01b031663fd165f53876040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b03168152602001915050602060405180830381600087803b15801561227e57600080fd5b505af1158015612292573d6000803e3d6000fd5b505050506040513d60208110156122a857600080fd5b5051905080156123a4576001600160a01b0382811660008181526004602090815260408083205467ffffffffffffffff9081168b524281168b8401908152436fffffffffffffffffffffffffffffffff9081168d8501908152978e1680875260029095528386208d5181549351995167ffffffffffffffff19909416908516177fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff1668010000000000000000999094169890980292909217821670010000000000000000000000000000000091909216021790945592517fe59f00019fc03badf2caa7d5de220ccfa5a411564a41f3b15906c02fd20150d59190a35b50505b6001016121b6565b5050505b50565b60006123c0612d97565b50506001600160a01b03166000908152600260209081526040918290208251606081018452905467ffffffffffffffff8082168084526801000000000000000083049091169383019390935270010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1692019190915290565b612443611cc3565b612494576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b61249d81611a98565b6124ee576040805162461bcd60e51b815260206004820152601f60248201527f5468697320627265616b657220686173206e6f74206265656e20616464656400604482015290519081900360640190fd5b6001600160a01b038116600090815260046020908152604091829020546001805484518185028101850190955280855267ffffffffffffffff9092169360609390929083018282801561256a57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161254c575b50505050509050612579612d97565b60005b8251811015612704576002600084838151811061259557fe5b6020908102919091018101516001600160a01b031682528181019290925260409081016000208151606081018352905467ffffffffffffffff8082168084526801000000000000000083048216958401959095527001000000000000000000000000000000009091046fffffffffffffffffffffffffffffffff169282019290925293508516141561263f5761263f83828151811061263057fe5b6020026020010151600061161a565b6001600160a01b0385166000908152600960205260408120845190919085908490811061266857fe5b6020908102919091018101516001600160a01b031682528101919091526040016000205460ff16156126fc576001600160a01b0385166000908152600960205260408120845182908690859081106126bc57fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff0219169083151502179055505b60010161257c565b5067ffffffffffffffff8316600090815260036020908152604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000001690556001600160a01b038716808452600492839052818420805467ffffffffffffffff1916905581517fe2c0c56a000000000000000000000000000000000000000000000000000000008152600593810193909352602483015251736200f54d73491d56b8d7a975c9ee18efb4d518df9263e2c0c56a9260448082019391829003018186803b1580156127d757600080fd5b505af41580156127eb573d6000803e3d6000fd5b50506040516001600160a01b03871692507f25d0fcab10ffc3ea7a197ec99e51df0362a1485e3a020caa618dbf72f92bb9f39150600090a250505050565b60026020526000908152604090205467ffffffffffffffff808216916801000000000000000081049091169070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1683565b612886611cc3565b6128d7576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6123b381612be0565b6128e8611cc3565b612939576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b838361294482611a98565b156129805760405162461bcd60e51b8152600401808060200182810382526023815260200180612ede6023913960400191505060405180910390fd5b67ffffffffffffffff81166000908152600360205260409020546001600160a01b0316156129df5760405162461bcd60e51b815260040180806020018281038252603b815260200180612e72603b913960400191505060405180910390fd5b67ffffffffffffffff8116612a255760405162461bcd60e51b815260040180806020018281038252602f815260200180612db8602f913960400191505060405180910390fd5b67ffffffffffffffff8516600081815260036020908152604080832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038c8116918217909255808552600493849052828520805467ffffffffffffffff191690961790955581517f07debf7c0000000000000000000000000000000000000000000000000000000081526005938101939093526024830194909452878416604483015292861660648201529151736200f54d73491d56b8d7a975c9ee18efb4d518df926307debf7c926084808301939192829003018186803b158015612b1557600080fd5b505af4158015612b29573d6000803e3d6000fd5b50506040516001600160a01b03891692507fb41d9a8e03d4798a0a905017e377ecae53ebc5ca694c8fccaeabb5a08c0d333f9150600090a2505050505050565b6001600160a01b03918216600090815260096020908152604080832093909416825291909152205460ff1690565b6000612bd983836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612d00565b9392505050565b6001600160a01b038116612c255760405162461bcd60e51b8152600401808060200182810382526026815260200180612e196026913960400191505060405180910390fd5b600080546040516001600160a01b038085169361010090930416917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b03909216610100027fffffffffffffffffffffff0000000000000000000000000000000000000000ff909216919091179055565b3390565b600082820183811015612bd9576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60008184841115612d8f5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612d54578181015183820152602001612d3c565b50505050905090810190601f168015612d815780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b60408051606081018252600080825260208201819052918101919091529056fe5468652064656661756c742074726164696e67206d6f64652063616e206e6f742068617665206120627265616b657254726164696e67206d6f6465206d7573742062652064656661756c74206f722068617665206120627265616b6572207365744f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373546869732072617465206665656420686173206e6f74206265656e20616464656420746f2074686520427265616b6572426f78546865726520697320616c7265616479206120627265616b65722061646465642077697468207468652073616d652074726164696e67206d6f64655468697320627265616b657220686173206e6f74206265656e20616464656420746f2074686520427265616b6572426f785468697320627265616b65722068617320616c7265616479206265656e2061646465645261746520666565642049442068617320616c7265616479206265656e206164646564536f727465644f7261636c65732061646472657373206d7573742062652073657452617465206665656420494420646f6573206e6f74206578697374206173206974206861732030206f7261636c6573a265627a7a723158201f19e4ba64c3acb116b113470f105c5af2bc8ef653c39ffe9240af5bf24349af64736f6c63430005110032
External libraries
AddressLinkedList : 0x6200f54d73491d56b8d7a975c9ee18efb4d518df
AddressSortedLinkedListWithMedian : 0xed477a99035d0c1e11369f1d7a4e587893cc002b