Contract Overview
Balance:
0 CELO
CELO Value:
$0.00
My Name Tag:
Not Available, login to update
Txn Hash | Method |
Block
|
From
|
To
|
Value | [Txn Fee] | |||
---|---|---|---|---|---|---|---|---|---|
0xd7eb37b41e8bab5c634034e5d340a2aca50bc8dabf18042b9392fe0db4254356 | 0x60806040 | 18261658 | 11 days 9 hrs ago | 0xbf841a8229f4995c080703098fb73455c4e7215b | IN | Create: CustomUrlsConsumerBase | 0 CELO | 0.0109689225 |
[ Download CSV Export ]
Contract Source Code Verified (Exact Match)
Contract Name:
CustomUrlsConsumerBase
Compiler Version
v0.8.17+commit.8df45f5f
Contract Source Code (Solidity)
/** *Submitted for verification at celoscan.io on 2023-03-16 */ // File: https://github.com/redstone-finance/redstone-oracles-monorepo/blob/4470072aab0e5a64ded46dda53a456f7d91f5d90/packages/evm-connector/contracts/libs/SignatureLib.sol pragma solidity ^0.8.4; library SignatureLib { uint256 constant ECDSA_SIG_R_BS = 32; uint256 constant ECDSA_SIG_S_BS = 32; function recoverSignerAddress(bytes32 signedHash, uint256 signatureCalldataNegativeOffset) internal pure returns (address) { bytes32 r; bytes32 s; uint8 v; assembly { let signatureCalldataStartPos := sub(calldatasize(), signatureCalldataNegativeOffset) r := calldataload(signatureCalldataStartPos) signatureCalldataStartPos := add(signatureCalldataStartPos, ECDSA_SIG_R_BS) s := calldataload(signatureCalldataStartPos) signatureCalldataStartPos := add(signatureCalldataStartPos, ECDSA_SIG_S_BS) v := byte(0, calldataload(signatureCalldataStartPos)) // last byte of the signature memory array } return ecrecover(signedHash, v, r, s); } } // File: https://github.com/redstone-finance/redstone-oracles-monorepo/blob/4470072aab0e5a64ded46dda53a456f7d91f5d90/packages/evm-connector/contracts/libs/BitmapLib.sol pragma solidity ^0.8.4; library BitmapLib { function setBitInBitmap(uint256 bitmap, uint256 bitIndex) internal pure returns (uint256) { return bitmap | (1 << bitIndex); } function getBitFromBitmap(uint256 bitmap, uint256 bitIndex) internal pure returns (bool) { uint256 bitAtIndex = bitmap & (1 << bitIndex); return bitAtIndex > 0; } } // File: https://github.com/redstone-finance/redstone-oracles-monorepo/blob/4470072aab0e5a64ded46dda53a456f7d91f5d90/packages/evm-connector/contracts/core/RedstoneConstants.sol pragma solidity ^0.8.4; /** * @title The base contract with helpful constants * @author The Redstone Oracles team * @dev It mainly contains redstone-related values, which improve readability * of other contracts (e.g. CalldataExtractor and RedstoneConsumerBase) */ contract RedstoneConstants { // === Abbreviations === // BS - Bytes size // PTR - Pointer (memory location) // SIG - Signature // Solidity and YUL constants uint256 internal constant STANDARD_SLOT_BS = 32; uint256 internal constant FREE_MEMORY_PTR = 0x40; uint256 internal constant BYTES_ARR_LEN_VAR_BS = 32; uint256 internal constant FUNCTION_SIGNATURE_BS = 4; uint256 internal constant REVERT_MSG_OFFSET = 68; // Revert message structure described here: https://ethereum.stackexchange.com/a/66173/106364 uint256 internal constant STRING_ERR_MESSAGE_MASK = 0x08c379a000000000000000000000000000000000000000000000000000000000; // RedStone protocol consts uint256 internal constant SIG_BS = 65; uint256 internal constant TIMESTAMP_BS = 6; uint256 internal constant DATA_PACKAGES_COUNT_BS = 2; uint256 internal constant DATA_POINTS_COUNT_BS = 3; uint256 internal constant DATA_POINT_VALUE_BYTE_SIZE_BS = 4; uint256 internal constant DATA_POINT_SYMBOL_BS = 32; uint256 internal constant DEFAULT_DATA_POINT_VALUE_BS = 32; uint256 internal constant UNSIGNED_METADATA_BYTE_SIZE_BS = 3; uint256 internal constant REDSTONE_MARKER_BS = 9; // byte size of 0x000002ed57011e0000 uint256 internal constant REDSTONE_MARKER_MASK = 0x0000000000000000000000000000000000000000000000000002ed57011e0000; // Derived values (based on consts) uint256 internal constant TIMESTAMP_NEGATIVE_OFFSET_IN_DATA_PACKAGE_WITH_STANDARD_SLOT_BS = 104; // SIG_BS + DATA_POINTS_COUNT_BS + DATA_POINT_VALUE_BYTE_SIZE_BS + STANDARD_SLOT_BS uint256 internal constant DATA_PACKAGE_WITHOUT_DATA_POINTS_BS = 78; // DATA_POINT_VALUE_BYTE_SIZE_BS + TIMESTAMP_BS + DATA_POINTS_COUNT_BS + SIG_BS uint256 internal constant DATA_PACKAGE_WITHOUT_DATA_POINTS_AND_SIG_BS = 13; // DATA_POINT_VALUE_BYTE_SIZE_BS + TIMESTAMP_BS + DATA_POINTS_COUNT_BS uint256 internal constant REDSTONE_MARKER_BS_PLUS_STANDARD_SLOT_BS = 41; // REDSTONE_MARKER_BS + STANDARD_SLOT_BS // Error messages error CalldataOverOrUnderFlow(); error IncorrectUnsignedMetadataSize(); error InsufficientNumberOfUniqueSigners(uint256 receivedSignersCount, uint256 requiredSignersCount); error EachSignerMustProvideTheSameValue(); error EmptyCalldataPointersArr(); error InvalidCalldataPointer(); error CalldataMustHaveValidPayload(); error SignerNotAuthorised(address receivedSigner); } // File: @openzeppelin/contracts/utils/math/SafeMath.sol // OpenZeppelin Contracts (last updated v4.6.0) (utils/math/SafeMath.sol) pragma solidity ^0.8.0; // CAUTION // This version of SafeMath should only be used with Solidity 0.8 or later, // because it relies on the compiler's built in overflow checks. /** * @dev Wrappers over Solidity's arithmetic operations. * * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler * now has built in overflow checking. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // 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 (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @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) { return a + b; } /** * @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 a - b; } /** * @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) { return a * b; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting 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 a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b <= a, errorMessage); return a - b; } } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a / b; } } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a % b; } } } // File: https://github.com/redstone-finance/redstone-oracles-monorepo/blob/4470072aab0e5a64ded46dda53a456f7d91f5d90/packages/evm-connector/contracts/core/CalldataExtractor.sol pragma solidity ^0.8.4; /** * @title The base contract with the main logic of data extraction from calldata * @author The Redstone Oracles team * @dev This contract was created to reuse the same logic in the RedstoneConsumerBase * and the ProxyConnector contracts */ contract CalldataExtractor is RedstoneConstants { using SafeMath for uint256; function _extractByteSizeOfUnsignedMetadata() internal pure returns (uint256) { // Checking if the calldata ends with the RedStone marker bool hasValidRedstoneMarker; assembly { let calldataLast32Bytes := calldataload(sub(calldatasize(), STANDARD_SLOT_BS)) hasValidRedstoneMarker := eq( REDSTONE_MARKER_MASK, and(calldataLast32Bytes, REDSTONE_MARKER_MASK) ) } if (!hasValidRedstoneMarker) { revert CalldataMustHaveValidPayload(); } // Using uint24, because unsigned metadata byte size number has 3 bytes uint24 unsignedMetadataByteSize; if (REDSTONE_MARKER_BS_PLUS_STANDARD_SLOT_BS > msg.data.length) { revert CalldataOverOrUnderFlow(); } assembly { unsignedMetadataByteSize := calldataload( sub(calldatasize(), REDSTONE_MARKER_BS_PLUS_STANDARD_SLOT_BS) ) } uint256 calldataNegativeOffset = unsignedMetadataByteSize + UNSIGNED_METADATA_BYTE_SIZE_BS + REDSTONE_MARKER_BS; if (calldataNegativeOffset + DATA_PACKAGES_COUNT_BS > msg.data.length) { revert IncorrectUnsignedMetadataSize(); } return calldataNegativeOffset; } // We return uint16, because unsigned metadata byte size number has 2 bytes function _extractDataPackagesCountFromCalldata(uint256 calldataNegativeOffset) internal pure returns (uint16 dataPackagesCount) { uint256 calldataNegativeOffsetWithStandardSlot = calldataNegativeOffset + STANDARD_SLOT_BS; if (calldataNegativeOffsetWithStandardSlot > msg.data.length) { revert CalldataOverOrUnderFlow(); } assembly { dataPackagesCount := calldataload( sub(calldatasize(), calldataNegativeOffsetWithStandardSlot) ) } return dataPackagesCount; } function _extractDataPointValueAndDataFeedId( uint256 calldataNegativeOffsetForDataPackage, uint256 defaultDataPointValueByteSize, uint256 dataPointIndex ) internal pure virtual returns (bytes32 dataPointDataFeedId, uint256 dataPointValue) { uint256 negativeOffsetToDataPoints = calldataNegativeOffsetForDataPackage + DATA_PACKAGE_WITHOUT_DATA_POINTS_BS; uint256 dataPointNegativeOffset = negativeOffsetToDataPoints.add( (1 + dataPointIndex).mul((defaultDataPointValueByteSize + DATA_POINT_SYMBOL_BS)) ); uint256 dataPointCalldataOffset = msg.data.length.sub(dataPointNegativeOffset); assembly { dataPointDataFeedId := calldataload(dataPointCalldataOffset) dataPointValue := calldataload(add(dataPointCalldataOffset, DATA_POINT_SYMBOL_BS)) } } function _extractDataPointsDetailsForDataPackage(uint256 calldataNegativeOffsetForDataPackage) internal pure returns (uint256 dataPointsCount, uint256 eachDataPointValueByteSize) { // Using uint24, because data points count byte size number has 3 bytes uint24 dataPointsCount_; // Using uint32, because data point value byte size has 4 bytes uint32 eachDataPointValueByteSize_; // Extract data points count uint256 negativeCalldataOffset = calldataNegativeOffsetForDataPackage + SIG_BS; uint256 calldataOffset = msg.data.length.sub(negativeCalldataOffset + STANDARD_SLOT_BS); assembly { dataPointsCount_ := calldataload(calldataOffset) } // Extract each data point value size calldataOffset = calldataOffset.sub(DATA_POINTS_COUNT_BS); assembly { eachDataPointValueByteSize_ := calldataload(calldataOffset) } // Prepare returned values dataPointsCount = dataPointsCount_; eachDataPointValueByteSize = eachDataPointValueByteSize_; } } // File: https://github.com/redstone-finance/redstone-oracles-monorepo/blob/4470072aab0e5a64ded46dda53a456f7d91f5d90/packages/evm-connector/contracts/libs/NumericArrayLib.sol pragma solidity ^0.8.4; library NumericArrayLib { // This function sort array in memory using bubble sort algorithm, // which performs even better than quick sort for small arrays uint256 constant BYTES_ARR_LEN_VAR_BS = 32; uint256 constant UINT256_VALUE_BS = 32; error CanNotPickMedianOfEmptyArray(); // This function modifies the array function pickMedian(uint256[] memory arr) internal pure returns (uint256) { if (arr.length == 0) { revert CanNotPickMedianOfEmptyArray(); } sort(arr); uint256 middleIndex = arr.length / 2; if (arr.length % 2 == 0) { uint256 sum = SafeMath.add(arr[middleIndex - 1], arr[middleIndex]); return sum / 2; } else { return arr[middleIndex]; } } function sort(uint256[] memory arr) internal pure { assembly { let arrLength := mload(arr) let valuesPtr := add(arr, BYTES_ARR_LEN_VAR_BS) let endPtr := add(valuesPtr, mul(arrLength, UINT256_VALUE_BS)) for { let arrIPtr := valuesPtr } lt(arrIPtr, endPtr) { arrIPtr := add(arrIPtr, UINT256_VALUE_BS) // arrIPtr += 32 } { for { let arrJPtr := valuesPtr } lt(arrJPtr, arrIPtr) { arrJPtr := add(arrJPtr, UINT256_VALUE_BS) // arrJPtr += 32 } { let arrI := mload(arrIPtr) let arrJ := mload(arrJPtr) if lt(arrI, arrJ) { mstore(arrIPtr, arrJ) mstore(arrJPtr, arrI) } } } } } } // File: https://github.com/redstone-finance/redstone-oracles-monorepo/blob/4470072aab0e5a64ded46dda53a456f7d91f5d90/packages/evm-connector/contracts/core/RedstoneDefaultsLib.sol pragma solidity ^0.8.4; /** * @title Default implementations of virtual redstone consumer base functions * @author The Redstone Oracles team */ library RedstoneDefaultsLib { uint256 constant DEFAULT_MAX_DATA_TIMESTAMP_DELAY_SECONDS = 3 minutes; uint256 constant DEFAULT_MAX_DATA_TIMESTAMP_AHEAD_SECONDS = 1 minutes; error TimestampFromTooLongFuture(uint256 receivedTimestampSeconds, uint256 blockTimestamp); error TimestampIsTooOld(uint256 receivedTimestampSeconds, uint256 blockTimestamp); function validateTimestamp(uint256 receivedTimestampMilliseconds) internal view { // Getting data timestamp from future seems quite unlikely // But we've already spent too much time with different cases // Where block.timestamp was less than dataPackage.timestamp. // Some blockchains may case this problem as well. // That's why we add MAX_BLOCK_TIMESTAMP_DELAY // and allow data "from future" but with a small delay uint256 receivedTimestampSeconds = receivedTimestampMilliseconds / 1000; if (block.timestamp < receivedTimestampSeconds) { if ((receivedTimestampSeconds - block.timestamp) > DEFAULT_MAX_DATA_TIMESTAMP_AHEAD_SECONDS) { revert TimestampFromTooLongFuture(receivedTimestampSeconds, block.timestamp); } } else if ((block.timestamp - receivedTimestampSeconds) > DEFAULT_MAX_DATA_TIMESTAMP_DELAY_SECONDS) { revert TimestampIsTooOld(receivedTimestampSeconds, block.timestamp); } } function aggregateValues(uint256[] memory values) internal pure returns (uint256) { return NumericArrayLib.pickMedian(values); } } // File: github/redstone-finance/redstone-oracles-monorepo/packages/evm-connector/contracts/core/RedstoneConsumerBase.sol pragma solidity ^0.8.4; /** * @title The base contract with the main Redstone logic * @author The Redstone Oracles team * @dev Do not use this contract directly in consumer contracts, take a * look at `RedstoneConsumerNumericBase` and `RedstoneConsumerBytesBase` instead */ abstract contract RedstoneConsumerBase is CalldataExtractor { using SafeMath for uint256; /* ========== VIRTUAL FUNCTIONS (MAY BE OVERRIDDEN IN CHILD CONTRACTS) ========== */ /** * @dev This function must be implemented by the child consumer contract. * It should return a unique index for a given signer address if the signer * is authorised, otherwise it should revert * @param receivedSigner The address of a signer, recovered from ECDSA signature * @return Unique index for a signer in the range [0..255] */ function getAuthorisedSignerIndex(address receivedSigner) public view virtual returns (uint8); /** * @dev This function may be overridden by the child consumer contract. * It should validate the timestamp against the current time (block.timestamp) * It should revert with a helpful message if the timestamp is not valid * @param receivedTimestampMilliseconds Timestamp extracted from calldata */ function validateTimestamp(uint256 receivedTimestampMilliseconds) public view virtual { RedstoneDefaultsLib.validateTimestamp(receivedTimestampMilliseconds); } /** * @dev This function should be overridden by the child consumer contract. * @return The minimum required value of unique authorised signers */ function getUniqueSignersThreshold() public view virtual returns (uint8) { return 1; } /** * @dev This function may be overridden by the child consumer contract. * It should aggregate values from different signers to a single uint value. * By default, it calculates the median value * @param values An array of uint256 values from different signers * @return Result of the aggregation in the form of a single number */ function aggregateValues(uint256[] memory values) public view virtual returns (uint256) { return RedstoneDefaultsLib.aggregateValues(values); } /* ========== FUNCTIONS WITH IMPLEMENTATION (CAN NOT BE OVERRIDDEN) ========== */ /** * @dev This is an internal helpful function for secure extraction oracle values * from the tx calldata. Security is achieved by signatures verification, timestamp * validation, and aggregating values from different authorised signers into a * single numeric value. If any of the required conditions (e.g. too old timestamp or * insufficient number of authorised signers) do not match, the function will revert. * * Note! You should not call this function in a consumer contract. You can use * `getOracleNumericValuesFromTxMsg` or `getOracleNumericValueFromTxMsg` instead. * * @param dataFeedIds An array of unique data feed identifiers * @return An array of the extracted and verified oracle values in the same order * as they are requested in dataFeedIds array */ function _securelyExtractOracleValuesFromTxMsg(bytes32[] memory dataFeedIds) internal view returns (uint256[] memory) { // Initializing helpful variables and allocating memory uint256[] memory uniqueSignerCountForDataFeedIds = new uint256[](dataFeedIds.length); uint256[] memory signersBitmapForDataFeedIds = new uint256[](dataFeedIds.length); uint256[][] memory valuesForDataFeeds = new uint256[][](dataFeedIds.length); for (uint256 i = 0; i < dataFeedIds.length; i++) { // The line below is commented because newly allocated arrays are filled with zeros // But we left it for better readability // signersBitmapForDataFeedIds[i] = 0; // <- setting to an empty bitmap valuesForDataFeeds[i] = new uint256[](getUniqueSignersThreshold()); } // Extracting the number of data packages from calldata uint256 calldataNegativeOffset = _extractByteSizeOfUnsignedMetadata(); uint256 dataPackagesCount = _extractDataPackagesCountFromCalldata(calldataNegativeOffset); calldataNegativeOffset += DATA_PACKAGES_COUNT_BS; // Saving current free memory pointer uint256 freeMemPtr; assembly { freeMemPtr := mload(FREE_MEMORY_PTR) } // Data packages extraction in a loop for (uint256 dataPackageIndex = 0; dataPackageIndex < dataPackagesCount; dataPackageIndex++) { // Extract data package details and update calldata offset uint256 dataPackageByteSize = _extractDataPackage( dataFeedIds, uniqueSignerCountForDataFeedIds, signersBitmapForDataFeedIds, valuesForDataFeeds, calldataNegativeOffset ); calldataNegativeOffset += dataPackageByteSize; // Shifting memory pointer back to the "safe" value assembly { mstore(FREE_MEMORY_PTR, freeMemPtr) } } // Validating numbers of unique signers and calculating aggregated values for each dataFeedId return _getAggregatedValues(valuesForDataFeeds, uniqueSignerCountForDataFeedIds); } /** * @dev This is a private helpful function, which extracts data for a data package based * on the given negative calldata offset, verifies them, and in the case of successful * verification updates the corresponding data package values in memory * * @param dataFeedIds an array of unique data feed identifiers * @param uniqueSignerCountForDataFeedIds an array with the numbers of unique signers * for each data feed * @param signersBitmapForDataFeedIds an array of signer bitmaps for data feeds * @param valuesForDataFeeds 2-dimensional array, valuesForDataFeeds[i][j] contains * j-th value for the i-th data feed * @param calldataNegativeOffset negative calldata offset for the given data package * * @return An array of the aggregated values */ function _extractDataPackage( bytes32[] memory dataFeedIds, uint256[] memory uniqueSignerCountForDataFeedIds, uint256[] memory signersBitmapForDataFeedIds, uint256[][] memory valuesForDataFeeds, uint256 calldataNegativeOffset ) private view returns (uint256) { uint256 signerIndex; ( uint256 dataPointsCount, uint256 eachDataPointValueByteSize ) = _extractDataPointsDetailsForDataPackage(calldataNegativeOffset); // We use scopes to resolve problem with too deep stack { uint48 extractedTimestamp; address signerAddress; bytes32 signedHash; bytes memory signedMessage; uint256 signedMessageBytesCount; signedMessageBytesCount = dataPointsCount.mul(eachDataPointValueByteSize + DATA_POINT_SYMBOL_BS) + DATA_PACKAGE_WITHOUT_DATA_POINTS_AND_SIG_BS; //DATA_POINT_VALUE_BYTE_SIZE_BS + TIMESTAMP_BS + DATA_POINTS_COUNT_BS uint256 timestampCalldataOffset = msg.data.length.sub( calldataNegativeOffset + TIMESTAMP_NEGATIVE_OFFSET_IN_DATA_PACKAGE_WITH_STANDARD_SLOT_BS); uint256 signedMessageCalldataOffset = msg.data.length.sub( calldataNegativeOffset + SIG_BS + signedMessageBytesCount); assembly { // Extracting the signed message signedMessage := extractBytesFromCalldata( signedMessageCalldataOffset, signedMessageBytesCount ) // Hashing the signed message signedHash := keccak256(add(signedMessage, BYTES_ARR_LEN_VAR_BS), signedMessageBytesCount) // Extracting timestamp extractedTimestamp := calldataload(timestampCalldataOffset) function initByteArray(bytesCount) -> ptr { ptr := mload(FREE_MEMORY_PTR) mstore(ptr, bytesCount) ptr := add(ptr, BYTES_ARR_LEN_VAR_BS) mstore(FREE_MEMORY_PTR, add(ptr, bytesCount)) } function extractBytesFromCalldata(offset, bytesCount) -> extractedBytes { let extractedBytesStartPtr := initByteArray(bytesCount) calldatacopy( extractedBytesStartPtr, offset, bytesCount ) extractedBytes := sub(extractedBytesStartPtr, BYTES_ARR_LEN_VAR_BS) } } // Validating timestamp validateTimestamp(extractedTimestamp); // Verifying the off-chain signature against on-chain hashed data signerAddress = SignatureLib.recoverSignerAddress( signedHash, calldataNegativeOffset + SIG_BS ); signerIndex = getAuthorisedSignerIndex(signerAddress); } // Updating helpful arrays { bytes32 dataPointDataFeedId; uint256 dataPointValue; for (uint256 dataPointIndex = 0; dataPointIndex < dataPointsCount; dataPointIndex++) { // Extracting data feed id and value for the current data point (dataPointDataFeedId, dataPointValue) = _extractDataPointValueAndDataFeedId( calldataNegativeOffset, eachDataPointValueByteSize, dataPointIndex ); for ( uint256 dataFeedIdIndex = 0; dataFeedIdIndex < dataFeedIds.length; dataFeedIdIndex++ ) { if (dataPointDataFeedId == dataFeedIds[dataFeedIdIndex]) { uint256 bitmapSignersForDataFeedId = signersBitmapForDataFeedIds[dataFeedIdIndex]; if ( !BitmapLib.getBitFromBitmap(bitmapSignersForDataFeedId, signerIndex) && /* current signer was not counted for current dataFeedId */ uniqueSignerCountForDataFeedIds[dataFeedIdIndex] < getUniqueSignersThreshold() ) { // Increase unique signer counter uniqueSignerCountForDataFeedIds[dataFeedIdIndex]++; // Add new value valuesForDataFeeds[dataFeedIdIndex][ uniqueSignerCountForDataFeedIds[dataFeedIdIndex] - 1 ] = dataPointValue; // Update signers bitmap signersBitmapForDataFeedIds[dataFeedIdIndex] = BitmapLib.setBitInBitmap( bitmapSignersForDataFeedId, signerIndex ); } // Breaking, as there couldn't be several indexes for the same feed ID break; } } } } // Return total data package byte size return DATA_PACKAGE_WITHOUT_DATA_POINTS_BS + (eachDataPointValueByteSize + DATA_POINT_SYMBOL_BS) * dataPointsCount; } /** * @dev This is a private helpful function, which aggregates values from different * authorised signers for the given arrays of values for each data feed * * @param valuesForDataFeeds 2-dimensional array, valuesForDataFeeds[i][j] contains * j-th value for the i-th data feed * @param uniqueSignerCountForDataFeedIds an array with the numbers of unique signers * for each data feed * * @return An array of the aggregated values */ function _getAggregatedValues( uint256[][] memory valuesForDataFeeds, uint256[] memory uniqueSignerCountForDataFeedIds ) private view returns (uint256[] memory) { uint256[] memory aggregatedValues = new uint256[](valuesForDataFeeds.length); uint256 uniqueSignersThreshold = getUniqueSignersThreshold(); for (uint256 dataFeedIndex = 0; dataFeedIndex < valuesForDataFeeds.length; dataFeedIndex++) { if (uniqueSignerCountForDataFeedIds[dataFeedIndex] < uniqueSignersThreshold) { revert InsufficientNumberOfUniqueSigners( uniqueSignerCountForDataFeedIds[dataFeedIndex], uniqueSignersThreshold); } uint256 aggregatedValueForDataFeedId = aggregateValues(valuesForDataFeeds[dataFeedIndex]); aggregatedValues[dataFeedIndex] = aggregatedValueForDataFeedId; } return aggregatedValues; } } // File: github/redstone-finance/redstone-oracles-monorepo/packages/evm-connector/contracts/core/RedstoneConsumerNumericBase.sol pragma solidity ^0.8.4; /** * @title The base contract for Redstone consumers' contracts that allows to * securely calculate numeric redstone oracle values * @author The Redstone Oracles team * @dev This contract can extend other contracts to allow them * securely fetch Redstone oracle data from transactions calldata */ abstract contract RedstoneConsumerNumericBase is RedstoneConsumerBase { /** * @dev This function can be used in a consumer contract to securely extract an * oracle value for a given data feed id. Security is achieved by * signatures verification, timestamp validation, and aggregating values * from different authorised signers into a single numeric value. If any of the * required conditions do not match, the function will revert. * Note! This function expects that tx calldata contains redstone payload in the end * Learn more about redstone payload here: https://github.com/redstone-finance/redstone-oracles-monorepo/tree/main/packages/evm-connector#readme * @param dataFeedId bytes32 value that uniquely identifies the data feed * @return Extracted and verified numeric oracle value for the given data feed id */ function getOracleNumericValueFromTxMsg(bytes32 dataFeedId) public view virtual returns (uint256) { bytes32[] memory dataFeedIds = new bytes32[](1); dataFeedIds[0] = dataFeedId; return getOracleNumericValuesFromTxMsg(dataFeedIds)[0]; } /** * @dev This function can be used in a consumer contract to securely extract several * numeric oracle values for a given array of data feed ids. Security is achieved by * signatures verification, timestamp validation, and aggregating values * from different authorised signers into a single numeric value. If any of the * required conditions do not match, the function will revert. * Note! This function expects that tx calldata contains redstone payload in the end * Learn more about redstone payload here: https://github.com/redstone-finance/redstone-oracles-monorepo/tree/main/packages/evm-connector#readme * @param dataFeedIds An array of unique data feed identifiers * @return An array of the extracted and verified oracle values in the same order * as they are requested in the dataFeedIds array */ function getOracleNumericValuesFromTxMsg(bytes32[] memory dataFeedIds) public view virtual returns (uint256[] memory) { return _securelyExtractOracleValuesFromTxMsg(dataFeedIds); } /** * @dev This function works similarly to the `getOracleNumericValuesFromTxMsg` with the * only difference that it allows to request oracle data for an array of data feeds * that may contain duplicates * * @param dataFeedIdsWithDuplicates An array of data feed identifiers (duplicates are allowed) * @return An array of the extracted and verified oracle values in the same order * as they are requested in the dataFeedIdsWithDuplicates array */ function getOracleNumericValuesWithDuplicatesFromTxMsg(bytes32[] memory dataFeedIdsWithDuplicates) public view returns (uint256[] memory) { // Building an array without duplicates bytes32[] memory dataFeedIdsWithoutDuplicates = new bytes32[](dataFeedIdsWithDuplicates.length); bool alreadyIncluded; uint256 uniqueDataFeedIdsCount = 0; for (uint256 indexWithDup = 0; indexWithDup < dataFeedIdsWithDuplicates.length; indexWithDup++) { // Checking if current element is already included in `dataFeedIdsWithoutDuplicates` alreadyIncluded = false; for (uint256 indexWithoutDup = 0; indexWithoutDup < uniqueDataFeedIdsCount; indexWithoutDup++) { if (dataFeedIdsWithoutDuplicates[indexWithoutDup] == dataFeedIdsWithDuplicates[indexWithDup]) { alreadyIncluded = true; break; } } // Adding if not included if (!alreadyIncluded) { dataFeedIdsWithoutDuplicates[uniqueDataFeedIdsCount] = dataFeedIdsWithDuplicates[indexWithDup]; uniqueDataFeedIdsCount++; } } // Overriding dataFeedIdsWithoutDuplicates.length // Equivalent to: dataFeedIdsWithoutDuplicates.length = uniqueDataFeedIdsCount; assembly { mstore(dataFeedIdsWithoutDuplicates, uniqueDataFeedIdsCount) } // Requesting oracle values (without duplicates) uint256[] memory valuesWithoutDuplicates = getOracleNumericValuesFromTxMsg(dataFeedIdsWithoutDuplicates); // Preparing result values array uint256[] memory valuesWithDuplicates = new uint256[](dataFeedIdsWithDuplicates.length); for (uint256 indexWithDup = 0; indexWithDup < dataFeedIdsWithDuplicates.length; indexWithDup++) { for (uint256 indexWithoutDup = 0; indexWithoutDup < dataFeedIdsWithoutDuplicates.length; indexWithoutDup++) { if (dataFeedIdsWithDuplicates[indexWithDup] == dataFeedIdsWithoutDuplicates[indexWithoutDup]) { valuesWithDuplicates[indexWithDup] = valuesWithoutDuplicates[indexWithoutDup]; break; } } } return valuesWithDuplicates; } } // File: github/redstone-finance/redstone-oracles-monorepo/packages/evm-connector/contracts/data-services/CustomUrlsConsumerBase.sol pragma solidity ^0.8.4; contract CustomUrlsConsumerBase is RedstoneConsumerNumericBase { function getUniqueSignersThreshold() public view virtual override returns (uint8) { return 2; } function getAuthorisedSignerIndex(address signerAddress) public view virtual override returns (uint8) { if (signerAddress == 0x11fFFc9970c41B9bFB9Aa35Be838d39bce918CfF) { return 0; } else if (signerAddress == 0xdBcC2C6c892C8d3e3Fe4D325fEc810B7376A5Ed6) { return 1; } else { revert SignerNotAuthorised(signerAddress); } } }
[{"inputs":[],"name":"CalldataMustHaveValidPayload","type":"error"},{"inputs":[],"name":"CalldataOverOrUnderFlow","type":"error"},{"inputs":[],"name":"CanNotPickMedianOfEmptyArray","type":"error"},{"inputs":[],"name":"EachSignerMustProvideTheSameValue","type":"error"},{"inputs":[],"name":"EmptyCalldataPointersArr","type":"error"},{"inputs":[],"name":"IncorrectUnsignedMetadataSize","type":"error"},{"inputs":[{"internalType":"uint256","name":"receivedSignersCount","type":"uint256"},{"internalType":"uint256","name":"requiredSignersCount","type":"uint256"}],"name":"InsufficientNumberOfUniqueSigners","type":"error"},{"inputs":[],"name":"InvalidCalldataPointer","type":"error"},{"inputs":[{"internalType":"address","name":"receivedSigner","type":"address"}],"name":"SignerNotAuthorised","type":"error"},{"inputs":[{"internalType":"uint256","name":"receivedTimestampSeconds","type":"uint256"},{"internalType":"uint256","name":"blockTimestamp","type":"uint256"}],"name":"TimestampFromTooLongFuture","type":"error"},{"inputs":[{"internalType":"uint256","name":"receivedTimestampSeconds","type":"uint256"},{"internalType":"uint256","name":"blockTimestamp","type":"uint256"}],"name":"TimestampIsTooOld","type":"error"},{"inputs":[{"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"aggregateValues","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"signerAddress","type":"address"}],"name":"getAuthorisedSignerIndex","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"dataFeedId","type":"bytes32"}],"name":"getOracleNumericValueFromTxMsg","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"dataFeedIds","type":"bytes32[]"}],"name":"getOracleNumericValuesFromTxMsg","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"dataFeedIdsWithDuplicates","type":"bytes32[]"}],"name":"getOracleNumericValuesWithDuplicatesFromTxMsg","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getUniqueSignersThreshold","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"receivedTimestampMilliseconds","type":"uint256"}],"name":"validateTimestamp","outputs":[],"stateMutability":"view","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b50611993806100206000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c8063a06a3b021161005b578063a06a3b0214610112578063b24ebfcc14610142578063f50b2efe14610172578063f90c49241461018e5761007d565b80633ce142f514610082578063600acb52146100b257806370ecc458146100e2575b600080fd5b61009c600480360381019061009791906111f3565b6101ac565b6040516100a9919061123c565b60405180910390f35b6100cc60048036038101906100c7919061128d565b610290565b6040516100d991906112d3565b60405180910390f35b6100fc60048036038101906100f79190611447565b61032c565b604051610109919061154e565b60405180910390f35b61012c60048036038101906101279190611447565b61033e565b604051610139919061154e565b60405180910390f35b61015c6004803603810190610157919061165f565b61058f565b60405161016991906112d3565b60405180910390f35b61018c600480360381019061018791906116a8565b6105a1565b005b6101966105ad565b6040516101a3919061123c565b60405180910390f35b60007311fffc9970c41b9bfb9aa35be838d39bce918cff73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036101fe576000905061028b565b73dbcc2c6c892c8d3e3fe4d325fec810b7376a5ed673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361024e576001905061028b565b816040517fec459bc000000000000000000000000000000000000000000000000000000000815260040161028291906116e4565b60405180910390fd5b919050565b600080600167ffffffffffffffff8111156102ae576102ad611304565b5b6040519080825280602002602001820160405280156102dc5781602001602082028036833780820191505090505b50905082816000815181106102f4576102f36116ff565b5b6020026020010181815250506103098161032c565b60008151811061031c5761031b6116ff565b5b6020026020010151915050919050565b6060610337826105b6565b9050919050565b60606000825167ffffffffffffffff81111561035d5761035c611304565b5b60405190808252806020026020018201604052801561038b5781602001602082028036833780820191505090505b5090506000806000905060005b8551811015610469576000925060005b82811015610407578682815181106103c3576103c26116ff565b5b60200260200101518582815181106103de576103dd6116ff565b5b6020026020010151036103f45760019350610407565b80806103ff9061175d565b9150506103a8565b5082610456578581815181106104205761041f6116ff565b5b602002602001015184838151811061043b5761043a6116ff565b5b60200260200101818152505081806104529061175d565b9250505b80806104619061175d565b915050610398565b5080835260006104788461032c565b90506000865167ffffffffffffffff81111561049757610496611304565b5b6040519080825280602002602001820160405280156104c55781602001602082028036833780820191505090505b50905060005b87518110156105815760005b865181101561056d578681815181106104f3576104f26116ff565b5b602002602001015189838151811061050e5761050d6116ff565b5b60200260200101510361055a5783818151811061052e5761052d6116ff565b5b6020026020010151838381518110610549576105486116ff565b5b60200260200101818152505061056d565b80806105659061175d565b9150506104d7565b5080806105799061175d565b9150506104cb565b508095505050505050919050565b600061059a826107c5565b9050919050565b6105aa816107d7565b50565b60006002905090565b60606000825167ffffffffffffffff8111156105d5576105d4611304565b5b6040519080825280602002602001820160405280156106035781602001602082028036833780820191505090505b5090506000835167ffffffffffffffff81111561062357610622611304565b5b6040519080825280602002602001820160405280156106515781602001602082028036833780820191505090505b5090506000845167ffffffffffffffff81111561067157610670611304565b5b6040519080825280602002602001820160405280156106a457816020015b606081526020019060019003908161068f5790505b50905060005b8551811015610737576106bb6105ad565b60ff1667ffffffffffffffff8111156106d7576106d6611304565b5b6040519080825280602002602001820160405280156107055781602001602082028036833780820191505090505b50828281518110610719576107186116ff565b5b6020026020010181905250808061072f9061175d565b9150506106aa565b5060006107426108a1565b9050600061074f826109b2565b61ffff16905060028261076291906117a5565b91506000604051905060005b828110156107ad5760006107858a89898989610a0e565b9050808561079391906117a5565b9450826040525080806107a59061175d565b91505061076e565b506107b88487610d06565b9650505050505050919050565b60006107d082610e53565b9050919050565b60006103e8826107e79190611808565b90508042101561084957603c42826107ff9190611839565b11156108445780426040517fb6b0916d00000000000000000000000000000000000000000000000000000000815260040161083b92919061186d565b60405180910390fd5b61089d565b60b481426108579190611839565b111561089c5780426040517f0321d0b500000000000000000000000000000000000000000000000000000000815260040161089392919061186d565b60405180910390fd5b5b5050565b60008060203603356602ed57011e000081166602ed57011e000014915050806108f6576040517fe7764c9e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008036905060291115610936576040517f5796f78a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602936033590506000600960038362ffffff1661095391906117a5565b61095d91906117a5565b9050600036905060028261097191906117a5565b11156109a9576040517fc30a7bd700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80935050505090565b6000806020836109c291906117a5565b90506000369050811115610a02576040517f5796f78a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80360335915050919050565b600080600080610a1d85610f47565b91509150600080600060606000600d610a4b602088610a3c91906117a5565b89610fbd90919063ffffffff16565b610a5591906117a5565b90506000610a7c60688c610a6991906117a5565b6000369050610fd390919063ffffffff16565b90506000610aae8360418e610a9191906117a5565b610a9b91906117a5565b6000369050610fd390919063ffffffff16565b9050610aba8382610ae8565b9350826020850120945081359650610b04565b60006040519050818152602081019050818101604052919050565b6000610af383610acd565b838382376020810391505092915050565b610b158765ffffffffffff166105a1565b610b2b8560418e610b2691906117a5565b610fe9565b9550610b36866101ac565b60ff1699505050505050505060008060005b84811015610cd157610b5b888583611068565b809350819450505060005b8c51811015610cbd578c8181518110610b8257610b816116ff565b5b60200260200101518403610caa5760008b8281518110610ba557610ba46116ff565b5b60200260200101519050610bb981896110ee565b158015610be95750610bc96105ad565b60ff168d8381518110610bdf57610bde6116ff565b5b6020026020010151105b15610ca4578c8281518110610c0157610c006116ff565b5b602002602001018051809190610c169061175d565b81525050838b8381518110610c2e57610c2d6116ff565b5b602002602001015160018f8581518110610c4b57610c4a6116ff565b5b6020026020010151610c5d9190611839565b81518110610c6e57610c6d6116ff565b5b602002602001018181525050610c848189611107565b8c8381518110610c9757610c966116ff565b5b6020026020010181815250505b50610cbd565b8080610cb59061175d565b915050610b66565b508080610cc99061175d565b915050610b48565b50505081602082610ce291906117a5565b610cec9190611896565b604e610cf891906117a5565b935050505095945050505050565b60606000835167ffffffffffffffff811115610d2557610d24611304565b5b604051908082528060200260200182016040528015610d535781602001602082028036833780820191505090505b5090506000610d606105ad565b60ff16905060005b8551811015610e475781858281518110610d8557610d846116ff565b5b60200260200101511015610dec57848181518110610da657610da56116ff565b5b6020026020010151826040517f2b13aef5000000000000000000000000000000000000000000000000000000008152600401610de392919061186d565b60405180910390fd5b6000610e11878381518110610e0457610e036116ff565b5b602002602001015161058f565b905080848381518110610e2757610e266116ff565b5b602002602001018181525050508080610e3f9061175d565b915050610d68565b50819250505092915050565b600080825103610e8f576040517f9e198af900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e9882611118565b600060028351610ea89190611808565b9050600060028451610eba91906118d8565b03610f23576000610f0b84600184610ed29190611839565b81518110610ee357610ee26116ff565b5b6020026020010151858481518110610efe57610efd6116ff565b5b602002602001015161116b565b9050600281610f1a9190611808565b92505050610f42565b828181518110610f3657610f356116ff565b5b60200260200101519150505b919050565b6000806000806000604186610f5c91906117a5565b90506000610f83602083610f7091906117a5565b6000369050610fd390919063ffffffff16565b905080359350610f9d600382610fd390919063ffffffff16565b9050803592508362ffffff1695508263ffffffff16945050505050915091565b60008183610fcb9190611896565b905092915050565b60008183610fe19190611839565b905092915050565b6000806000808436038035935060208101905080359250602081019050803560001a915050600186828585604051600081526020016040526040516110319493929190611918565b6020604051602081039080840390855afa158015611053573d6000803e3d6000fd5b50505060206040510351935050505092915050565b6000806000604e8661107a91906117a5565b905060006110bb6110ac60208861109191906117a5565b87600161109e91906117a5565b610fbd90919063ffffffff16565b8361116b90919063ffffffff16565b905060006110d6826000369050610fd390919063ffffffff16565b90508035945060208101359350505050935093915050565b600080826001901b841690506000811191505092915050565b6000816001901b8317905092915050565b805160208201602082028101815b8181101561116457825b8181101561115857815181518082101561114b578084528183525b5050602081019050611130565b50602081019050611126565b5050505050565b6000818361117991906117a5565b905092915050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006111c082611195565b9050919050565b6111d0816111b5565b81146111db57600080fd5b50565b6000813590506111ed816111c7565b92915050565b6000602082840312156112095761120861118b565b5b6000611217848285016111de565b91505092915050565b600060ff82169050919050565b61123681611220565b82525050565b6000602082019050611251600083018461122d565b92915050565b6000819050919050565b61126a81611257565b811461127557600080fd5b50565b60008135905061128781611261565b92915050565b6000602082840312156112a3576112a261118b565b5b60006112b184828501611278565b91505092915050565b6000819050919050565b6112cd816112ba565b82525050565b60006020820190506112e860008301846112c4565b92915050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61133c826112f3565b810181811067ffffffffffffffff8211171561135b5761135a611304565b5b80604052505050565b600061136e611181565b905061137a8282611333565b919050565b600067ffffffffffffffff82111561139a57611399611304565b5b602082029050602081019050919050565b600080fd5b60006113c36113be8461137f565b611364565b905080838252602082019050602084028301858111156113e6576113e56113ab565b5b835b8181101561140f57806113fb8882611278565b8452602084019350506020810190506113e8565b5050509392505050565b600082601f83011261142e5761142d6112ee565b5b813561143e8482602086016113b0565b91505092915050565b60006020828403121561145d5761145c61118b565b5b600082013567ffffffffffffffff81111561147b5761147a611190565b5b61148784828501611419565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6114c5816112ba565b82525050565b60006114d783836114bc565b60208301905092915050565b6000602082019050919050565b60006114fb82611490565b611505818561149b565b9350611510836114ac565b8060005b8381101561154157815161152888826114cb565b9750611533836114e3565b925050600181019050611514565b5085935050505092915050565b6000602082019050818103600083015261156881846114f0565b905092915050565b600067ffffffffffffffff82111561158b5761158a611304565b5b602082029050602081019050919050565b6115a5816112ba565b81146115b057600080fd5b50565b6000813590506115c28161159c565b92915050565b60006115db6115d684611570565b611364565b905080838252602082019050602084028301858111156115fe576115fd6113ab565b5b835b81811015611627578061161388826115b3565b845260208401935050602081019050611600565b5050509392505050565b600082601f830112611646576116456112ee565b5b81356116568482602086016115c8565b91505092915050565b6000602082840312156116755761167461118b565b5b600082013567ffffffffffffffff81111561169357611692611190565b5b61169f84828501611631565b91505092915050565b6000602082840312156116be576116bd61118b565b5b60006116cc848285016115b3565b91505092915050565b6116de816111b5565b82525050565b60006020820190506116f960008301846116d5565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000611768826112ba565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361179a5761179961172e565b5b600182019050919050565b60006117b0826112ba565b91506117bb836112ba565b92508282019050808211156117d3576117d261172e565b5b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000611813826112ba565b915061181e836112ba565b92508261182e5761182d6117d9565b5b828204905092915050565b6000611844826112ba565b915061184f836112ba565b92508282039050818111156118675761186661172e565b5b92915050565b600060408201905061188260008301856112c4565b61188f60208301846112c4565b9392505050565b60006118a1826112ba565b91506118ac836112ba565b92508282026118ba816112ba565b915082820484148315176118d1576118d061172e565b5b5092915050565b60006118e3826112ba565b91506118ee836112ba565b9250826118fe576118fd6117d9565b5b828206905092915050565b61191281611257565b82525050565b600060808201905061192d6000830187611909565b61193a602083018661122d565b6119476040830185611909565b6119546060830184611909565b9594505050505056fea2646970667358221220596992b93bbba805833348e4c54352d8819a37f00bd6d0271128748bb8dc95bd64736f6c63430008110033
Deployed ByteCode Sourcemap
36964:572:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;37141:392;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;32829:276;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;33966:211;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;34666:2122;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;21562:151;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;20768:167;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;37032:103;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;37141:392;37261:5;37299:42;37282:59;;:13;:59;;;37278:250;;37359:1;37352:8;;;;37278:250;37395:42;37378:59;;:13;:59;;;37374:154;;37455:1;37448:8;;;;37374:154;37506:13;37486:34;;;;;;;;;;;:::i;:::-;;;;;;;;37141:392;;;;:::o;32829:276::-;32938:7;32957:28;33002:1;32988:16;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32957:47;;33028:10;33011:11;33023:1;33011:14;;;;;;;;:::i;:::-;;;;;;;:27;;;;;33052:44;33084:11;33052:31;:44::i;:::-;33097:1;33052:47;;;;;;;;:::i;:::-;;;;;;;;33045:54;;;32829:276;;;:::o;33966:211::-;34086:16;34121:50;34159:11;34121:37;:50::i;:::-;34114:57;;33966:211;;;:::o;34666:2122::-;34786:16;34856:45;34918:25;:32;34904:47;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;34856:95;;34958:20;34985:30;35018:1;34985:34;;35033:20;35028:725;35074:25;:32;35059:12;:47;35028:725;;;35243:5;35225:23;;35262;35257:274;35309:22;35291:15;:40;35257:274;;;35416:25;35442:12;35416:39;;;;;;;;:::i;:::-;;;;;;;;35367:28;35396:15;35367:45;;;;;;;;:::i;:::-;;;;;;;;:88;35363:159;;35488:4;35470:22;;35505:5;;35363:159;35333:17;;;;;:::i;:::-;;;;35257:274;;;;35579:15;35574:172;;35662:25;35688:12;35662:39;;;;;;;;:::i;:::-;;;;;;;;35607:28;35636:22;35607:52;;;;;;;;:::i;:::-;;;;;;;:94;;;;;35712:24;;;;;:::i;:::-;;;;35574:172;35108:14;;;;;:::i;:::-;;;;35028:725;;;;35956:22;35926:28;35919:60;36048:40;36091:61;36123:28;36091:31;:61::i;:::-;36048:104;;36199:37;36253:25;:32;36239:47;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;36199:87;;36298:20;36293:454;36339:25;:32;36324:12;:47;36293:454;;;36403:23;36398:342;36450:28;:35;36432:15;:53;36398:342;;;36564:28;36593:15;36564:45;;;;;;;;:::i;:::-;;;;;;;;36521:25;36547:12;36521:39;;;;;;;;:::i;:::-;;;;;;;;:88;36517:214;;36661:23;36685:15;36661:40;;;;;;;;:::i;:::-;;;;;;;;36624:20;36645:12;36624:34;;;;;;;;:::i;:::-;;;;;;;:77;;;;;36714:5;;36517:214;36487:17;;;;;:::i;:::-;;;;36398:342;;;;36373:14;;;;;:::i;:::-;;;;36293:454;;;;36762:20;36755:27;;;;;;;34666:2122;;;:::o;21562:151::-;21641:7;21664:43;21700:6;21664:35;:43::i;:::-;21657:50;;21562:151;;;:::o;20768:167::-;20861:68;20899:29;20861:37;:68::i;:::-;20768:167;:::o;37032:103::-;37107:5;37128:1;37121:8;;37032:103;:::o;22630:2070::-;22745:16;22834:48;22899:11;:18;22885:33;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;22834:84;;22925:44;22986:11;:18;22972:33;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;22925:80;;23012:37;23068:11;:18;23052:35;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23012:75;;23099:9;23094:350;23118:11;:18;23114:1;:22;23094:350;;;23408:27;:25;:27::i;:::-;23394:42;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23370:18;23389:1;23370:21;;;;;;;;:::i;:::-;;;;;;;:66;;;;23138:3;;;;;:::i;:::-;;;;23094:350;;;;23513:30;23546:36;:34;:36::i;:::-;23513:69;;23589:25;23617:61;23655:22;23617:37;:61::i;:::-;23589:89;;;;2898:1;23685:48;;;;;:::i;:::-;;;23785:18;23848:15;23842:22;23828:36;;23927:24;23922:585;23976:17;23957:16;:36;23922:585;;;24090:27;24120:192;24150:11;24172:31;24214:27;24252:18;24281:22;24120:19;:192::i;:::-;24090:222;;24347:19;24321:45;;;;;:::i;:::-;;;24480:10;24463:15;24456:35;24445:55;23995:18;;;;;:::i;:::-;;;;23922:585;;;;24621:73;24642:18;24662:31;24621:20;:73::i;:::-;24614:80;;;;;;;;22630:2070;;;:::o;19220:136::-;19293:7;19316:34;19343:6;19316:26;:34::i;:::-;19309:41;;19220:136;;;:::o;18239:975::-;18692:32;18759:4;18727:29;:36;;;;:::i;:::-;18692:71;;18794:24;18776:15;:42;18772:437;;;18040:9;18861:15;18834:24;:42;;;;:::i;:::-;18833:87;18829:190;;;18967:24;18993:15;18940:69;;;;;;;;;;;;:::i;:::-;;;;;;;;18829:190;18772:437;;;17966:9;19055:24;19037:15;:42;;;;:::i;:::-;19036:87;19032:177;;;19159:24;19185:15;19141:60;;;;;;;;;;;;:::i;:::-;;;;;;;;19032:177;18772:437;18319:895;18239:975;:::o;12077:1200::-;12146:7;12225:27;12337:16;12321:14;12317:37;12304:51;12458:20;12437:19;12433:46;12402:20;12389:99;12363:125;;12268:227;12506:22;12501:83;;12546:30;;;;;;;;;;;;;;12501:83;12669:31;12754:8;;:15;;4012:2;12711:58;12707:113;;;12787:25;;;;;;;;;;;;;;12707:113;12915:40;12899:14;12895:61;12872:93;12844:121;;12978:30;3254:1;3201;13011:24;:64;;;;;;:::i;:::-;:92;;;;:::i;:::-;12978:125;;13164:8;;:15;;2898:1;13114:22;:47;;;;:::i;:::-;:65;13110:126;;;13197:31;;;;;;;;;;;;;;13110:126;13249:22;13242:29;;;;;12077:1200;:::o;13362:540::-;13479:24;13515:46;2283:2;13564:22;:41;;;;:::i;:::-;13515:90;;13657:8;;:15;;13616:38;:56;13612:111;;;13690:25;;;;;;;;;;;;;;13612:111;13811:38;13795:14;13791:59;13768:91;13747:112;;13872:24;13362:540;;;:::o;25515:4605::-;25793:7;25809:19;25846:23;25878:34;25922:63;25962:22;25922:39;:63::i;:::-;25837:148;;;;26064:25;26098:21;26128:18;26155:26;26190:31;3865:2;26258:70;3072:2;26278:26;:49;;;;:::i;:::-;26258:15;:19;;:70;;;;:::i;:::-;:125;;;;:::i;:::-;26232:151;;26464:31;26498:119;3550:3;26528:22;:88;;;;:::i;:::-;26498:8;;:15;;:19;;:119;;;;:::i;:::-;26464:153;;26628:35;26666:88;26730:23;2793:2;26696:22;:31;;;;:::i;:::-;:57;;;;:::i;:::-;26666:8;;:15;;:19;;:88;;;;:::i;:::-;26628:126;;26844:111;26921:23;26881:27;26844:111;:::i;:::-;26827:128;;27072:23;27049:20;27034:13;27030:40;27020:76;27006:90;;27176:23;27163:37;27141:59;;27212:236;;;27250:3;27280:15;27274:22;27267:29;;27320:10;27315:3;27308:23;27359:20;27354:3;27350:30;27343:37;;27425:10;27420:3;27416:20;27399:15;27392:45;27212:236;;;:::o;27460:350::-;27517:14;27575:25;27589:10;27575:25;:::i;:::-;27697:10;27676:6;27639:22;27612:108;27778:20;27754:22;27750:49;27732:67;;27532:278;27460:350;;;;:::o;:::-;27860:37;27878:18;27860:37;;:17;:37::i;:::-;27997:105;28041:10;2793:2;28062:22;:31;;;;:::i;:::-;27997:33;:105::i;:::-;27981:121;;28125:39;28150:13;28125:24;:39::i;:::-;28111:53;;;;26055:2117;;;;;;;28221:27;28257:22;28293;28288:1632;28338:15;28321:14;:32;28288:1632;;;28497:147;28545:22;28580:26;28619:14;28497:35;:147::i;:::-;28457:187;;;;;;;;28674:23;28657:1254;28732:11;:18;28714:15;:36;28657:1254;;;28832:11;28844:15;28832:28;;;;;;;;:::i;:::-;;;;;;;;28809:19;:51;28805:1095;;28877:34;28914:27;28942:15;28914:44;;;;;;;;:::i;:::-;;;;;;;;28877:81;;28996:67;29023:26;29051:11;28996:26;:67::i;:::-;28995:68;:225;;;;;29193:27;:25;:27::i;:::-;29142:78;;:31;29174:15;29142:48;;;;;;;;:::i;:::-;;;;;;;;:78;28995:225;28975:806;;;29302:31;29334:15;29302:48;;;;;;;;:::i;:::-;;;;;;;:50;;;;;;;;:::i;:::-;;;;;29529:14;29403:18;29422:15;29403:35;;;;;;;;:::i;:::-;;;;;;;;29508:1;29457:31;29489:15;29457:48;;;;;;;;:::i;:::-;;;;;;;;:52;;;;:::i;:::-;29403:123;;;;;;;;:::i;:::-;;;;;;;:140;;;;;29649:116;29692:26;29737:11;29649:24;:116::i;:::-;29602:27;29630:15;29602:44;;;;;;;;:::i;:::-;;;;;;;:163;;;;;28975:806;29881:5;;;28805:1095;28763:17;;;;;:::i;:::-;;;;28657:1254;;;;28355:16;;;;;:::i;:::-;;;;28288:1632;;;;28212:1715;;30099:15;3072:2;30039:26;:49;;;;:::i;:::-;30038:76;;;;:::i;:::-;3706:2;29993:121;;;;:::i;:::-;29979:135;;;;;25515:4605;;;;;;;:::o;30602:880::-;30758:16;30783:33;30833:18;:25;30819:40;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30783:76;;30866:30;30899:27;:25;:27::i;:::-;30866:60;;;;30940:21;30935:510;30983:18;:25;30967:13;:41;30935:510;;;31089:22;31040:31;31072:13;31040:46;;;;;;;;:::i;:::-;;;;;;;;:71;31036:233;;;31177:31;31209:13;31177:46;;;;;;;;:::i;:::-;;;;;;;;31236:22;31131:128;;;;;;;;;;;;:::i;:::-;;;;;;;;31036:233;31277:36;31316:50;31332:18;31351:13;31332:33;;;;;;;;:::i;:::-;;;;;;;;31316:15;:50::i;:::-;31277:89;;31409:28;31375:16;31392:13;31375:31;;;;;;;;:::i;:::-;;;;;;;:62;;;;;31027:418;31010:15;;;;;:::i;:::-;;;;30935:510;;;;31460:16;31453:23;;;;30602:880;;;;:::o;16341:403::-;16406:7;16440:1;16426:3;:10;:15;16422:75;;16459:30;;;;;;;;;;;;;;16422:75;16503:9;16508:3;16503:4;:9::i;:::-;16519:19;16554:1;16541:3;:10;:14;;;;:::i;:::-;16519:36;;16584:1;16579;16566:3;:10;:14;;;;:::i;:::-;:19;16562:177;;16596:11;16610:52;16623:3;16641:1;16627:11;:15;;;;:::i;:::-;16623:20;;;;;;;;:::i;:::-;;;;;;;;16645:3;16649:11;16645:16;;;;;;;;:::i;:::-;;;;;;;;16610:12;:52::i;:::-;16596:66;;16684:1;16678:3;:7;;;;:::i;:::-;16671:14;;;;;;16562:177;16715:3;16719:11;16715:16;;;;;;;;:::i;:::-;;;;;;;;16708:23;;;16341:403;;;;:::o;14729:1053::-;14862:23;14887:34;15010:23;15111:34;15188:30;2793:2;15221:36;:45;;;;:::i;:::-;15188:78;;15273:22;15298:62;2283:2;15318:22;:41;;;;:::i;:::-;15298:8;;:15;;:19;;:62;;;;:::i;:::-;15273:87;;15418:14;15405:28;15385:48;;15508:40;2953:1;15508:14;:18;;:40;;;;:::i;:::-;15491:57;;15617:14;15604:28;15573:59;;15697:16;15679:34;;;;15749:27;15720:56;;;;14926:856;;;;14729:1053;;;:::o;8095:98::-;8153:7;8184:1;8180;:5;;;;:::i;:::-;8173:12;;8095:98;;;;:::o;7738:::-;7796:7;7827:1;7823;:5;;;;:::i;:::-;7816:12;;7738:98;;;;:::o;316:727::-;445:7;464:9;480;496:7;581:31;565:14;561:52;639:25;626:39;621:44;;733:14;706:25;702:46;673:75;;774:25;761:39;756:44;;868:14;841:25;837:46;808:75;;917:25;904:39;901:1;896:48;891:53;;519:475;1007:30;1017:10;1029:1;1032;1035;1007:30;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1000:37;;;;;316:727;;;;:::o;13908:815::-;14113:27;14142:22;14173:34;3706:2;14210:36;:74;;;;:::i;:::-;14173:111;;14291:31;14325:126;14364:80;3072:2;14390:29;:52;;;;:::i;:::-;14369:14;14365:1;:18;;;;:::i;:::-;14364:24;;:80;;;;:::i;:::-;14325:26;:30;;:126;;;;:::i;:::-;14291:160;;14458:31;14492:44;14512:23;14492:8;;:15;;:19;;:44;;;;:::i;:::-;14458:78;;14597:23;14584:37;14561:60;;14689:20;14664:23;14660:50;14647:64;14629:82;;14552:166;;;13908:815;;;;;;:::o;1416:175::-;1499:4;1512:18;1548:8;1543:1;:13;;1533:6;:24;1512:45;;1584:1;1571:10;:14;1564:21;;;1416:175;;;;:::o;1276:134::-;1357:7;1395:8;1390:1;:13;;1380:6;:24;1373:31;;1276:134;;;;:::o;16750:774::-;16848:3;16842:10;16886:20;16881:3;16877:30;16959:16;16948:9;16944:32;16933:9;16929:48;17015:9;16985:527;17046:6;17037:7;17034:19;16985:527;;;17176:9;17144:359;17209:7;17200;17197:20;17144:359;;;17332:7;17326:14;17370:7;17364:14;17402:4;17396;17393:14;17390:102;;;17439:4;17430:7;17423:21;17474:4;17465:7;17458:21;17390:102;17301:202;;17255:16;17246:7;17242:30;17231:41;;17144:359;;;17148:48;17089:16;17080:7;17076:30;17065:41;;16985:527;;;16989:44;16816:703;;;16750:774;:::o;7357:98::-;7415:7;7446:1;7442;:5;;;;:::i;:::-;7435:12;;7357:98;;;;:::o;7:75:1:-;40:6;73:2;67:9;57:19;;7:75;:::o;88:117::-;197:1;194;187:12;211:117;320:1;317;310:12;334:126;371:7;411:42;404:5;400:54;389:65;;334:126;;;:::o;466:96::-;503:7;532:24;550:5;532:24;:::i;:::-;521:35;;466:96;;;:::o;568:122::-;641:24;659:5;641:24;:::i;:::-;634:5;631:35;621:63;;680:1;677;670:12;621:63;568:122;:::o;696:139::-;742:5;780:6;767:20;758:29;;796:33;823:5;796:33;:::i;:::-;696:139;;;;:::o;841:329::-;900:6;949:2;937:9;928:7;924:23;920:32;917:119;;;955:79;;:::i;:::-;917:119;1075:1;1100:53;1145:7;1136:6;1125:9;1121:22;1100:53;:::i;:::-;1090:63;;1046:117;841:329;;;;:::o;1176:86::-;1211:7;1251:4;1244:5;1240:16;1229:27;;1176:86;;;:::o;1268:112::-;1351:22;1367:5;1351:22;:::i;:::-;1346:3;1339:35;1268:112;;:::o;1386:214::-;1475:4;1513:2;1502:9;1498:18;1490:26;;1526:67;1590:1;1579:9;1575:17;1566:6;1526:67;:::i;:::-;1386:214;;;;:::o;1606:77::-;1643:7;1672:5;1661:16;;1606:77;;;:::o;1689:122::-;1762:24;1780:5;1762:24;:::i;:::-;1755:5;1752:35;1742:63;;1801:1;1798;1791:12;1742:63;1689:122;:::o;1817:139::-;1863:5;1901:6;1888:20;1879:29;;1917:33;1944:5;1917:33;:::i;:::-;1817:139;;;;:::o;1962:329::-;2021:6;2070:2;2058:9;2049:7;2045:23;2041:32;2038:119;;;2076:79;;:::i;:::-;2038:119;2196:1;2221:53;2266:7;2257:6;2246:9;2242:22;2221:53;:::i;:::-;2211:63;;2167:117;1962:329;;;;:::o;2297:77::-;2334:7;2363:5;2352:16;;2297:77;;;:::o;2380:118::-;2467:24;2485:5;2467:24;:::i;:::-;2462:3;2455:37;2380:118;;:::o;2504:222::-;2597:4;2635:2;2624:9;2620:18;2612:26;;2648:71;2716:1;2705:9;2701:17;2692:6;2648:71;:::i;:::-;2504:222;;;;:::o;2732:117::-;2841:1;2838;2831:12;2855:102;2896:6;2947:2;2943:7;2938:2;2931:5;2927:14;2923:28;2913:38;;2855:102;;;:::o;2963:180::-;3011:77;3008:1;3001:88;3108:4;3105:1;3098:15;3132:4;3129:1;3122:15;3149:281;3232:27;3254:4;3232:27;:::i;:::-;3224:6;3220:40;3362:6;3350:10;3347:22;3326:18;3314:10;3311:34;3308:62;3305:88;;;3373:18;;:::i;:::-;3305:88;3413:10;3409:2;3402:22;3192:238;3149:281;;:::o;3436:129::-;3470:6;3497:20;;:::i;:::-;3487:30;;3526:33;3554:4;3546:6;3526:33;:::i;:::-;3436:129;;;:::o;3571:311::-;3648:4;3738:18;3730:6;3727:30;3724:56;;;3760:18;;:::i;:::-;3724:56;3810:4;3802:6;3798:17;3790:25;;3870:4;3864;3860:15;3852:23;;3571:311;;;:::o;3888:117::-;3997:1;3994;3987:12;4028:710;4124:5;4149:81;4165:64;4222:6;4165:64;:::i;:::-;4149:81;:::i;:::-;4140:90;;4250:5;4279:6;4272:5;4265:21;4313:4;4306:5;4302:16;4295:23;;4366:4;4358:6;4354:17;4346:6;4342:30;4395:3;4387:6;4384:15;4381:122;;;4414:79;;:::i;:::-;4381:122;4529:6;4512:220;4546:6;4541:3;4538:15;4512:220;;;4621:3;4650:37;4683:3;4671:10;4650:37;:::i;:::-;4645:3;4638:50;4717:4;4712:3;4708:14;4701:21;;4588:144;4572:4;4567:3;4563:14;4556:21;;4512:220;;;4516:21;4130:608;;4028:710;;;;;:::o;4761:370::-;4832:5;4881:3;4874:4;4866:6;4862:17;4858:27;4848:122;;4889:79;;:::i;:::-;4848:122;5006:6;4993:20;5031:94;5121:3;5113:6;5106:4;5098:6;5094:17;5031:94;:::i;:::-;5022:103;;4838:293;4761:370;;;;:::o;5137:539::-;5221:6;5270:2;5258:9;5249:7;5245:23;5241:32;5238:119;;;5276:79;;:::i;:::-;5238:119;5424:1;5413:9;5409:17;5396:31;5454:18;5446:6;5443:30;5440:117;;;5476:79;;:::i;:::-;5440:117;5581:78;5651:7;5642:6;5631:9;5627:22;5581:78;:::i;:::-;5571:88;;5367:302;5137:539;;;;:::o;5682:114::-;5749:6;5783:5;5777:12;5767:22;;5682:114;;;:::o;5802:184::-;5901:11;5935:6;5930:3;5923:19;5975:4;5970:3;5966:14;5951:29;;5802:184;;;;:::o;5992:132::-;6059:4;6082:3;6074:11;;6112:4;6107:3;6103:14;6095:22;;5992:132;;;:::o;6130:108::-;6207:24;6225:5;6207:24;:::i;:::-;6202:3;6195:37;6130:108;;:::o;6244:179::-;6313:10;6334:46;6376:3;6368:6;6334:46;:::i;:::-;6412:4;6407:3;6403:14;6389:28;;6244:179;;;;:::o;6429:113::-;6499:4;6531;6526:3;6522:14;6514:22;;6429:113;;;:::o;6578:732::-;6697:3;6726:54;6774:5;6726:54;:::i;:::-;6796:86;6875:6;6870:3;6796:86;:::i;:::-;6789:93;;6906:56;6956:5;6906:56;:::i;:::-;6985:7;7016:1;7001:284;7026:6;7023:1;7020:13;7001:284;;;7102:6;7096:13;7129:63;7188:3;7173:13;7129:63;:::i;:::-;7122:70;;7215:60;7268:6;7215:60;:::i;:::-;7205:70;;7061:224;7048:1;7045;7041:9;7036:14;;7001:284;;;7005:14;7301:3;7294:10;;6702:608;;;6578:732;;;;:::o;7316:373::-;7459:4;7497:2;7486:9;7482:18;7474:26;;7546:9;7540:4;7536:20;7532:1;7521:9;7517:17;7510:47;7574:108;7677:4;7668:6;7574:108;:::i;:::-;7566:116;;7316:373;;;;:::o;7695:311::-;7772:4;7862:18;7854:6;7851:30;7848:56;;;7884:18;;:::i;:::-;7848:56;7934:4;7926:6;7922:17;7914:25;;7994:4;7988;7984:15;7976:23;;7695:311;;;:::o;8012:122::-;8085:24;8103:5;8085:24;:::i;:::-;8078:5;8075:35;8065:63;;8124:1;8121;8114:12;8065:63;8012:122;:::o;8140:139::-;8186:5;8224:6;8211:20;8202:29;;8240:33;8267:5;8240:33;:::i;:::-;8140:139;;;;:::o;8302:710::-;8398:5;8423:81;8439:64;8496:6;8439:64;:::i;:::-;8423:81;:::i;:::-;8414:90;;8524:5;8553:6;8546:5;8539:21;8587:4;8580:5;8576:16;8569:23;;8640:4;8632:6;8628:17;8620:6;8616:30;8669:3;8661:6;8658:15;8655:122;;;8688:79;;:::i;:::-;8655:122;8803:6;8786:220;8820:6;8815:3;8812:15;8786:220;;;8895:3;8924:37;8957:3;8945:10;8924:37;:::i;:::-;8919:3;8912:50;8991:4;8986:3;8982:14;8975:21;;8862:144;8846:4;8841:3;8837:14;8830:21;;8786:220;;;8790:21;8404:608;;8302:710;;;;;:::o;9035:370::-;9106:5;9155:3;9148:4;9140:6;9136:17;9132:27;9122:122;;9163:79;;:::i;:::-;9122:122;9280:6;9267:20;9305:94;9395:3;9387:6;9380:4;9372:6;9368:17;9305:94;:::i;:::-;9296:103;;9112:293;9035:370;;;;:::o;9411:539::-;9495:6;9544:2;9532:9;9523:7;9519:23;9515:32;9512:119;;;9550:79;;:::i;:::-;9512:119;9698:1;9687:9;9683:17;9670:31;9728:18;9720:6;9717:30;9714:117;;;9750:79;;:::i;:::-;9714:117;9855:78;9925:7;9916:6;9905:9;9901:22;9855:78;:::i;:::-;9845:88;;9641:302;9411:539;;;;:::o;9956:329::-;10015:6;10064:2;10052:9;10043:7;10039:23;10035:32;10032:119;;;10070:79;;:::i;:::-;10032:119;10190:1;10215:53;10260:7;10251:6;10240:9;10236:22;10215:53;:::i;:::-;10205:63;;10161:117;9956:329;;;;:::o;10291:118::-;10378:24;10396:5;10378:24;:::i;:::-;10373:3;10366:37;10291:118;;:::o;10415:222::-;10508:4;10546:2;10535:9;10531:18;10523:26;;10559:71;10627:1;10616:9;10612:17;10603:6;10559:71;:::i;:::-;10415:222;;;;:::o;10643:180::-;10691:77;10688:1;10681:88;10788:4;10785:1;10778:15;10812:4;10809:1;10802:15;10829:180;10877:77;10874:1;10867:88;10974:4;10971:1;10964:15;10998:4;10995:1;10988:15;11015:233;11054:3;11077:24;11095:5;11077:24;:::i;:::-;11068:33;;11123:66;11116:5;11113:77;11110:103;;11193:18;;:::i;:::-;11110:103;11240:1;11233:5;11229:13;11222:20;;11015:233;;;:::o;11254:191::-;11294:3;11313:20;11331:1;11313:20;:::i;:::-;11308:25;;11347:20;11365:1;11347:20;:::i;:::-;11342:25;;11390:1;11387;11383:9;11376:16;;11411:3;11408:1;11405:10;11402:36;;;11418:18;;:::i;:::-;11402:36;11254:191;;;;:::o;11451:180::-;11499:77;11496:1;11489:88;11596:4;11593:1;11586:15;11620:4;11617:1;11610:15;11637:185;11677:1;11694:20;11712:1;11694:20;:::i;:::-;11689:25;;11728:20;11746:1;11728:20;:::i;:::-;11723:25;;11767:1;11757:35;;11772:18;;:::i;:::-;11757:35;11814:1;11811;11807:9;11802:14;;11637:185;;;;:::o;11828:194::-;11868:4;11888:20;11906:1;11888:20;:::i;:::-;11883:25;;11922:20;11940:1;11922:20;:::i;:::-;11917:25;;11966:1;11963;11959:9;11951:17;;11990:1;11984:4;11981:11;11978:37;;;11995:18;;:::i;:::-;11978:37;11828:194;;;;:::o;12028:332::-;12149:4;12187:2;12176:9;12172:18;12164:26;;12200:71;12268:1;12257:9;12253:17;12244:6;12200:71;:::i;:::-;12281:72;12349:2;12338:9;12334:18;12325:6;12281:72;:::i;:::-;12028:332;;;;;:::o;12366:410::-;12406:7;12429:20;12447:1;12429:20;:::i;:::-;12424:25;;12463:20;12481:1;12463:20;:::i;:::-;12458:25;;12518:1;12515;12511:9;12540:30;12558:11;12540:30;:::i;:::-;12529:41;;12719:1;12710:7;12706:15;12703:1;12700:22;12680:1;12673:9;12653:83;12630:139;;12749:18;;:::i;:::-;12630:139;12414:362;12366:410;;;;:::o;12782:176::-;12814:1;12831:20;12849:1;12831:20;:::i;:::-;12826:25;;12865:20;12883:1;12865:20;:::i;:::-;12860:25;;12904:1;12894:35;;12909:18;;:::i;:::-;12894:35;12950:1;12947;12943:9;12938:14;;12782:176;;;;:::o;12964:118::-;13051:24;13069:5;13051:24;:::i;:::-;13046:3;13039:37;12964:118;;:::o;13088:545::-;13261:4;13299:3;13288:9;13284:19;13276:27;;13313:71;13381:1;13370:9;13366:17;13357:6;13313:71;:::i;:::-;13394:68;13458:2;13447:9;13443:18;13434:6;13394:68;:::i;:::-;13472:72;13540:2;13529:9;13525:18;13516:6;13472:72;:::i;:::-;13554;13622:2;13611:9;13607:18;13598:6;13554:72;:::i;:::-;13088:545;;;;;;;:::o
Swarm Source
ipfs://596992b93bbba805833348e4c54352d8819a37f00bd6d0271128748bb8dc95bd
Age | Block | Fee Address | BC Fee Address | Voting Power | Jailed | Incoming |
---|
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.