Contract 0xd2322468e5aa331381200754f6daad3df923539e

Txn Hash Method
Block
From
To
Value [Txn Fee]
0x917dfcb68c1928b740cfb99d2ddc02aa734da5a9969793cfe485b859deaaa52cRegister Protoco...280120852022-01-15 7:06:0711 days 13 hrs ago0x481140f916a4e64559694db4d56d692cadc0326c IN  0xd2322468e5aa331381200754f6daad3df923539e0 FTM0.048517779387
0xe250dd6ca053d7995f7c0f06c6a1a9b7c5ea5e4aff5999ef2cbd34de96b60bea0x60806040280118762022-01-15 7:02:5211 days 13 hrs ago0x481140f916a4e64559694db4d56d692cadc0326c IN  Create: AllowlistRegistry0 FTM0.38650396255
[ Download CSV Export 
Latest 1 internal transaction
Parent Txn Hash Block From To Value
0xe250dd6ca053d7995f7c0f06c6a1a9b7c5ea5e4aff5999ef2cbd34de96b60bea280118762022-01-15 7:02:5211 days 13 hrs ago 0x481140f916a4e64559694db4d56d692cadc0326c  Contract Creation0 FTM
[ Download CSV Export 
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
AllowlistRegistry

Compiler Version
v0.8.11+commit.d7f03943

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity Multiple files format)

File 1 of 6: AllowlistRegistry.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.11;
import "./CalldataValidation.sol";
import "./IAllowlist.sol";

/*******************************************************
 *                      Interfaces
 *******************************************************/
interface IAllowlistFactory {
  function cloneAllowlist(string memory, address) external returns (address);
}

interface IProtocolOwnership {
  function ownerAddressByName(string memory) external view returns (address);
}

/*******************************************************
 *                   Main Contract Logic
 *******************************************************/
contract AllowlistRegistry {
  address public factoryAddress;
  string[] public registeredProtocols; // Array of all protocols which have successfully completed registration
  mapping(string => address) public allowlistAddressByOriginName; // Address of protocol specific allowlist
  address public protocolOwnershipAddress; // Address of temporary protocol ownership contract (TODO: Implement DNSSEC validation on Fantom)

  constructor(address _factoryAddress, address _protocolOwnershipAddress) {
    factoryAddress = _factoryAddress;
    protocolOwnershipAddress = _protocolOwnershipAddress;
  }

  /**
   * @notice Determine protocol onwer address given an origin name
   * @param originName is the domain name for a protocol (ie. "yearn.finance")
   * @return ownerAddress Returns the address of the domain controller if the domain is registered on ENS
   */
  function protocolOwnerAddressByOriginName(string memory originName)
    public
    view
    returns (address ownerAddress)
  {
    ownerAddress = IProtocolOwnership(protocolOwnershipAddress).ownerAddressByName(originName);
  }

  /**
   * @notice Begin protocol registration
   * @param originName is the domain name for a protocol (ie. "yearn.finance")
   * @dev Only valid protocol owners can begin registration
   * @dev Beginning registration generates a smart contract each protocol can use
   *      to manage their conditions and validation implementation logic
   * @dev Only fully registered protocols appear on the registration list
   */
  function registerProtocol(string memory originName) public {
    // Make sure caller is protocol owner
    address protocolOwnerAddress = protocolOwnerAddressByOriginName(originName);
    require(
      protocolOwnerAddress == msg.sender,
      "Only protocol owners can register protocols"
    );

    // Make sure protocol is not already registered
    bool protocolIsAlreadyRegistered = allowlistAddressByOriginName[
      originName
    ] != address(0);
    require(
      protocolIsAlreadyRegistered == false,
      "Protocol is already registered"
    );

    // Clone, register and initialize allowlist
    address allowlistAddress = IAllowlistFactory(factoryAddress).cloneAllowlist(
      originName,
      protocolOwnerAddress
    );
    allowlistAddressByOriginName[originName] = allowlistAddress;

    // Register protocol
    registeredProtocols.push(originName);
  }

  /**
   * @notice Return a list of fully registered protocols
   */
  function registeredProtocolsList() public view returns (string[] memory) {
    return registeredProtocols;
  }

  /**
   * @notice Allow protocol owners to override and replace existing allowlist
   * @dev This method is destructive and cannot be undone
   * @dev Protocols can only re-register if they have already registered once
   */
  function reregisterProtocol(
    string memory originName,
    IAllowlist.Condition[] memory conditions
  ) public {
    address protocolOwnerAddress = protocolOwnerAddressByOriginName(originName);
    bool callerIsProtocolOwner = protocolOwnerAddress == msg.sender;
    bool protocolIsRegistered = allowlistAddressByOriginName[originName] !=
      address(0);

    // Only owner can re-register
    require(
      callerIsProtocolOwner,
      "Only protocol owners can replace their allowlist with a new allowlist"
    );

    // Only registered protocols can re-register
    require(protocolIsRegistered, "Protocol is not yet registered");

    // Delete existing allowlist
    delete allowlistAddressByOriginName[originName];

    // Clone, re-register and initialize allowlist
    IAllowlistFactory allowlistFactory = IAllowlistFactory(factoryAddress);
    address allowlistAddress = allowlistFactory.cloneAllowlist(
      originName,
      address(this)
    );
    allowlistAddressByOriginName[originName] = allowlistAddress;

    // Add conditions to new allowlist
    IAllowlist allowlist = IAllowlist(allowlistAddress);
    allowlist.addConditions(conditions);
    IAllowlist(allowlist).setOwnerAddress(protocolOwnerAddress);
  }

  /**
   * @notice Determine whether or not a given target and calldata is valid
   * @dev In order to be valid, target and calldata must pass the allowlist conditions tests
   * @param targetAddress The target address of the method call
   * @param data The raw calldata of the call
   * @return isValid True if valid, false if not
   */
  function validateCalldataByOrigin(
    string memory originName,
    address targetAddress,
    bytes calldata data
  ) public view returns (bool isValid) {
    address allowlistAddress = allowlistAddressByOriginName[originName];
    isValid = CalldataValidation.validateCalldataByAllowlist(
      allowlistAddress,
      targetAddress,
      data
    );
  }
}

File 2 of 6: AbiDecoder.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.11;
import "./Strings.sol";

/**
 * @title Decode raw calldata and params
 * @author yearn.finance
 */

library AbiDecoder {
  /**
   * @notice Extract all params from calldata given a list of param types and raw calldata bytes
   * @param paramTypes An array of param types (ie. ["address", "bytes[]", "uint256"])
   * @param data Raw calldata (including 4byte method selector)
   * @return Returns an array of input param data
   */
  function getParamsFromCalldata(
    string[] memory paramTypes,
    bytes calldata data
  ) public pure returns (bytes[] memory) {
    uint256 numberOfParams = paramTypes.length;
    bytes[] memory results = new bytes[](numberOfParams);
    for (uint256 paramIdx = 0; paramIdx < numberOfParams; paramIdx++) {
      string memory paramType = paramTypes[paramIdx];
      bytes memory param = getParamFromCalldata(data, paramType, paramIdx);
      results[paramIdx] = param;
    }
    return results;
  }

  /**
   * @notice Extract param bytes given calldata, param type and param index
   * @param data Raw calldata (including 4byte method selector)
   * @param paramIdx The position of the param data to fetch (0 will fetch the first param)
   * @return Returns the raw data of the param at paramIdx index
   * @dev If the type is "bytes", "bytes[]", "string" or "string[]" the offset byte
   *      will be set to 0x20. The param is isolated in such a way that it can be passed as an
   *      input to another method selector using call or staticcall.
   */
  function getParamFromCalldata(
    bytes calldata data,
    string memory paramType,
    uint256 paramIdx
  ) public pure returns (bytes memory) {
    uint256 paramsStartIdx = 0x04; // Start after method selector
    uint256 paramOffset = 0x20 * paramIdx;
    bytes memory paramDescriptorValue = bytes(
      data[paramsStartIdx + paramOffset:paramsStartIdx + paramOffset + 0x20]
    );

    bool paramTypeIsStringOrBytes = Strings.stringsEqual(paramType, "bytes") ||
      Strings.stringsEqual(paramType, "string");
    bool paramTypeIsStringArrayOrBytesArray = Strings.stringsEqual(
      paramType,
      "bytes[]"
    ) || Strings.stringsEqual(paramType, "string[]");
    bool _paramTypeIsArray = paramTypeIsArray(paramType);

    uint256 paramStartIdx = uint256(bytes32(paramDescriptorValue)) + 0x04;
    if (paramTypeIsStringOrBytes) {
      return extractParamForBytesType(data, paramStartIdx);
    } else if (paramTypeIsStringArrayOrBytesArray) {
      return extractParamForBytesArrayType(data, paramStartIdx);
    } else if (_paramTypeIsArray) {
      return extractParamForSimpleArray(data, paramStartIdx);
    } else {
      return paramDescriptorValue;
    }
  }

  /**
   * @notice Extract param for "bytes" and "string" types given calldata and a param start index
   * @param data Raw calldata (including 4byte method selector)
   * @param paramStartIdx The offset the param starts at
   * @return Returns the raw data of the param at paramIdx index
   */
  function extractParamForBytesType(bytes calldata data, uint256 paramStartIdx)
    public
    pure
    returns (bytes memory)
  {
    uint256 paramEndIdx = paramStartIdx + 0x20;
    bytes32 bytesLengthBytes = bytes32(data[paramStartIdx:paramEndIdx]);
    uint256 bytesLength = uint256(bytesLengthBytes);
    bytes memory dataToAdd = abi.encodePacked(
      uint256(0x20),
      bytes32(bytesLengthBytes)
    );
    uint256 numberOfRowsOfBytes = (bytesLength / 32) + 1;
    for (uint256 rowIdx; rowIdx < numberOfRowsOfBytes; rowIdx++) {
      uint256 rowStartIdx = paramEndIdx + (0x20 * rowIdx);
      dataToAdd = abi.encodePacked(
        dataToAdd,
        data[rowStartIdx:rowStartIdx + 0x20]
      );
    }
    return dataToAdd;
  }

  /**
   * @notice Extract param for "bytes[]" and "string[]" types given calldata and a param start index
   * @param data Raw calldata (including 4byte method selector)
   * @param paramStartIdx The offset the param starts at
   * @return Returns the raw data of the param at paramIdx index
   */
  function extractParamForBytesArrayType(
    bytes calldata data,
    uint256 paramStartIdx
  ) public pure returns (bytes memory) {
    uint256 paramEndIdx = paramStartIdx + 0x20;
    bytes32 arrayLengthBytes = bytes32(data[paramStartIdx:paramEndIdx]);
    uint256 arrayLength = uint256(arrayLengthBytes);
    bytes memory dataToAdd = abi.encodePacked(
      uint256(0x20),
      bytes32(arrayLengthBytes)
    );
    uint256 lastOffsetStartIdx = paramEndIdx + (0x20 * arrayLength) - 0x20;
    uint256 lastOffset = uint256(
      bytes32(data[lastOffsetStartIdx:lastOffsetStartIdx + 0x20])
    );
    bytes32 lastElementBytesLengthBytes = bytes32(
      data[paramEndIdx + lastOffset:paramEndIdx + lastOffset + 0x20]
    );
    uint256 lastElementBytesLength = uint256(lastElementBytesLengthBytes);
    uint256 numberOfRowsOfBytesForLastElement = (lastElementBytesLength / 32) +
      1;
    uint256 dataEndIdx = paramEndIdx +
      lastOffset +
      0x20 +
      (0x20 * numberOfRowsOfBytesForLastElement);
    dataToAdd = abi.encodePacked(dataToAdd, data[paramEndIdx:dataEndIdx]);
    return dataToAdd;
  }

  /**
   * @notice Extract param for "*[]" types given calldata and a param start index, assuming each element is 32 bytes
   * @param data Raw calldata (including 4byte method selector)
   * @param paramStartIdx The offset the param starts at
   * @return Returns the raw data of the param at paramIdx index
   */
  function extractParamForSimpleArray(
    bytes calldata data,
    uint256 paramStartIdx
  ) public pure returns (bytes memory) {
    uint256 paramEndIdx = paramStartIdx + 0x20;
    bytes32 arrayLengthBytes = bytes32(data[paramStartIdx:paramEndIdx]);
    uint256 arrayLength = uint256(arrayLengthBytes);
    bytes memory dataToAdd = abi.encodePacked(
      uint256(0x20),
      bytes32(arrayLengthBytes)
    );
    for (uint256 rowIdx; rowIdx < arrayLength; rowIdx++) {
      uint256 rowStartIdx = paramEndIdx + (0x20 * rowIdx);
      dataToAdd = abi.encodePacked(
        dataToAdd,
        data[rowStartIdx:rowStartIdx + 0x20]
      );
    }
    return dataToAdd;
  }

  /**
   * @notice Check to see if the last two characters of a string are "[]"
   * @param paramType Param type as a string (ie. "uint256", "uint256[]")
   * @return Returns true if the paramType ends with "[]", false if not
   */
  function paramTypeIsArray(string memory paramType)
    internal
    pure
    returns (bool)
  {
    bytes32 lastTwoCharacters;
    assembly {
      let len := mload(paramType)
      lastTwoCharacters := mload(add(add(paramType, 0x20), sub(len, 2)))
    }
    return lastTwoCharacters == bytes32(bytes("[]"));
  }
}

File 3 of 6: CalldataValidation.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.11;
import "./Strings.sol";
import "./AbiDecoder.sol";
import "./IAllowlist.sol";

/**
 * @title Validate raw calldata against an allowlist
 * @author yearn.finance
 */

/*******************************************************
 *                   Main Contract Logic
 *******************************************************/
library CalldataValidation {
  /**
   * @notice Calculate a method signature given a condition
   * @param condition The condition from which to generate the signature
   * @return signature The method signature in string format (ie. "approve(address,uint256)")
   */
  function methodSignatureByCondition(IAllowlist.Condition memory condition)
    public
    pure
    returns (string memory signature)
  {
    bytes memory signatureBytes = abi.encodePacked(condition.methodName, "(");
    for (uint256 paramIdx; paramIdx < condition.paramTypes.length; paramIdx++) {
      signatureBytes = abi.encodePacked(
        signatureBytes,
        condition.paramTypes[paramIdx]
      );
      if (paramIdx + 1 < condition.paramTypes.length) {
        signatureBytes = abi.encodePacked(signatureBytes, ",");
      }
    }
    signatureBytes = abi.encodePacked(signatureBytes, ")");
    signature = string(signatureBytes);
  }

  /**
   * @notice Check target validity
   * @param implementationAddress The address the validation method will be executed against
   * @param targetAddress The target address to validate
   * @param requirementValidationMethod The method to execute
   * @return targetValid Returns true if the target is valid and false otherwise
   * @dev If "requirementValidationMethod" is "isValidVaultToken" and target address is usdc
   *      the validation check will look like this: usdc.isValidVaultToken(targetAddress),
   *      where the result of the validation method is expected to return a bool
   */
  function checkTarget(
    address implementationAddress,
    address targetAddress,
    string memory requirementValidationMethod
  ) public view returns (bool targetValid) {
    string memory methodSignature = string(
      abi.encodePacked(requirementValidationMethod, "(address)")
    );
    (, bytes memory data) = address(implementationAddress).staticcall(
      abi.encodeWithSignature(methodSignature, targetAddress)
    );
    targetValid = abi.decode(data, (bool));
  }

  /**
   * @notice Check method selector validity
   * @param data Raw input calldata (we will extract the 4-byte selector
   *             from the beginning of the calldata)
   * @param condition The condition struct to check (we generate the complete
   *        method selector using condition.methodName and condition.paramTypes)
   * @return methodSelectorValid Returns true if the method selector is valid and false otherwise
   */
  function checkMethodSelector(
    bytes calldata data,
    IAllowlist.Condition memory condition
  ) public pure returns (bool methodSelectorValid) {
    string memory methodSignature = methodSignatureByCondition(condition);
    bytes4 methodSelectorBySignature = bytes4(
      keccak256(bytes(methodSignature))
    );
    bytes4 methodSelectorByCalldata = bytes4(data[0:4]);
    methodSelectorValid = methodSelectorBySignature == methodSelectorByCalldata;
  }

  /**
   * @notice Check an individual method param's validity
   * @param implementationAddress The address the validation method will be executed against
   * @param requirement The specific requirement (of type "param") to check (ie. ["param", "isVault", "0"])
   * @dev A condition may have multiple requirements, all of which must be true
   * @dev The middle element of a requirement is the requirement validation method
   * @dev The last element of a requirement is the parameter index to validate against
   * @param condition The entire condition struct to check the param against
   * @param data Raw input calldata for the original method call
   * @return Returns true if the param is valid, false if not
   */
  function checkParam(
    address implementationAddress,
    string[] memory requirement,
    IAllowlist.Condition memory condition,
    bytes calldata data
  ) public view returns (bool) {
    uint256 paramIdx = Strings.atoi(requirement[2], 10);
    string memory paramType = condition.paramTypes[paramIdx];
    bytes memory paramCalldata = AbiDecoder.getParamFromCalldata(
      data,
      paramType,
      paramIdx
    );
    string memory methodSignature = string(
      abi.encodePacked(requirement[1], "(", paramType, ")")
    );
    bytes memory encodedCalldata = abi.encodePacked(
      bytes4(keccak256(bytes(methodSignature))),
      paramCalldata
    );
    bool success;
    bytes memory resultData;
    (success, resultData) = address(implementationAddress).staticcall(
      encodedCalldata
    );
    if (success) {
      return abi.decode(resultData, (bool));
    }
    return false;
  }

  /**
   * @notice Test a target address and calldata against a specific condition and implementation
   * @param condition The condition to test
   * @param targetAddress Target address of the original method call
   * @param data Calldata of the original methodcall
   * @return Returns true if the condition passes and false if not
   * @dev The condition check is comprised of 3 parts:
          - Method selector check (to make sure the calldata method selector matches the condition method selector)
          - Target check (to make sure the target is valid)
          - Param check (to make sure the specified param is valid)
   */
  function testCondition(
    address allowlistAddress,
    IAllowlist.Condition memory condition,
    address targetAddress,
    bytes calldata data
  ) public view returns (bool) {
    string[][] memory requirements = condition.requirements;
    address implementationAddress = IAllowlist(allowlistAddress)
      .implementationById(condition.implementationId);
    for (
      uint256 requirementIdx;
      requirementIdx < requirements.length;
      requirementIdx++
    ) {
      string[] memory requirement = requirements[requirementIdx];
      string memory requirementType = requirement[0];
      string memory requirementValidationMethod = requirement[1];
      if (!checkMethodSelector(data, condition)) {
        return false;
      }
      if (Strings.stringsEqual(requirementType, "target")) {
        bool targetValid = checkTarget(
          implementationAddress,
          targetAddress,
          requirementValidationMethod
        );
        if (!targetValid) {
          return false;
        }
      } else if (Strings.stringsEqual(requirementType, "param")) {
        bool paramValid = checkParam(
          implementationAddress,
          requirement,
          condition,
          data
        );
        if (!paramValid) {
          return false;
        }
      }
    }
    return true;
  }

  /**
   * @notice Test target address and calldata against all stored protocol conditions
   * @dev This is done to determine whether or not the target address and calldata are valid and whitelisted
   * @dev This is the primary method that should be called by integrators
   * @param allowlistAddress The address of the allowlist to check calldata against
   * @param targetAddress The target address of the call
   * @param data The raw calldata to test
   * @return Returns true if the calldata/target test is successful and false if not
   */
  function validateCalldataByAllowlist(
    address allowlistAddress,
    address targetAddress,
    bytes calldata data
  ) public view returns (bool) {
    IAllowlist.Condition[] memory _conditions = IAllowlist(allowlistAddress)
      .conditionsList();
    for (
      uint256 conditionIdx;
      conditionIdx < _conditions.length;
      conditionIdx++
    ) {
      IAllowlist.Condition memory condition = _conditions[conditionIdx];
      bool conditionPassed = testCondition(
        allowlistAddress,
        condition,
        targetAddress,
        data
      );
      if (conditionPassed) {
        return true;
      }
    }
    return false;
  }
}

File 4 of 6: IAllowlist.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.11;
import "./IOwnable.sol";

interface IAllowlist is IOwnable {
  struct Condition {
    string id;
    string implementationId;
    string methodName;
    string[] paramTypes;
    string[][] requirements;
  }

  function conditionsList() external view returns (Condition[] memory);

  function addConditions(Condition[] memory) external;

  function implementationById(string memory) external view returns (address);
}

File 5 of 6: IOwnable.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.11;

interface IOwnable {
  function setOwnerAddress(address _ownerAddress) external;
}

File 6 of 6: Strings.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.11;

/**
 * @title Small library for working with strings
 * @author yearn.finance
 */

library Strings {
  /**
   * @notice Search for a needle in a haystack
   * @param haystack The string to search
   * @param needle The string to search for
   */
  function stringStartsWith(string memory haystack, string memory needle)
    public
    pure
    returns (bool)
  {
    return indexOfStringInString(needle, haystack) == 0;
  }

  /**
   * @notice Find the index of a string in another string
   * @param needle The string to search for
   * @param haystack The string to search
   * @return Returns -1 if no match is found, otherwise returns the index of the match
   */
  function indexOfStringInString(string memory needle, string memory haystack)
    public
    pure
    returns (int256)
  {
    bytes memory _needle = bytes(needle);
    bytes memory _haystack = bytes(haystack);
    if (_haystack.length < _needle.length) {
      return -1;
    }
    bool _match;
    for (uint256 haystackIdx; haystackIdx < _haystack.length; haystackIdx++) {
      for (uint256 needleIdx; needleIdx < _needle.length; needleIdx++) {
        uint8 needleChar = uint8(_needle[needleIdx]);
        if (haystackIdx + needleIdx >= _haystack.length) {
          return -1;
        }
        uint8 haystackChar = uint8(_haystack[haystackIdx + needleIdx]);
        if (needleChar == haystackChar) {
          _match = true;
          if (needleIdx == _needle.length - 1) {
            return int256(haystackIdx);
          }
        } else {
          _match = false;
          break;
        }
      }
    }
    return -1;
  }

  /**
   * @notice Check to see if two strings are exactly equal
   * @dev Supports strings of arbitrary length
   * @param input0 First string to compare
   * @param input1 Second string to compare
   * @return Returns true if strings are exactly equal, false if not
   */
  function stringsEqual(string memory input0, string memory input1)
    public
    pure
    returns (bool)
  {
    uint256 input0Length = bytes(input0).length;
    uint256 input1Length = bytes(input1).length;
    uint256 maxLength;
    if (input0Length > input1Length) {
      maxLength = input0Length;
    } else {
      maxLength = input1Length;
    }
    uint256 numberOfRowsToCompare = (maxLength / 32) + 1;
    bytes32 input0Bytes32;
    bytes32 input1Bytes32;
    for (uint256 rowIdx; rowIdx < numberOfRowsToCompare; rowIdx++) {
      uint256 offset = 0x20 * (rowIdx + 1);
      assembly {
        input0Bytes32 := mload(add(input0, offset))
        input1Bytes32 := mload(add(input1, offset))
      }
      if (input0Bytes32 != input1Bytes32) {
        return false;
      }
    }
    return true;
  }

  /**
   * @notice Convert ASCII to integer
   * @param input Integer as a string (ie. "345")
   * @param base Base to use for the conversion (10 for decimal)
   * @return output Returns uint256 representation of input string
   * @dev Based on GemERC721 utility but includes a fix
   */
  function atoi(string memory input, uint8 base)
    public
    pure
    returns (uint256 output)
  {
    require(base == 2 || base == 8 || base == 10 || base == 16);
    bytes memory buf = bytes(input);
    for (uint256 idx = 0; idx < buf.length; idx++) {
      uint8 digit = uint8(buf[idx]) - 0x30;
      if (digit > 10) {
        digit -= 7;
      }
      require(digit < base);
      output *= base;
      output += digit;
    }
    return output;
  }

  /**
   * @notice Convert integer to ASCII
   * @param input Integer as a string (ie. "345")
   * @param base Base to use for the conversion (10 for decimal)
   * @return output Returns string representation of input integer
   * @dev Based on GemERC721 utility but includes a fix
   */
  function itoa(uint256 input, uint8 base)
    public
    pure
    returns (string memory output)
  {
    require(base == 2 || base == 8 || base == 10 || base == 16);
    if (input == 0) {
      return "0";
    }
    bytes memory buf = new bytes(256);
    uint256 idx = 0;
    while (input > 0) {
      uint8 digit = uint8(input % base);
      uint8 ascii = digit + 0x30;
      if (digit > 9) {
        ascii += 7;
      }
      buf[idx++] = bytes1(ascii);
      input /= base;
    }
    uint256 length = idx;
    for (idx = 0; idx < length / 2; idx++) {
      buf[idx] ^= buf[length - 1 - idx];
      buf[length - 1 - idx] ^= buf[idx];
      buf[idx] ^= buf[length - 1 - idx];
    }
    output = string(buf);
  }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_factoryAddress","type":"address"},{"internalType":"address","name":"_protocolOwnershipAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"string","name":"","type":"string"}],"name":"allowlistAddressByOriginName","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"factoryAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"originName","type":"string"}],"name":"protocolOwnerAddressByOriginName","outputs":[{"internalType":"address","name":"ownerAddress","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"protocolOwnershipAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"originName","type":"string"}],"name":"registerProtocol","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"registeredProtocols","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"registeredProtocolsList","outputs":[{"internalType":"string[]","name":"","type":"string[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"originName","type":"string"},{"components":[{"internalType":"string","name":"id","type":"string"},{"internalType":"string","name":"implementationId","type":"string"},{"internalType":"string","name":"methodName","type":"string"},{"internalType":"string[]","name":"paramTypes","type":"string[]"},{"internalType":"string[][]","name":"requirements","type":"string[][]"}],"internalType":"struct IAllowlist.Condition[]","name":"conditions","type":"tuple[]"}],"name":"reregisterProtocol","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"originName","type":"string"},{"internalType":"address","name":"targetAddress","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"validateCalldataByOrigin","outputs":[{"internalType":"bool","name":"isValid","type":"bool"}],"stateMutability":"view","type":"function"}]

60806040523480156200001157600080fd5b5060405162001e5638038062001e5683398181016040528101906200003791906200012a565b816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505062000171565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620000f282620000c5565b9050919050565b6200010481620000e5565b81146200011057600080fd5b50565b6000815190506200012481620000f9565b92915050565b60008060408385031215620001445762000143620000c0565b5b6000620001548582860162000113565b9250506020620001678582860162000113565b9150509250929050565b611cd580620001816000396000f3fe608060405234801561001057600080fd5b50600436106100935760003560e01c8063966dae0e11610066578063966dae0e14610146578063a1514ddd14610164578063da06ca6d14610180578063f892cc8d146101b0578063fa5d100a146101ce57610093565b80631052f20a146100985780631ca20c29146100c85780633af1d08d146100e6578063524a4b7414610116575b600080fd5b6100b260048036038101906100ad9190610e02565b6101ea565b6040516100bf9190610ead565b60405180910390f35b6100d06102b7565b6040516100dd9190611012565b60405180910390f35b61010060048036038101906100fb9190611034565b610390565b60405161010d919061108c565b60405180910390f35b610130600480360381019061012b9190611034565b6103d9565b60405161013d919061108c565b60405180910390f35b61014e61047e565b60405161015b919061108c565b60405180910390f35b61017e60048036038101906101799190611034565b6104a2565b005b61019a600480360381019061019591906110dd565b610718565b6040516101a79190611154565b60405180910390f35b6101b86107c4565b6040516101c5919061108c565b60405180910390f35b6101e860048036038101906101e3919061153b565b6107ea565b005b6000806002866040516101fd91906115ef565b908152602001604051809103902060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905073c4fa9d2440482b4fead00748d33186f7b0539098630d16ed6f828787876040518563ffffffff1660e01b815260040161026b9493929190611653565b602060405180830381865af4158015610288573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ac91906116bf565b915050949350505050565b60606001805480602002602001604051908101604052809291908181526020016000905b828210156103875783829060005260206000200180546102fa9061171b565b80601f01602080910402602001604051908101604052809291908181526020018280546103269061171b565b80156103735780601f1061034857610100808354040283529160200191610373565b820191906000526020600020905b81548152906001019060200180831161035657829003601f168201915b5050505050815260200190600101906102db565b50505050905090565b6002818051602081018201805184825260208301602085012081835280955050505050506000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dc07e20a836040518263ffffffff1660e01b81526004016104369190611154565b602060405180830381865afa158015610453573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104779190611762565b9050919050565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60006104ad826103d9565b90503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461051d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161051490611801565b60405180910390fd5b60008073ffffffffffffffffffffffffffffffffffffffff1660028460405161054691906115ef565b908152602001604051809103902060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415905060001515811515146105d6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105cd9061186d565b60405180910390fd5b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a0fbe58885856040518363ffffffff1660e01b815260040161063492919061188d565b6020604051808303816000875af1158015610653573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106779190611762565b90508060028560405161068a91906115ef565b908152602001604051809103902060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600184908060018154018082558091505060019003906000526020600020016000909190919091509080519060200190610711929190610b47565b5050505050565b6001818154811061072857600080fd5b9060005260206000200160009150905080546107439061171b565b80601f016020809104026020016040519081016040528092919081815260200182805461076f9061171b565b80156107bc5780601f10610791576101008083540402835291602001916107bc565b820191906000526020600020905b81548152906001019060200180831161079f57829003601f168201915b505050505081565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60006107f5836103d9565b905060003373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614905060008073ffffffffffffffffffffffffffffffffffffffff1660028660405161085391906115ef565b908152602001604051809103902060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614159050816108dc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108d390611955565b60405180910390fd5b8061091c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610913906119c1565b60405180910390fd5b60028560405161092c91906115ef565b908152602001604051809103902060006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905560008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060008173ffffffffffffffffffffffffffffffffffffffff1663a0fbe58888306040518363ffffffff1660e01b81526004016109c092919061188d565b6020604051808303816000875af11580156109df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a039190611762565b905080600288604051610a1691906115ef565b908152602001604051809103902060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008190508073ffffffffffffffffffffffffffffffffffffffff1663c1854a57886040518263ffffffff1660e01b8152600401610aa09190611c7d565b600060405180830381600087803b158015610aba57600080fd5b505af1158015610ace573d6000803e3d6000fd5b505050508073ffffffffffffffffffffffffffffffffffffffff1663331a6bf5876040518263ffffffff1660e01b8152600401610b0b919061108c565b600060405180830381600087803b158015610b2557600080fd5b505af1158015610b39573d6000803e3d6000fd5b505050505050505050505050565b828054610b539061171b565b90600052602060002090601f016020900481019282610b755760008555610bbc565b82601f10610b8e57805160ff1916838001178555610bbc565b82800160010185558215610bbc579182015b82811115610bbb578251825591602001919060010190610ba0565b5b509050610bc99190610bcd565b5090565b5b80821115610be6576000816000905550600101610bce565b5090565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b610c5182610c08565b810181811067ffffffffffffffff82111715610c7057610c6f610c19565b5b80604052505050565b6000610c83610bea565b9050610c8f8282610c48565b919050565b600067ffffffffffffffff821115610caf57610cae610c19565b5b610cb882610c08565b9050602081019050919050565b82818337600083830152505050565b6000610ce7610ce284610c94565b610c79565b905082815260208101848484011115610d0357610d02610c03565b5b610d0e848285610cc5565b509392505050565b600082601f830112610d2b57610d2a610bfe565b5b8135610d3b848260208601610cd4565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610d6f82610d44565b9050919050565b610d7f81610d64565b8114610d8a57600080fd5b50565b600081359050610d9c81610d76565b92915050565b600080fd5b600080fd5b60008083601f840112610dc257610dc1610bfe565b5b8235905067ffffffffffffffff811115610ddf57610dde610da2565b5b602083019150836001820283011115610dfb57610dfa610da7565b5b9250929050565b60008060008060608587031215610e1c57610e1b610bf4565b5b600085013567ffffffffffffffff811115610e3a57610e39610bf9565b5b610e4687828801610d16565b9450506020610e5787828801610d8d565b935050604085013567ffffffffffffffff811115610e7857610e77610bf9565b5b610e8487828801610dac565b925092505092959194509250565b60008115159050919050565b610ea781610e92565b82525050565b6000602082019050610ec26000830184610e9e565b92915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600081519050919050565b600082825260208201905092915050565b60005b83811015610f2e578082015181840152602081019050610f13565b83811115610f3d576000848401525b50505050565b6000610f4e82610ef4565b610f588185610eff565b9350610f68818560208601610f10565b610f7181610c08565b840191505092915050565b6000610f888383610f43565b905092915050565b6000602082019050919050565b6000610fa882610ec8565b610fb28185610ed3565b935083602082028501610fc485610ee4565b8060005b858110156110005784840389528151610fe18582610f7c565b9450610fec83610f90565b925060208a01995050600181019050610fc8565b50829750879550505050505092915050565b6000602082019050818103600083015261102c8184610f9d565b905092915050565b60006020828403121561104a57611049610bf4565b5b600082013567ffffffffffffffff81111561106857611067610bf9565b5b61107484828501610d16565b91505092915050565b61108681610d64565b82525050565b60006020820190506110a1600083018461107d565b92915050565b6000819050919050565b6110ba816110a7565b81146110c557600080fd5b50565b6000813590506110d7816110b1565b92915050565b6000602082840312156110f3576110f2610bf4565b5b6000611101848285016110c8565b91505092915050565b600082825260208201905092915050565b600061112682610ef4565b611130818561110a565b9350611140818560208601610f10565b61114981610c08565b840191505092915050565b6000602082019050818103600083015261116e818461111b565b905092915050565b600067ffffffffffffffff82111561119157611190610c19565b5b602082029050602081019050919050565b600080fd5b600080fd5b600067ffffffffffffffff8211156111c7576111c6610c19565b5b602082029050602081019050919050565b60006111eb6111e6846111ac565b610c79565b9050808382526020820190506020840283018581111561120e5761120d610da7565b5b835b8181101561125557803567ffffffffffffffff81111561123357611232610bfe565b5b8086016112408982610d16565b85526020850194505050602081019050611210565b5050509392505050565b600082601f83011261127457611273610bfe565b5b81356112848482602086016111d8565b91505092915050565b600067ffffffffffffffff8211156112a8576112a7610c19565b5b602082029050602081019050919050565b60006112cc6112c78461128d565b610c79565b905080838252602082019050602084028301858111156112ef576112ee610da7565b5b835b8181101561133657803567ffffffffffffffff81111561131457611313610bfe565b5b808601611321898261125f565b855260208501945050506020810190506112f1565b5050509392505050565b600082601f83011261135557611354610bfe565b5b81356113658482602086016112b9565b91505092915050565b600060a08284031215611384576113836111a2565b5b61138e60a0610c79565b9050600082013567ffffffffffffffff8111156113ae576113ad6111a7565b5b6113ba84828501610d16565b600083015250602082013567ffffffffffffffff8111156113de576113dd6111a7565b5b6113ea84828501610d16565b602083015250604082013567ffffffffffffffff81111561140e5761140d6111a7565b5b61141a84828501610d16565b604083015250606082013567ffffffffffffffff81111561143e5761143d6111a7565b5b61144a8482850161125f565b606083015250608082013567ffffffffffffffff81111561146e5761146d6111a7565b5b61147a84828501611340565b60808301525092915050565b600061149961149484611176565b610c79565b905080838252602082019050602084028301858111156114bc576114bb610da7565b5b835b8181101561150357803567ffffffffffffffff8111156114e1576114e0610bfe565b5b8086016114ee898261136e565b855260208501945050506020810190506114be565b5050509392505050565b600082601f83011261152257611521610bfe565b5b8135611532848260208601611486565b91505092915050565b6000806040838503121561155257611551610bf4565b5b600083013567ffffffffffffffff8111156115705761156f610bf9565b5b61157c85828601610d16565b925050602083013567ffffffffffffffff81111561159d5761159c610bf9565b5b6115a98582860161150d565b9150509250929050565b600081905092915050565b60006115c982610ef4565b6115d381856115b3565b93506115e3818560208601610f10565b80840191505092915050565b60006115fb82846115be565b915081905092915050565b61160f81610d64565b82525050565b600082825260208201905092915050565b60006116328385611615565b935061163f838584610cc5565b61164883610c08565b840190509392505050565b60006060820190506116686000830187611606565b6116756020830186611606565b8181036040830152611688818486611626565b905095945050505050565b61169c81610e92565b81146116a757600080fd5b50565b6000815190506116b981611693565b92915050565b6000602082840312156116d5576116d4610bf4565b5b60006116e3848285016116aa565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061173357607f821691505b60208210811415611747576117466116ec565b5b50919050565b60008151905061175c81610d76565b92915050565b60006020828403121561177857611777610bf4565b5b60006117868482850161174d565b91505092915050565b7f4f6e6c792070726f746f636f6c206f776e6572732063616e207265676973746560008201527f722070726f746f636f6c73000000000000000000000000000000000000000000602082015250565b60006117eb602b8361110a565b91506117f68261178f565b604082019050919050565b6000602082019050818103600083015261181a816117de565b9050919050565b7f50726f746f636f6c20697320616c726561647920726567697374657265640000600082015250565b6000611857601e8361110a565b915061186282611821565b602082019050919050565b600060208201905081810360008301526118868161184a565b9050919050565b600060408201905081810360008301526118a7818561111b565b90506118b6602083018461107d565b9392505050565b7f4f6e6c792070726f746f636f6c206f776e6572732063616e207265706c61636560008201527f20746865697220616c6c6f776c69737420776974682061206e657720616c6c6f60208201527f776c697374000000000000000000000000000000000000000000000000000000604082015250565b600061193f60458361110a565b915061194a826118bd565b606082019050919050565b6000602082019050818103600083015261196e81611932565b9050919050565b7f50726f746f636f6c206973206e6f742079657420726567697374657265640000600082015250565b60006119ab601e8361110a565b91506119b682611975565b602082019050919050565b600060208201905081810360008301526119da8161199e565b9050919050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600082825260208201905092915050565b6000611a2982610ec8565b611a338185611a0d565b935083602082028501611a4585610ee4565b8060005b85811015611a815784840389528151611a628582610f7c565b9450611a6d83610f90565b925060208a01995050600181019050611a49565b50829750879550505050505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6000611acb8383611a1e565b905092915050565b6000602082019050919050565b6000611aeb82611a93565b611af58185611a9e565b935083602082028501611b0785611aaf565b8060005b85811015611b435784840389528151611b248582611abf565b9450611b2f83611ad3565b925060208a01995050600181019050611b0b565b50829750879550505050505092915050565b600060a0830160008301518482036000860152611b728282610f43565b91505060208301518482036020860152611b8c8282610f43565b91505060408301518482036040860152611ba68282610f43565b91505060608301518482036060860152611bc08282611a1e565b91505060808301518482036080860152611bda8282611ae0565b9150508091505092915050565b6000611bf38383611b55565b905092915050565b6000602082019050919050565b6000611c13826119e1565b611c1d81856119ec565b935083602082028501611c2f856119fd565b8060005b85811015611c6b5784840389528151611c4c8582611be7565b9450611c5783611bfb565b925060208a01995050600181019050611c33565b50829750879550505050505092915050565b60006020820190508181036000830152611c978184611c08565b90509291505056fea2646970667358221220e065b48c9438d850d390ad6d20857e40e10879d39856e239bbe33194043cea1d64736f6c634300080b0033000000000000000000000000687d43df83a535944709b057e33ca632dee511d9000000000000000000000000ef8e447bd63fd3c1eec349cf4d1dce19be7a807c

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000687d43df83a535944709b057e33ca632dee511d9000000000000000000000000ef8e447bd63fd3c1eec349cf4d1dce19be7a807c

-----Decoded View---------------
Arg [0] : _factoryAddress (address): 0x687d43df83a535944709b057e33ca632dee511d9
Arg [1] : _protocolOwnershipAddress (address): 0xef8e447bd63fd3c1eec349cf4d1dce19be7a807c

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000687d43df83a535944709b057e33ca632dee511d9
Arg [1] : 000000000000000000000000ef8e447bd63fd3c1eec349cf4d1dce19be7a807c


Library Used

CalldataValidation : 0xc4fa9d2440482b4fead00748d33186f7b0539098

Deployed ByteCode Sourcemap

648:4750:1:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5038:358;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3118:110;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;824:62;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1515:226;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;679:29;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;2166:879;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;712:35;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;932:39;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3458:1237;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;5038:358;5179:12;5199:24;5226:28;5255:10;5226:40;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;5199:67;;5282:18;:46;5336:16;5360:13;5381:4;;5282:109;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5272:119;;5193:203;5038:358;;;;;;:::o;3118:110::-;3174:15;3204:19;3197:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3118:110;:::o;824:62::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;1515:226::-;1616:20;1680:24;;;;;;;;;;;1661:63;;;1725:10;1661:75;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1646:90;;1515:226;;;:::o;679:29::-;;;;;;;;;;;;:::o;2166:879::-;2273:28;2304:44;2337:10;2304:32;:44::i;:::-;2273:75;;2393:10;2369:34;;:20;:34;;;2354:108;;;;;;;;;;;;:::i;:::-;;;;;;;;;2521:32;2620:1;2556:66;;:28;2592:10;2556:52;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;:66;;;;2521:101;;2674:5;2643:36;;:27;:36;;;2628:97;;;;;;;;;;;;:::i;:::-;;;;;;;;;2780:24;2825:14;;;;;;;;;;;2807:48;;;2863:10;2881:20;2807:100;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;2780:127;;2956:16;2913:28;2942:10;2913:40;;;;;;:::i;:::-;;;;;;;;;;;;;;:59;;;;;;;;;;;;;;;;;;3004:19;3029:10;3004:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;2225:820;;;2166:879;:::o;712:35::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;932:39::-;;;;;;;;;;;;;:::o;3458:1237::-;3579:28;3610:44;3643:10;3610:32;:44::i;:::-;3579:75;;3660:26;3713:10;3689:34;;:20;:34;;;3660:63;;3729:25;3815:1;3757:60;;:28;3786:10;3757:40;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;:60;;;;3729:88;;3873:21;3858:121;;;;;;;;;;;;:::i;:::-;;;;;;;;;4043:20;4035:63;;;;;;;;;;;;:::i;:::-;;;;;;;;;4145:28;4174:10;4145:40;;;;;;:::i;:::-;;;;;;;;;;;;;;4138:47;;;;;;;;;;;4243:34;4298:14;;;;;;;;;;;4243:70;;4319:24;4346:16;:31;;;4385:10;4411:4;4346:76;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;4319:103;;4471:16;4428:28;4457:10;4428:40;;;;;;:::i;:::-;;;;;;;;;;;;;;:59;;;;;;;;;;;;;;;;;;4533:20;4567:16;4533:51;;4590:9;:23;;;4614:10;4590:35;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4642:9;4631:37;;;4669:20;4631:59;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3573:1122;;;;;;3458:1237;;:::o;-1:-1:-1:-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;:::o;7:75:6:-;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:117;443:1;440;433:12;457:117;566:1;563;556:12;580:102;621:6;672:2;668:7;663:2;656:5;652:14;648:28;638:38;;580:102;;;:::o;688:180::-;736:77;733:1;726:88;833:4;830:1;823:15;857:4;854:1;847:15;874:281;957:27;979:4;957:27;:::i;:::-;949:6;945:40;1087:6;1075:10;1072:22;1051:18;1039:10;1036:34;1033:62;1030:88;;;1098:18;;:::i;:::-;1030:88;1138:10;1134:2;1127:22;917:238;874:281;;:::o;1161:129::-;1195:6;1222:20;;:::i;:::-;1212:30;;1251:33;1279:4;1271:6;1251:33;:::i;:::-;1161:129;;;:::o;1296:308::-;1358:4;1448:18;1440:6;1437:30;1434:56;;;1470:18;;:::i;:::-;1434:56;1508:29;1530:6;1508:29;:::i;:::-;1500:37;;1592:4;1586;1582:15;1574:23;;1296:308;;;:::o;1610:154::-;1694:6;1689:3;1684;1671:30;1756:1;1747:6;1742:3;1738:16;1731:27;1610:154;;;:::o;1770:412::-;1848:5;1873:66;1889:49;1931:6;1889:49;:::i;:::-;1873:66;:::i;:::-;1864:75;;1962:6;1955:5;1948:21;2000:4;1993:5;1989:16;2038:3;2029:6;2024:3;2020:16;2017:25;2014:112;;;2045:79;;:::i;:::-;2014:112;2135:41;2169:6;2164:3;2159;2135:41;:::i;:::-;1854:328;1770:412;;;;;:::o;2202:340::-;2258:5;2307:3;2300:4;2292:6;2288:17;2284:27;2274:122;;2315:79;;:::i;:::-;2274:122;2432:6;2419:20;2457:79;2532:3;2524:6;2517:4;2509:6;2505:17;2457:79;:::i;:::-;2448:88;;2264:278;2202:340;;;;:::o;2548:126::-;2585:7;2625:42;2618:5;2614:54;2603:65;;2548:126;;;:::o;2680:96::-;2717:7;2746:24;2764:5;2746:24;:::i;:::-;2735:35;;2680:96;;;:::o;2782:122::-;2855:24;2873:5;2855:24;:::i;:::-;2848:5;2845:35;2835:63;;2894:1;2891;2884:12;2835:63;2782:122;:::o;2910:139::-;2956:5;2994:6;2981:20;2972:29;;3010:33;3037:5;3010:33;:::i;:::-;2910:139;;;;:::o;3055:117::-;3164:1;3161;3154:12;3178:117;3287:1;3284;3277:12;3314:552;3371:8;3381:6;3431:3;3424:4;3416:6;3412:17;3408:27;3398:122;;3439:79;;:::i;:::-;3398:122;3552:6;3539:20;3529:30;;3582:18;3574:6;3571:30;3568:117;;;3604:79;;:::i;:::-;3568:117;3718:4;3710:6;3706:17;3694:29;;3772:3;3764:4;3756:6;3752:17;3742:8;3738:32;3735:41;3732:128;;;3779:79;;:::i;:::-;3732:128;3314:552;;;;;:::o;3872:997::-;3970:6;3978;3986;3994;4043:2;4031:9;4022:7;4018:23;4014:32;4011:119;;;4049:79;;:::i;:::-;4011:119;4197:1;4186:9;4182:17;4169:31;4227:18;4219:6;4216:30;4213:117;;;4249:79;;:::i;:::-;4213:117;4354:63;4409:7;4400:6;4389:9;4385:22;4354:63;:::i;:::-;4344:73;;4140:287;4466:2;4492:53;4537:7;4528:6;4517:9;4513:22;4492:53;:::i;:::-;4482:63;;4437:118;4622:2;4611:9;4607:18;4594:32;4653:18;4645:6;4642:30;4639:117;;;4675:79;;:::i;:::-;4639:117;4788:64;4844:7;4835:6;4824:9;4820:22;4788:64;:::i;:::-;4770:82;;;;4565:297;3872:997;;;;;;;:::o;4875:90::-;4909:7;4952:5;4945:13;4938:21;4927:32;;4875:90;;;:::o;4971:109::-;5052:21;5067:5;5052:21;:::i;:::-;5047:3;5040:34;4971:109;;:::o;5086:210::-;5173:4;5211:2;5200:9;5196:18;5188:26;;5224:65;5286:1;5275:9;5271:17;5262:6;5224:65;:::i;:::-;5086:210;;;;:::o;5302:124::-;5379:6;5413:5;5407:12;5397:22;;5302:124;;;:::o;5432:194::-;5541:11;5575:6;5570:3;5563:19;5615:4;5610:3;5606:14;5591:29;;5432:194;;;;:::o;5632:142::-;5709:4;5732:3;5724:11;;5762:4;5757:3;5753:14;5745:22;;5632:142;;;:::o;5780:99::-;5832:6;5866:5;5860:12;5850:22;;5780:99;;;:::o;5885:159::-;5959:11;5993:6;5988:3;5981:19;6033:4;6028:3;6024:14;6009:29;;5885:159;;;;:::o;6050:307::-;6118:1;6128:113;6142:6;6139:1;6136:13;6128:113;;;6227:1;6222:3;6218:11;6212:18;6208:1;6203:3;6199:11;6192:39;6164:2;6161:1;6157:10;6152:15;;6128:113;;;6259:6;6256:1;6253:13;6250:101;;;6339:1;6330:6;6325:3;6321:16;6314:27;6250:101;6099:258;6050:307;;;:::o;6363:344::-;6441:3;6469:39;6502:5;6469:39;:::i;:::-;6524:61;6578:6;6573:3;6524:61;:::i;:::-;6517:68;;6594:52;6639:6;6634:3;6627:4;6620:5;6616:16;6594:52;:::i;:::-;6671:29;6693:6;6671:29;:::i;:::-;6666:3;6662:39;6655:46;;6445:262;6363:344;;;;:::o;6713:196::-;6802:10;6837:66;6899:3;6891:6;6837:66;:::i;:::-;6823:80;;6713:196;;;;:::o;6915:123::-;6995:4;7027;7022:3;7018:14;7010:22;;6915:123;;;:::o;7072:991::-;7211:3;7240:64;7298:5;7240:64;:::i;:::-;7320:96;7409:6;7404:3;7320:96;:::i;:::-;7313:103;;7442:3;7487:4;7479:6;7475:17;7470:3;7466:27;7517:66;7577:5;7517:66;:::i;:::-;7606:7;7637:1;7622:396;7647:6;7644:1;7641:13;7622:396;;;7718:9;7712:4;7708:20;7703:3;7696:33;7769:6;7763:13;7797:84;7876:4;7861:13;7797:84;:::i;:::-;7789:92;;7904:70;7967:6;7904:70;:::i;:::-;7894:80;;8003:4;7998:3;7994:14;7987:21;;7682:336;7669:1;7666;7662:9;7657:14;;7622:396;;;7626:14;8034:4;8027:11;;8054:3;8047:10;;7216:847;;;;;7072:991;;;;:::o;8069:413::-;8232:4;8270:2;8259:9;8255:18;8247:26;;8319:9;8313:4;8309:20;8305:1;8294:9;8290:17;8283:47;8347:128;8470:4;8461:6;8347:128;:::i;:::-;8339:136;;8069:413;;;;:::o;8488:509::-;8557:6;8606:2;8594:9;8585:7;8581:23;8577:32;8574:119;;;8612:79;;:::i;:::-;8574:119;8760:1;8749:9;8745:17;8732:31;8790:18;8782:6;8779:30;8776:117;;;8812:79;;:::i;:::-;8776:117;8917:63;8972:7;8963:6;8952:9;8948:22;8917:63;:::i;:::-;8907:73;;8703:287;8488:509;;;;:::o;9003:118::-;9090:24;9108:5;9090:24;:::i;:::-;9085:3;9078:37;9003:118;;:::o;9127:222::-;9220:4;9258:2;9247:9;9243:18;9235:26;;9271:71;9339:1;9328:9;9324:17;9315:6;9271:71;:::i;:::-;9127:222;;;;:::o;9355:77::-;9392:7;9421:5;9410:16;;9355:77;;;:::o;9438:122::-;9511:24;9529:5;9511:24;:::i;:::-;9504:5;9501:35;9491:63;;9550:1;9547;9540:12;9491:63;9438:122;:::o;9566:139::-;9612:5;9650:6;9637:20;9628:29;;9666:33;9693:5;9666:33;:::i;:::-;9566:139;;;;:::o;9711:329::-;9770:6;9819:2;9807:9;9798:7;9794:23;9790:32;9787:119;;;9825:79;;:::i;:::-;9787:119;9945:1;9970:53;10015:7;10006:6;9995:9;9991:22;9970:53;:::i;:::-;9960:63;;9916:117;9711:329;;;;:::o;10046:169::-;10130:11;10164:6;10159:3;10152:19;10204:4;10199:3;10195:14;10180:29;;10046:169;;;;:::o;10221:364::-;10309:3;10337:39;10370:5;10337:39;:::i;:::-;10392:71;10456:6;10451:3;10392:71;:::i;:::-;10385:78;;10472:52;10517:6;10512:3;10505:4;10498:5;10494:16;10472:52;:::i;:::-;10549:29;10571:6;10549:29;:::i;:::-;10544:3;10540:39;10533:46;;10313:272;10221:364;;;;:::o;10591:313::-;10704:4;10742:2;10731:9;10727:18;10719:26;;10791:9;10785:4;10781:20;10777:1;10766:9;10762:17;10755:47;10819:78;10892:4;10883:6;10819:78;:::i;:::-;10811:86;;10591:313;;;;:::o;10910:338::-;11014:4;11104:18;11096:6;11093:30;11090:56;;;11126:18;;:::i;:::-;11090:56;11176:4;11168:6;11164:17;11156:25;;11236:4;11230;11226:15;11218:23;;10910:338;;;:::o;11254:117::-;11363:1;11360;11353:12;11377:117;11486:1;11483;11476:12;11500:321;11587:4;11677:18;11669:6;11666:30;11663:56;;;11699:18;;:::i;:::-;11663:56;11749:4;11741:6;11737:17;11729:25;;11809:4;11803;11799:15;11791:23;;11500:321;;;:::o;11843:945::-;11949:5;11974:91;11990:74;12057:6;11990:74;:::i;:::-;11974:91;:::i;:::-;11965:100;;12085:5;12114:6;12107:5;12100:21;12148:4;12141:5;12137:16;12130:23;;12201:4;12193:6;12189:17;12181:6;12177:30;12230:3;12222:6;12219:15;12216:122;;;12249:79;;:::i;:::-;12216:122;12364:6;12347:435;12381:6;12376:3;12373:15;12347:435;;;12470:3;12457:17;12506:18;12493:11;12490:35;12487:122;;;12528:79;;:::i;:::-;12487:122;12652:11;12644:6;12640:24;12690:47;12733:3;12721:10;12690:47;:::i;:::-;12685:3;12678:60;12767:4;12762:3;12758:14;12751:21;;12423:359;;12407:4;12402:3;12398:14;12391:21;;12347:435;;;12351:21;11955:833;;11843:945;;;;;:::o;12810:390::-;12891:5;12940:3;12933:4;12925:6;12921:17;12917:27;12907:122;;12948:79;;:::i;:::-;12907:122;13065:6;13052:20;13090:104;13190:3;13182:6;13175:4;13167:6;13163:17;13090:104;:::i;:::-;13081:113;;12897:303;12810:390;;;;:::o;13206:346::-;13318:4;13408:18;13400:6;13397:30;13394:56;;;13430:18;;:::i;:::-;13394:56;13480:4;13472:6;13468:17;13460:25;;13540:4;13534;13530:15;13522:23;;13206:346;;;:::o;13576:1020::-;13707:5;13732:116;13748:99;13840:6;13748:99;:::i;:::-;13732:116;:::i;:::-;13723:125;;13868:5;13897:6;13890:5;13883:21;13931:4;13924:5;13920:16;13913:23;;13984:4;13976:6;13972:17;13964:6;13960:30;14013:3;14005:6;14002:15;13999:122;;;14032:79;;:::i;:::-;13999:122;14147:6;14130:460;14164:6;14159:3;14156:15;14130:460;;;14253:3;14240:17;14289:18;14276:11;14273:35;14270:122;;;14311:79;;:::i;:::-;14270:122;14435:11;14427:6;14423:24;14473:72;14541:3;14529:10;14473:72;:::i;:::-;14468:3;14461:85;14575:4;14570:3;14566:14;14559:21;;14206:384;;14190:4;14185:3;14181:14;14174:21;;14130:460;;;14134:21;13713:883;;13576:1020;;;;;:::o;14620:440::-;14726:5;14775:3;14768:4;14760:6;14756:17;14752:27;14742:122;;14783:79;;:::i;:::-;14742:122;14900:6;14887:20;14925:129;15050:3;15042:6;15035:4;15027:6;15023:17;14925:129;:::i;:::-;14916:138;;14732:328;14620:440;;;;:::o;15101:2015::-;15177:5;15221:4;15209:9;15204:3;15200:19;15196:30;15193:117;;;15229:79;;:::i;:::-;15193:117;15328:21;15344:4;15328:21;:::i;:::-;15319:30;;15434:1;15423:9;15419:17;15406:31;15464:18;15456:6;15453:30;15450:117;;;15486:79;;:::i;:::-;15450:117;15606:59;15661:3;15652:6;15641:9;15637:22;15606:59;:::i;:::-;15599:4;15592:5;15588:16;15581:85;15359:318;15776:2;15765:9;15761:18;15748:32;15807:18;15799:6;15796:30;15793:117;;;15829:79;;:::i;:::-;15793:117;15949:59;16004:3;15995:6;15984:9;15980:22;15949:59;:::i;:::-;15942:4;15935:5;15931:16;15924:85;15687:333;16113:2;16102:9;16098:18;16085:32;16144:18;16136:6;16133:30;16130:117;;;16166:79;;:::i;:::-;16130:117;16286:59;16341:3;16332:6;16321:9;16317:22;16286:59;:::i;:::-;16279:4;16272:5;16268:16;16261:85;16030:327;16450:2;16439:9;16435:18;16422:32;16481:18;16473:6;16470:30;16467:117;;;16503:79;;:::i;:::-;16467:117;16623:84;16703:3;16694:6;16683:9;16679:22;16623:84;:::i;:::-;16616:4;16609:5;16605:16;16598:110;16367:352;16814:3;16803:9;16799:19;16786:33;16846:18;16838:6;16835:30;16832:117;;;16868:79;;:::i;:::-;16832:117;16988:109;17093:3;17084:6;17073:9;17069:22;16988:109;:::i;:::-;16981:4;16974:5;16970:16;16963:135;16729:380;15101:2015;;;;:::o;17159:996::-;17282:5;17307:108;17323:91;17407:6;17323:91;:::i;:::-;17307:108;:::i;:::-;17298:117;;17435:5;17464:6;17457:5;17450:21;17498:4;17491:5;17487:16;17480:23;;17551:4;17543:6;17539:17;17531:6;17527:30;17580:3;17572:6;17569:15;17566:122;;;17599:79;;:::i;:::-;17566:122;17714:6;17697:452;17731:6;17726:3;17723:15;17697:452;;;17820:3;17807:17;17856:18;17843:11;17840:35;17837:122;;;17878:79;;:::i;:::-;17837:122;18002:11;17994:6;17990:24;18040:64;18100:3;18088:10;18040:64;:::i;:::-;18035:3;18028:77;18134:4;18129:3;18125:14;18118:21;;17773:376;;17757:4;17752:3;17748:14;17741:21;;17697:452;;;17701:21;17288:867;;17159:996;;;;;:::o;18198:424::-;18296:5;18345:3;18338:4;18330:6;18326:17;18322:27;18312:122;;18353:79;;:::i;:::-;18312:122;18470:6;18457:20;18495:121;18612:3;18604:6;18597:4;18589:6;18585:17;18495:121;:::i;:::-;18486:130;;18302:320;18198:424;;;;:::o;18628:918::-;18758:6;18766;18815:2;18803:9;18794:7;18790:23;18786:32;18783:119;;;18821:79;;:::i;:::-;18783:119;18969:1;18958:9;18954:17;18941:31;18999:18;18991:6;18988:30;18985:117;;;19021:79;;:::i;:::-;18985:117;19126:63;19181:7;19172:6;19161:9;19157:22;19126:63;:::i;:::-;19116:73;;18912:287;19266:2;19255:9;19251:18;19238:32;19297:18;19289:6;19286:30;19283:117;;;19319:79;;:::i;:::-;19283:117;19424:105;19521:7;19512:6;19501:9;19497:22;19424:105;:::i;:::-;19414:115;;19209:330;18628:918;;;;;:::o;19552:148::-;19654:11;19691:3;19676:18;;19552:148;;;;:::o;19706:377::-;19812:3;19840:39;19873:5;19840:39;:::i;:::-;19895:89;19977:6;19972:3;19895:89;:::i;:::-;19888:96;;19993:52;20038:6;20033:3;20026:4;20019:5;20015:16;19993:52;:::i;:::-;20070:6;20065:3;20061:16;20054:23;;19816:267;19706:377;;;;:::o;20089:275::-;20221:3;20243:95;20334:3;20325:6;20243:95;:::i;:::-;20236:102;;20355:3;20348:10;;20089:275;;;;:::o;20370:126::-;20465:24;20483:5;20465:24;:::i;:::-;20460:3;20453:37;20370:126;;:::o;20502:176::-;20593:11;20627:6;20622:3;20615:19;20667:4;20662:3;20658:14;20643:29;;20502:176;;;;:::o;20706:317::-;20810:3;20831:78;20902:6;20897:3;20831:78;:::i;:::-;20824:85;;20919:43;20955:6;20950:3;20943:5;20919:43;:::i;:::-;20987:29;21009:6;20987:29;:::i;:::-;20982:3;20978:39;20971:46;;20706:317;;;;;:::o;21029:581::-;21214:4;21252:2;21241:9;21237:18;21229:26;;21265:79;21341:1;21330:9;21326:17;21317:6;21265:79;:::i;:::-;21354:80;21430:2;21419:9;21415:18;21406:6;21354:80;:::i;:::-;21481:9;21475:4;21471:20;21466:2;21455:9;21451:18;21444:48;21509:94;21598:4;21589:6;21581;21509:94;:::i;:::-;21501:102;;21029:581;;;;;;;:::o;21616:116::-;21686:21;21701:5;21686:21;:::i;:::-;21679:5;21676:32;21666:60;;21722:1;21719;21712:12;21666:60;21616:116;:::o;21738:137::-;21792:5;21823:6;21817:13;21808:22;;21839:30;21863:5;21839:30;:::i;:::-;21738:137;;;;:::o;21881:345::-;21948:6;21997:2;21985:9;21976:7;21972:23;21968:32;21965:119;;;22003:79;;:::i;:::-;21965:119;22123:1;22148:61;22201:7;22192:6;22181:9;22177:22;22148:61;:::i;:::-;22138:71;;22094:125;21881:345;;;;:::o;22232:180::-;22280:77;22277:1;22270:88;22377:4;22374:1;22367:15;22401:4;22398:1;22391:15;22418:320;22462:6;22499:1;22493:4;22489:12;22479:22;;22546:1;22540:4;22536:12;22567:18;22557:81;;22623:4;22615:6;22611:17;22601:27;;22557:81;22685:2;22677:6;22674:14;22654:18;22651:38;22648:84;;;22704:18;;:::i;:::-;22648:84;22469:269;22418:320;;;:::o;22744:143::-;22801:5;22832:6;22826:13;22817:22;;22848:33;22875:5;22848:33;:::i;:::-;22744:143;;;;:::o;22893:351::-;22963:6;23012:2;23000:9;22991:7;22987:23;22983:32;22980:119;;;23018:79;;:::i;:::-;22980:119;23138:1;23163:64;23219:7;23210:6;23199:9;23195:22;23163:64;:::i;:::-;23153:74;;23109:128;22893:351;;;;:::o;23250:230::-;23390:34;23386:1;23378:6;23374:14;23367:58;23459:13;23454:2;23446:6;23442:15;23435:38;23250:230;:::o;23486:366::-;23628:3;23649:67;23713:2;23708:3;23649:67;:::i;:::-;23642:74;;23725:93;23814:3;23725:93;:::i;:::-;23843:2;23838:3;23834:12;23827:19;;23486:366;;;:::o;23858:419::-;24024:4;24062:2;24051:9;24047:18;24039:26;;24111:9;24105:4;24101:20;24097:1;24086:9;24082:17;24075:47;24139:131;24265:4;24139:131;:::i;:::-;24131:139;;23858:419;;;:::o;24283:180::-;24423:32;24419:1;24411:6;24407:14;24400:56;24283:180;:::o;24469:366::-;24611:3;24632:67;24696:2;24691:3;24632:67;:::i;:::-;24625:74;;24708:93;24797:3;24708:93;:::i;:::-;24826:2;24821:3;24817:12;24810:19;;24469:366;;;:::o;24841:419::-;25007:4;25045:2;25034:9;25030:18;25022:26;;25094:9;25088:4;25084:20;25080:1;25069:9;25065:17;25058:47;25122:131;25248:4;25122:131;:::i;:::-;25114:139;;24841:419;;;:::o;25266:423::-;25407:4;25445:2;25434:9;25430:18;25422:26;;25494:9;25488:4;25484:20;25480:1;25469:9;25465:17;25458:47;25522:78;25595:4;25586:6;25522:78;:::i;:::-;25514:86;;25610:72;25678:2;25667:9;25663:18;25654:6;25610:72;:::i;:::-;25266:423;;;;;:::o;25695:293::-;25835:34;25831:1;25823:6;25819:14;25812:58;25904:34;25899:2;25891:6;25887:15;25880:59;25973:7;25968:2;25960:6;25956:15;25949:32;25695:293;:::o;25994:366::-;26136:3;26157:67;26221:2;26216:3;26157:67;:::i;:::-;26150:74;;26233:93;26322:3;26233:93;:::i;:::-;26351:2;26346:3;26342:12;26335:19;;25994:366;;;:::o;26366:419::-;26532:4;26570:2;26559:9;26555:18;26547:26;;26619:9;26613:4;26609:20;26605:1;26594:9;26590:17;26583:47;26647:131;26773:4;26647:131;:::i;:::-;26639:139;;26366:419;;;:::o;26791:180::-;26931:32;26927:1;26919:6;26915:14;26908:56;26791:180;:::o;26977:366::-;27119:3;27140:67;27204:2;27199:3;27140:67;:::i;:::-;27133:74;;27216:93;27305:3;27216:93;:::i;:::-;27334:2;27329:3;27325:12;27318:19;;26977:366;;;:::o;27349:419::-;27515:4;27553:2;27542:9;27538:18;27530:26;;27602:9;27596:4;27592:20;27588:1;27577:9;27573:17;27566:47;27630:131;27756:4;27630:131;:::i;:::-;27622:139;;27349:419;;;:::o;27774:141::-;27868:6;27902:5;27896:12;27886:22;;27774:141;;;:::o;27921:211::-;28047:11;28081:6;28076:3;28069:19;28121:4;28116:3;28112:14;28097:29;;27921:211;;;;:::o;28138:159::-;28232:4;28255:3;28247:11;;28285:4;28280:3;28276:14;28268:22;;28138:159;;;:::o;28303:184::-;28402:11;28436:6;28431:3;28424:19;28476:4;28471:3;28467:14;28452:29;;28303:184;;;;:::o;28521:971::-;28650:3;28679:64;28737:5;28679:64;:::i;:::-;28759:86;28838:6;28833:3;28759:86;:::i;:::-;28752:93;;28871:3;28916:4;28908:6;28904:17;28899:3;28895:27;28946:66;29006:5;28946:66;:::i;:::-;29035:7;29066:1;29051:396;29076:6;29073:1;29070:13;29051:396;;;29147:9;29141:4;29137:20;29132:3;29125:33;29198:6;29192:13;29226:84;29305:4;29290:13;29226:84;:::i;:::-;29218:92;;29333:70;29396:6;29333:70;:::i;:::-;29323:80;;29432:4;29427:3;29423:14;29416:21;;29111:336;29098:1;29095;29091:9;29086:14;;29051:396;;;29055:14;29463:4;29456:11;;29483:3;29476:10;;28655:837;;;;;28521:971;;;;:::o;29498:149::-;29600:6;29634:5;29628:12;29618:22;;29498:149;;;:::o;29653:209::-;29777:11;29811:6;29806:3;29799:19;29851:4;29846:3;29842:14;29827:29;;29653:209;;;;:::o;29868:167::-;29970:4;29993:3;29985:11;;30023:4;30018:3;30014:14;30006:22;;29868:167;;;:::o;30041:296::-;30180:10;30215:116;30327:3;30319:6;30215:116;:::i;:::-;30201:130;;30041:296;;;;:::o;30343:148::-;30448:4;30480;30475:3;30471:14;30463:22;;30343:148;;;:::o;30529:1171::-;30708:3;30737:89;30820:5;30737:89;:::i;:::-;30842:111;30946:6;30941:3;30842:111;:::i;:::-;30835:118;;30979:3;31024:4;31016:6;31012:17;31007:3;31003:27;31054:91;31139:5;31054:91;:::i;:::-;31168:7;31199:1;31184:471;31209:6;31206:1;31203:13;31184:471;;;31280:9;31274:4;31270:20;31265:3;31258:33;31331:6;31325:13;31359:134;31488:4;31473:13;31359:134;:::i;:::-;31351:142;;31516:95;31604:6;31516:95;:::i;:::-;31506:105;;31640:4;31635:3;31631:14;31624:21;;31244:411;31231:1;31228;31224:9;31219:14;;31184:471;;;31188:14;31671:4;31664:11;;31691:3;31684:10;;30713:987;;;;;30529:1171;;;;:::o;31772:1586::-;31885:3;31921:4;31916:3;31912:14;32006:4;31999:5;31995:16;31989:23;32059:3;32053:4;32049:14;32042:4;32037:3;32033:14;32026:38;32085:73;32153:4;32139:12;32085:73;:::i;:::-;32077:81;;31936:233;32263:4;32256:5;32252:16;32246:23;32316:3;32310:4;32306:14;32299:4;32294:3;32290:14;32283:38;32342:73;32410:4;32396:12;32342:73;:::i;:::-;32334:81;;32179:247;32514:4;32507:5;32503:16;32497:23;32567:3;32561:4;32557:14;32550:4;32545:3;32541:14;32534:38;32593:73;32661:4;32647:12;32593:73;:::i;:::-;32585:81;;32436:241;32765:4;32758:5;32754:16;32748:23;32818:3;32812:4;32808:14;32801:4;32796:3;32792:14;32785:38;32844:123;32962:4;32948:12;32844:123;:::i;:::-;32836:131;;32687:291;33068:4;33061:5;33057:16;33051:23;33121:3;33115:4;33111:14;33104:4;33099:3;33095:14;33088:38;33147:173;33315:4;33301:12;33147:173;:::i;:::-;33139:181;;32988:343;33348:4;33341:11;;31890:1468;31772:1586;;;;:::o;33364:264::-;33487:10;33522:100;33618:3;33610:6;33522:100;:::i;:::-;33508:114;;33364:264;;;;:::o;33634:140::-;33731:4;33763;33758:3;33754:14;33746:22;;33634:140;;;:::o;33850:1127::-;34023:3;34052:81;34127:5;34052:81;:::i;:::-;34149:113;34255:6;34250:3;34149:113;:::i;:::-;34142:120;;34288:3;34333:4;34325:6;34321:17;34316:3;34312:27;34363:83;34440:5;34363:83;:::i;:::-;34469:7;34500:1;34485:447;34510:6;34507:1;34504:13;34485:447;;;34581:9;34575:4;34571:20;34566:3;34559:33;34632:6;34626:13;34660:118;34773:4;34758:13;34660:118;:::i;:::-;34652:126;;34801:87;34881:6;34801:87;:::i;:::-;34791:97;;34917:4;34912:3;34908:14;34901:21;;34545:387;34532:1;34529;34525:9;34520:14;;34485:447;;;34489:14;34948:4;34941:11;;34968:3;34961:10;;34028:949;;;;;33850:1127;;;;:::o;34983:481::-;35180:4;35218:2;35207:9;35203:18;35195:26;;35267:9;35261:4;35257:20;35253:1;35242:9;35238:17;35231:47;35295:162;35452:4;35443:6;35295:162;:::i;:::-;35287:170;;34983:481;;;;:::o

Swarm Source

ipfs://e065b48c9438d850d390ad6d20857e40e10879d39856e239bbe33194043cea1d
Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Validator ID :
0 FTM

Amount Staked
0

Amount Delegated
0

Staking Total
0

Staking Start Epoch
0

Staking Start Time
0

Proof of Importance
0

Origination Score
0

Validation Score
0

Active
0

Online
0

Downtime
0 s
Address Amount claimed Rewards Created On Epoch Created On
Block Uncle Number Difficulty Gas Used Reward
Loading
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.