ETH Price: $2,431.89 (+0.38%)

Token

Liquid Staked ETH (LsETH)
 

Overview

Max Total Supply

0 LsETH

Holders

0

Total Transfers

-

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 18 Decimals)

Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information
# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
RiverV1

Compiler Version
v0.8.10+commit.fc410830

Optimization Enabled:
Yes with 100 runs

Other Settings:
default evmVersion, BSL 1.1 license
File 1 of 45 : River.1.sol
//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.10;

import "./interfaces/IAllowlist.1.sol";
import "./interfaces/IOperatorRegistry.1.sol";
import "./interfaces/IRiver.1.sol";
import "./interfaces/IELFeeRecipient.1.sol";

import "./components/ConsensusLayerDepositManager.1.sol";
import "./components/UserDepositManager.1.sol";
import "./components/SharesManager.1.sol";
import "./components/OracleManager.1.sol";
import "./Initializable.sol";
import "./Administrable.sol";

import "./state/river/AllowlistAddress.sol";
import "./state/river/OperatorsRegistryAddress.sol";
import "./state/river/CollectorAddress.sol";
import "./state/river/GlobalFee.sol";
import "./state/river/ELFeeRecipientAddress.sol";

/// @title River (v1)
/// @author Kiln
/// @notice This contract merges all the manager contracts and implements all the virtual methods stitching all components together
/// @notice
/// @notice    +---------------------------------------------------------------------+
/// @notice    |                                                                     |
/// @notice    |                           Consensus Layer                           |
/// @notice    |                                                                     |
/// @notice    | +-------------------+  +-------------------+  +-------------------+ |
/// @notice    | |                   |  |                   |  |                   | |
/// @notice    | |  EL Fee Recipient |  |      Oracle       |  |  Deposit Contract | |
/// @notice    | |                   |  |                   |  |                   | |
/// @notice    | +---------|---------+  +---------|---------+  +---------|---------+ |
/// @notice    +---------------------------------------------------------------------+
/// @notice                |         7            |            5         |
/// @notice                +-----------------|    |    |-----------------+
/// @notice                                  |    |6   |
/// @notice                                  |    |    |
/// @notice        +---------+          +----|----|----|----+            +---------+
/// @notice        |         |          |                   |     2      |         |
/// @notice        |Operator |          |       River       --------------  User   |
/// @notice        |         |          |                   |            |         |
/// @notice        +----|----+          +----|---------|----+            +---------+
/// @notice             |                    |         |
/// @notice             |             4      |         |       3
/// @notice             |1     +-------------|         |--------------+
/// @notice             |      |                                      |
/// @notice             |      |                                      |
/// @notice      +------|------|------------+           +-------------|------------+
/// @notice      |                          |           |                          |
/// @notice      |    Operators Registry    |           |         Allowlist        |
/// @notice      |                          |           |                          |
/// @notice      +--------------------------+           +--------------------------+
/// @notice
/// @notice      1. Operators are adding BLS Public Keys of validators running in their
/// @notice         infrastructure.
/// @notice      2. User deposit ETH to the system and get shares minted in exchange
/// @notice      3. Upon deposit, the system verifies if the User is allowed to deposit
/// @notice         by querying the Allowlist
/// @notice      4. When the system has enough funds to deposit validators, keys are pulled
/// @notice         from the Operators Registry
/// @notice      5. The deposit data is computed and the validators are funded via the official
/// @notice         deposit contract
/// @notice      6. Oracles report the total balance of the running validators and the total count
/// @notice         of running validators
/// @notice      7. The running validators propose blocks that reward the EL Fee Recipient. The funds
/// @notice         are pulled back in the system.
/// @notice
contract RiverV1 is
    ConsensusLayerDepositManagerV1,
    UserDepositManagerV1,
    SharesManagerV1,
    OracleManagerV1,
    Initializable,
    Administrable,
    IRiverV1
{
    /// @notice The mask for the deposit right
    uint256 internal constant DEPOSIT_MASK = 0x1;

    /// @inheritdoc IRiverV1
    function initRiverV1(
        address _depositContractAddress,
        address _elFeeRecipientAddress,
        bytes32 _withdrawalCredentials,
        address _oracleAddress,
        address _systemAdministratorAddress,
        address _allowlistAddress,
        address _operatorRegistryAddress,
        address _collectorAddress,
        uint256 _globalFee
    ) external init(0) {
        _setAdmin(_systemAdministratorAddress);

        CollectorAddress.set(_collectorAddress);
        emit SetCollector(_collectorAddress);

        GlobalFee.set(_globalFee);
        emit SetGlobalFee(_globalFee);

        ELFeeRecipientAddress.set(_elFeeRecipientAddress);
        emit SetELFeeRecipient(_elFeeRecipientAddress);

        AllowlistAddress.set(_allowlistAddress);
        emit SetAllowlist(_allowlistAddress);

        OperatorsRegistryAddress.set(_operatorRegistryAddress);
        emit SetOperatorsRegistry(_operatorRegistryAddress);

        ConsensusLayerDepositManagerV1.initConsensusLayerDepositManagerV1(
            _depositContractAddress, _withdrawalCredentials
        );

        OracleManagerV1.initOracleManagerV1(_oracleAddress);
    }

    /// @inheritdoc IRiverV1
    function getGlobalFee() external view returns (uint256) {
        return GlobalFee.get();
    }

    /// @inheritdoc IRiverV1
    function getAllowlist() external view returns (address) {
        return AllowlistAddress.get();
    }

    /// @inheritdoc IRiverV1
    function getCollector() external view returns (address) {
        return CollectorAddress.get();
    }

    /// @inheritdoc IRiverV1
    function getELFeeRecipient() external view returns (address) {
        return ELFeeRecipientAddress.get();
    }

    /// @inheritdoc IRiverV1
    function setGlobalFee(uint256 newFee) external onlyAdmin {
        GlobalFee.set(newFee);
        emit SetGlobalFee(newFee);
    }

    /// @inheritdoc IRiverV1
    function setAllowlist(address _newAllowlist) external onlyAdmin {
        AllowlistAddress.set(_newAllowlist);
        emit SetAllowlist(_newAllowlist);
    }

    /// @inheritdoc IRiverV1
    function setCollector(address _newCollector) external onlyAdmin {
        CollectorAddress.set(_newCollector);
        emit SetCollector(_newCollector);
    }

    /// @inheritdoc IRiverV1
    function setELFeeRecipient(address _newELFeeRecipient) external onlyAdmin {
        ELFeeRecipientAddress.set(_newELFeeRecipient);
        emit SetELFeeRecipient(_newELFeeRecipient);
    }

    /// @inheritdoc IRiverV1
    function getOperatorsRegistry() external view returns (address) {
        return OperatorsRegistryAddress.get();
    }

    /// @inheritdoc IRiverV1
    function sendELFees() external payable {
        if (msg.sender != ELFeeRecipientAddress.get()) {
            revert LibErrors.Unauthorized(msg.sender);
        }
    }

    /// @notice Overriden handler to pass the system admin inside components
    /// @return The address of the admin
    function _getRiverAdmin()
        internal
        view
        override (OracleManagerV1, ConsensusLayerDepositManagerV1)
        returns (address)
    {
        return Administrable._getAdmin();
    }

    /// @notice Overriden handler called whenever a token transfer is triggered
    /// @param _from Token sender
    /// @param _to Token receiver
    function _onTransfer(address _from, address _to) internal view override {
        IAllowlistV1 allowlist = IAllowlistV1(AllowlistAddress.get());
        if (allowlist.isDenied(_from)) {
            revert Denied(_from);
        }
        if (allowlist.isDenied(_to)) {
            revert Denied(_to);
        }
    }

    /// @notice Overriden handler called whenever a user deposits ETH to the system. Mints the adequate amount of shares.
    /// @param _depositor User address that made the deposit
    /// @param _amount Amount of ETH deposited
    function _onDeposit(address _depositor, address _recipient, uint256 _amount) internal override {
        uint256 mintedShares = SharesManagerV1._mintShares(_depositor, _amount);
        IAllowlistV1 allowlist = IAllowlistV1(AllowlistAddress.get());
        if (_depositor == _recipient) {
            allowlist.onlyAllowed(_depositor, DEPOSIT_MASK); // this call reverts if unauthorized or denied
        } else {
            allowlist.onlyAllowed(_depositor, DEPOSIT_MASK); // this call reverts if unauthorized or denied
            if (allowlist.isDenied(_recipient)) {
                revert Denied(_recipient);
            }
            _transfer(_depositor, _recipient, mintedShares);
        }
    }

    /// @notice Overriden handler called whenever a deposit to the consensus layer is made. Should retrieve _requestedAmount or lower keys
    /// @param _requestedAmount Amount of keys required. Contract is expected to send _requestedAmount or lower.
    /// @return publicKeys Array of fundable public keys
    /// @return signatures Array of signatures linked to the public keys
    function _getNextValidators(uint256 _requestedAmount)
        internal
        override
        returns (bytes[] memory publicKeys, bytes[] memory signatures)
    {
        return IOperatorsRegistryV1(OperatorsRegistryAddress.get()).pickNextValidators(_requestedAmount);
    }

    /// @notice Overriden handler to pull funds from the execution layer fee recipient to River and return the delta in the balance
    /// @param _max The maximum amount to pull from the execution layer fee recipient
    /// @return The amount pulled from the execution layer fee recipient
    function _pullELFees(uint256 _max) internal override returns (uint256) {
        address elFeeRecipient = ELFeeRecipientAddress.get();
        if (elFeeRecipient == address(0)) {
            return 0;
        }
        uint256 initialBalance = address(this).balance;
        IELFeeRecipientV1(payable(elFeeRecipient)).pullELFees(_max);
        uint256 collectedELFees = address(this).balance - initialBalance;
        BalanceToDeposit.set(BalanceToDeposit.get() + collectedELFees);
        emit PulledELFees(collectedELFees);
        return collectedELFees;
    }

    /// @notice Overriden handler called whenever the balance of ETH handled by the system increases. Computes the fees paid to the collector
    /// @param _amount Additional ETH received
    function _onEarnings(uint256 _amount) internal override {
        uint256 oldTotalSupply = _totalSupply();
        if (oldTotalSupply == 0) {
            revert ZeroMintedShares();
        }
        uint256 newTotalBalance = _assetBalance();
        uint256 globalFee = GlobalFee.get();
        uint256 numerator = _amount * oldTotalSupply * globalFee;
        uint256 denominator = (newTotalBalance * LibBasisPoints.BASIS_POINTS_MAX) - (_amount * globalFee);
        uint256 sharesToMint = denominator == 0 ? 0 : (numerator / denominator);

        if (sharesToMint > 0) {
            address collector = CollectorAddress.get();
            _mintRawShares(collector, sharesToMint);
            uint256 newTotalSupply = _totalSupply();
            uint256 oldTotalBalance = newTotalBalance - _amount;
            emit RewardsEarned(collector, oldTotalBalance, oldTotalSupply, newTotalBalance, newTotalSupply);
        }
    }

    /// @notice Overriden handler called whenever the total balance of ETH is requested
    /// @return The current total asset balance managed by River
    function _assetBalance() internal view override returns (uint256) {
        uint256 clValidatorCount = CLValidatorCount.get();
        uint256 depositedValidatorCount = DepositedValidatorCount.get();
        if (clValidatorCount < depositedValidatorCount) {
            return CLValidatorTotalBalance.get() + BalanceToDeposit.get()
                + (depositedValidatorCount - clValidatorCount) * ConsensusLayerDepositManagerV1.DEPOSIT_SIZE;
        } else {
            return CLValidatorTotalBalance.get() + BalanceToDeposit.get();
        }
    }
}

File 2 of 45 : Administrable.sol
//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.10;

import "./interfaces/IAdministrable.sol";

import "./libraries/LibAdministrable.sol";
import "./libraries/LibSanitize.sol";

/// @title Administrable
/// @author Kiln
/// @notice This contract handles the administration of the contracts
abstract contract Administrable is IAdministrable {
    /// @notice Prevents unauthorized calls
    modifier onlyAdmin() {
        if (msg.sender != LibAdministrable._getAdmin()) {
            revert LibErrors.Unauthorized(msg.sender);
        }
        _;
    }

    /// @notice Prevents unauthorized calls
    modifier onlyPendingAdmin() {
        if (msg.sender != LibAdministrable._getPendingAdmin()) {
            revert LibErrors.Unauthorized(msg.sender);
        }
        _;
    }

    /// @inheritdoc IAdministrable
    function getAdmin() external view returns (address) {
        return LibAdministrable._getAdmin();
    }

    /// @inheritdoc IAdministrable
    function getPendingAdmin() external view returns (address) {
        return LibAdministrable._getPendingAdmin();
    }

    /// @inheritdoc IAdministrable
    function proposeAdmin(address _newAdmin) external onlyAdmin {
        _setPendingAdmin(_newAdmin);
    }

    /// @inheritdoc IAdministrable
    function acceptAdmin() external onlyPendingAdmin {
        _setAdmin(LibAdministrable._getPendingAdmin());
        _setPendingAdmin(address(0));
    }

    /// @notice Internal utility to set the admin address
    /// @param _admin Address to set as admin
    function _setAdmin(address _admin) internal {
        LibSanitize._notZeroAddress(_admin);
        LibAdministrable._setAdmin(_admin);
        emit SetAdmin(_admin);
    }

    /// @notice Internal utility to set the pending admin address
    /// @param _pendingAdmin Address to set as pending admin
    function _setPendingAdmin(address _pendingAdmin) internal {
        LibAdministrable._setPendingAdmin(_pendingAdmin);
        emit SetPendingAdmin(_pendingAdmin);
    }

    /// @notice Internal utility to retrieve the address of the current admin
    /// @return The address of admin
    function _getAdmin() internal view returns (address) {
        return LibAdministrable._getAdmin();
    }
}

File 3 of 45 : Initializable.sol
//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.10;

import "./state/shared/Version.sol";

/// @title Initializable
/// @author Kiln
/// @notice This contract ensures that initializers are called only once per version
contract Initializable {
    /// @notice An error occured during the initialization
    /// @param version The version that was attempting to be initialized
    /// @param expectedVersion The version that was expected
    error InvalidInitialization(uint256 version, uint256 expectedVersion);

    /// @notice Emitted when the contract is properly initialized
    /// @param version New version of the contracts
    /// @param cdata Complete calldata that was used during the initialization
    event Initialize(uint256 version, bytes cdata);

    /// @notice Use this modifier on initializers along with a hard-coded version number
    /// @param _version Version to initialize
    modifier init(uint256 _version) {
        if (_version != Version.get()) {
            revert InvalidInitialization(_version, Version.get());
        }
        Version.set(_version + 1); // prevents reentrency on the called method
        _;
        emit Initialize(_version, msg.data);
    }
}

File 4 of 45 : ConsensusLayerDepositManager.1.sol
//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.10;

import "../interfaces/components/IConsensusLayerDepositManager.1.sol";
import "../interfaces/IDepositContract.sol";

import "../libraries/LibBytes.sol";
import "../libraries/LibUint256.sol";

import "../state/river/DepositContractAddress.sol";
import "../state/river/WithdrawalCredentials.sol";
import "../state/river/DepositedValidatorCount.sol";
import "../state/river/BalanceToDeposit.sol";

/// @title Consensus Layer Deposit Manager (v1)
/// @author Kiln
/// @notice This contract handles the interactions with the official deposit contract, funding all validators
/// @notice Whenever a deposit to the consensus layer is requested, this contract computed the amount of keys
/// @notice that could be deposited depending on the amount available in the contract. It then tries to retrieve
/// @notice validator keys by calling its internal virtual method _getNextValidators. This method should be
/// @notice overridden by the implementing contract to provide [0; _keyCount] keys when invoked.
abstract contract ConsensusLayerDepositManagerV1 is IConsensusLayerDepositManagerV1 {
    /// @notice Size of a BLS Public key in bytes
    uint256 public constant PUBLIC_KEY_LENGTH = 48;
    /// @notice Size of a BLS Signature in bytes
    uint256 public constant SIGNATURE_LENGTH = 96;
    /// @notice Size of a deposit in ETH
    uint256 public constant DEPOSIT_SIZE = 32 ether;

    /// @notice Handler called to retrieve the internal River admin address
    /// @dev Must be overriden
    function _getRiverAdmin() internal view virtual returns (address);

    /// @notice Prevents unauthorized calls
    modifier onlyAdmin_CDMV1() {
        if (msg.sender != _getRiverAdmin()) {
            revert LibErrors.Unauthorized(msg.sender);
        }
        _;
    }

    /// @notice Internal helper to retrieve validator keys ready to be funded
    /// @dev Must be overridden
    /// @param _keyCount The amount of keys (or less) to return.
    function _getNextValidators(uint256 _keyCount)
        internal
        virtual
        returns (bytes[] memory publicKeys, bytes[] memory signatures);

    /// @notice Initializer to set the deposit contract address and the withdrawal credentials to use
    /// @param _depositContractAddress The address of the deposit contract
    /// @param _withdrawalCredentials The withdrawal credentials to apply to all deposits
    function initConsensusLayerDepositManagerV1(address _depositContractAddress, bytes32 _withdrawalCredentials)
        internal
    {
        DepositContractAddress.set(_depositContractAddress);
        emit SetDepositContractAddress(_depositContractAddress);

        WithdrawalCredentials.set(_withdrawalCredentials);
        emit SetWithdrawalCredentials(_withdrawalCredentials);
    }

    /// @inheritdoc IConsensusLayerDepositManagerV1
    function getBalanceToDeposit() external view returns (uint256) {
        return BalanceToDeposit.get();
    }

    /// @inheritdoc IConsensusLayerDepositManagerV1
    function getWithdrawalCredentials() external view returns (bytes32) {
        return WithdrawalCredentials.get();
    }

    /// @inheritdoc IConsensusLayerDepositManagerV1
    function getDepositedValidatorCount() external view returns (uint256) {
        return DepositedValidatorCount.get();
    }

    /// @inheritdoc IConsensusLayerDepositManagerV1
    function depositToConsensusLayer(uint256 _maxCount) external onlyAdmin_CDMV1 {
        uint256 balanceToDeposit = BalanceToDeposit.get();
        uint256 keyToDepositCount = LibUint256.min(balanceToDeposit / DEPOSIT_SIZE, _maxCount);

        if (keyToDepositCount == 0) {
            revert NotEnoughFunds();
        }

        (bytes[] memory publicKeys, bytes[] memory signatures) = _getNextValidators(keyToDepositCount);

        uint256 receivedPublicKeyCount = publicKeys.length;

        if (receivedPublicKeyCount == 0) {
            revert NoAvailableValidatorKeys();
        }

        if (receivedPublicKeyCount > keyToDepositCount) {
            revert InvalidPublicKeyCount();
        }

        uint256 receivedSignatureCount = signatures.length;

        if (receivedSignatureCount != receivedPublicKeyCount) {
            revert InvalidSignatureCount();
        }

        bytes32 withdrawalCredentials = WithdrawalCredentials.get();

        if (withdrawalCredentials == 0) {
            revert InvalidWithdrawalCredentials();
        }

        for (uint256 idx = 0; idx < receivedPublicKeyCount;) {
            _depositValidator(publicKeys[idx], signatures[idx], withdrawalCredentials);
            unchecked {
                ++idx;
            }
        }
        BalanceToDeposit.set(balanceToDeposit - DEPOSIT_SIZE * receivedPublicKeyCount);
        DepositedValidatorCount.set(DepositedValidatorCount.get() + receivedPublicKeyCount);
    }

    /// @notice Deposits 32 ETH to the official Deposit contract
    /// @param _publicKey The public key of the validator
    /// @param _signature The signature provided by the operator
    /// @param _withdrawalCredentials The withdrawal credentials provided by River
    function _depositValidator(bytes memory _publicKey, bytes memory _signature, bytes32 _withdrawalCredentials)
        internal
    {
        if (_publicKey.length != PUBLIC_KEY_LENGTH) {
            revert InconsistentPublicKeys();
        }

        if (_signature.length != SIGNATURE_LENGTH) {
            revert InconsistentSignatures();
        }
        uint256 value = DEPOSIT_SIZE;

        uint256 depositAmount = value / 1 gwei;

        bytes32 pubkeyRoot = sha256(bytes.concat(_publicKey, bytes16(0)));
        bytes32 signatureRoot = sha256(
            bytes.concat(
                sha256(LibBytes.slice(_signature, 0, 64)),
                sha256(bytes.concat(LibBytes.slice(_signature, 64, SIGNATURE_LENGTH - 64), bytes32(0)))
            )
        );

        bytes32 depositDataRoot = sha256(
            bytes.concat(
                sha256(bytes.concat(pubkeyRoot, _withdrawalCredentials)),
                sha256(bytes.concat(bytes32(LibUint256.toLittleEndian64(depositAmount)), signatureRoot))
            )
        );

        uint256 targetBalance = address(this).balance - value;

        IDepositContract(DepositContractAddress.get()).deposit{value: value}(
            _publicKey, abi.encodePacked(_withdrawalCredentials), _signature, depositDataRoot
        );
        if (address(this).balance != targetBalance) {
            revert ErrorOnDeposit();
        }
        emit FundedValidatorKey(_publicKey);
    }
}

File 5 of 45 : OracleManager.1.sol
//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.10;

import "../interfaces/components/IOracleManager.1.sol";

import "../state/river/OracleAddress.sol";
import "../state/river/LastOracleRoundId.sol";
import "../state/river/CLValidatorTotalBalance.sol";
import "../state/river/CLValidatorCount.sol";
import "../state/river/DepositedValidatorCount.sol";

/// @title Oracle Manager (v1)
/// @author Kiln
/// @notice This contract handles the inputs provided by the oracle
/// @notice The Oracle contract is plugged to this contract and is in charge of pushing
/// @notice data whenever a new report has been deemed valid. The report consists in two
/// @notice values: the sum of all balances of all deposited validators and the count of
/// @notice validators that have been activated on the consensus layer.
abstract contract OracleManagerV1 is IOracleManagerV1 {
    /// @notice Handler called if the delta between the last and new validator balance sum is positive
    /// @dev Must be overridden
    /// @param _profits The positive increase in the validator balance sum (staking rewards)
    function _onEarnings(uint256 _profits) internal virtual;

    /// @notice Handler called to pull the Execution layer fees from the recipient
    /// @dev Must be overridden
    /// @param _max The maximum amount to pull inside the system
    /// @return The amount pulled inside the system
    function _pullELFees(uint256 _max) internal virtual returns (uint256);

    /// @notice Handler called to retrieve the system administrator address
    /// @dev Must be overridden
    /// @return The system administrator address
    function _getRiverAdmin() internal view virtual returns (address);

    /// @notice Prevents unauthorized calls
    modifier onlyAdmin_OMV1() {
        if (msg.sender != _getRiverAdmin()) {
            revert LibErrors.Unauthorized(msg.sender);
        }
        _;
    }

    /// @notice Set the initial oracle address
    /// @param _oracle Address of the oracle
    function initOracleManagerV1(address _oracle) internal {
        OracleAddress.set(_oracle);
        emit SetOracle(_oracle);
    }

    /// @inheritdoc IOracleManagerV1
    function getOracle() external view returns (address) {
        return OracleAddress.get();
    }

    /// @inheritdoc IOracleManagerV1
    function getCLValidatorTotalBalance() external view returns (uint256) {
        return CLValidatorTotalBalance.get();
    }

    /// @inheritdoc IOracleManagerV1
    function getCLValidatorCount() external view returns (uint256) {
        return CLValidatorCount.get();
    }

    /// @inheritdoc IOracleManagerV1
    function setOracle(address _oracleAddress) external onlyAdmin_OMV1 {
        OracleAddress.set(_oracleAddress);
        emit SetOracle(_oracleAddress);
    }

    /// @inheritdoc IOracleManagerV1
    function setConsensusLayerData(
        uint256 _validatorCount,
        uint256 _validatorTotalBalance,
        bytes32 _roundId,
        uint256 _maxIncrease
    ) external {
        if (msg.sender != OracleAddress.get()) {
            revert LibErrors.Unauthorized(msg.sender);
        }

        if (_validatorCount > DepositedValidatorCount.get()) {
            revert InvalidValidatorCountReport(_validatorCount, DepositedValidatorCount.get());
        }

        uint256 newValidators = _validatorCount - CLValidatorCount.get();
        uint256 previousValidatorTotalBalance = CLValidatorTotalBalance.get() + (newValidators * 32 ether);

        CLValidatorTotalBalance.set(_validatorTotalBalance);
        CLValidatorCount.set(_validatorCount);
        LastOracleRoundId.set(_roundId);

        uint256 executionLayerFees;

        // if there's a margin left for pulling the execution layer fees that would leave our delta under the allowed maxIncrease value, do it
        if ((_maxIncrease + previousValidatorTotalBalance) > _validatorTotalBalance) {
            executionLayerFees = _pullELFees((_maxIncrease + previousValidatorTotalBalance) - _validatorTotalBalance);
        }

        if (previousValidatorTotalBalance < _validatorTotalBalance + executionLayerFees) {
            _onEarnings((_validatorTotalBalance + executionLayerFees) - previousValidatorTotalBalance);
        }

        emit ConsensusLayerDataUpdate(_validatorCount, _validatorTotalBalance, _roundId);
    }
}

File 6 of 45 : SharesManager.1.sol
//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.10;

import "../interfaces/components/ISharesManager.1.sol";

import "../libraries/LibSanitize.sol";

import "../state/river/Shares.sol";
import "../state/river/SharesPerOwner.sol";
import "../state/shared/ApprovalsPerOwner.sol";

/// @title Shares Manager (v1)
/// @author Kiln
/// @notice This contract handles the shares of the depositor and the ERC20 interface
abstract contract SharesManagerV1 is ISharesManagerV1 {
    /// @notice Internal hook triggered on the external transfer call
    /// @dev Must be overridden
    /// @param _from Address of the sender
    /// @param _to Address of the recipient
    function _onTransfer(address _from, address _to) internal view virtual;

    /// @notice Internal method to override to provide the total underlying asset balance
    /// @dev Must be overridden
    /// @return The total asset balance of the system
    function _assetBalance() internal view virtual returns (uint256);

    /// @notice Modifier used to ensure that the transfer is allowed by using the internal hook to perform internal checks
    /// @param _from Address of the sender
    /// @param _to Address of the recipient
    modifier transferAllowed(address _from, address _to) {
        _onTransfer(_from, _to);
        _;
    }

    /// @notice Modifier used to ensure the amount transferred is not 0
    /// @param _value Amount to check
    modifier isNotZero(uint256 _value) {
        if (_value == 0) {
            revert NullTransfer();
        }
        _;
    }

    /// @notice Modifier used to ensure that the sender has enough funds for the transfer
    /// @param _owner Address of the sender
    /// @param _value Value that is required to be sent
    modifier hasFunds(address _owner, uint256 _value) {
        if (_balanceOf(_owner) < _value) {
            revert BalanceTooLow();
        }
        _;
    }

    /// @inheritdoc ISharesManagerV1
    function name() external pure returns (string memory) {
        return "Liquid Staked ETH";
    }

    /// @inheritdoc ISharesManagerV1
    function symbol() external pure returns (string memory) {
        return "LsETH";
    }

    /// @inheritdoc ISharesManagerV1
    function decimals() external pure returns (uint8) {
        return 18;
    }

    /// @inheritdoc ISharesManagerV1
    function totalSupply() external view returns (uint256) {
        return _totalSupply();
    }

    /// @inheritdoc ISharesManagerV1
    function totalUnderlyingSupply() external view returns (uint256) {
        return _assetBalance();
    }

    /// @inheritdoc ISharesManagerV1
    function balanceOf(address _owner) external view returns (uint256) {
        return _balanceOf(_owner);
    }

    /// @inheritdoc ISharesManagerV1
    function balanceOfUnderlying(address _owner) public view returns (uint256) {
        return _balanceFromShares(SharesPerOwner.get(_owner));
    }

    /// @inheritdoc ISharesManagerV1
    function underlyingBalanceFromShares(uint256 _shares) external view returns (uint256) {
        return _balanceFromShares(_shares);
    }

    /// @inheritdoc ISharesManagerV1
    function sharesFromUnderlyingBalance(uint256 _underlyingAssetAmount) external view returns (uint256) {
        return _sharesFromBalance(_underlyingAssetAmount);
    }

    /// @inheritdoc ISharesManagerV1
    function allowance(address _owner, address _spender) external view returns (uint256) {
        return ApprovalsPerOwner.get(_owner, _spender);
    }

    /// @inheritdoc ISharesManagerV1
    function transfer(address _to, uint256 _value)
        external
        transferAllowed(msg.sender, _to)
        isNotZero(_value)
        hasFunds(msg.sender, _value)
        returns (bool)
    {
        if (_to == address(0)) {
            revert UnauthorizedTransfer(msg.sender, address(0));
        }
        return _transfer(msg.sender, _to, _value);
    }

    /// @inheritdoc ISharesManagerV1
    function transferFrom(address _from, address _to, uint256 _value)
        external
        transferAllowed(_from, _to)
        isNotZero(_value)
        hasFunds(_from, _value)
        returns (bool)
    {
        if (_to == address(0)) {
            revert UnauthorizedTransfer(_from, address(0));
        }
        _spendAllowance(_from, _value);
        return _transfer(_from, _to, _value);
    }

    /// @inheritdoc ISharesManagerV1
    function approve(address _spender, uint256 _value) external returns (bool) {
        _approve(msg.sender, _spender, _value);
        return true;
    }

    /// @inheritdoc ISharesManagerV1
    function increaseAllowance(address _spender, uint256 _additionalValue) external returns (bool) {
        _approve(msg.sender, _spender, ApprovalsPerOwner.get(msg.sender, _spender) + _additionalValue);
        return true;
    }

    /// @inheritdoc ISharesManagerV1
    function decreaseAllowance(address _spender, uint256 _subtractableValue) external returns (bool) {
        _approve(msg.sender, _spender, ApprovalsPerOwner.get(msg.sender, _spender) - _subtractableValue);
        return true;
    }

    /// @notice Internal utility to spend the allowance of an account from the message sender
    /// @param _from Address owning the allowance
    /// @param _value Amount of allowance in shares to spend
    function _spendAllowance(address _from, uint256 _value) internal {
        uint256 currentAllowance = ApprovalsPerOwner.get(_from, msg.sender);
        if (currentAllowance < _value) {
            revert AllowanceTooLow(_from, msg.sender, currentAllowance, _value);
        }
        if (currentAllowance != type(uint256).max) {
            _approve(_from, msg.sender, currentAllowance - _value);
        }
    }

    /// @notice Internal utility to change the allowance of an owner to a spender
    /// @param _owner The owner of the shares
    /// @param _spender The allowed spender of the shares
    /// @param _value The new allowance value
    function _approve(address _owner, address _spender, uint256 _value) internal {
        LibSanitize._notZeroAddress(_owner);
        LibSanitize._notZeroAddress(_spender);
        ApprovalsPerOwner.set(_owner, _spender, _value);
        emit Approval(_owner, _spender, _value);
    }

    /// @notice Internal utility to retrieve the total supply of tokens
    /// @return The total supply
    function _totalSupply() internal view returns (uint256) {
        return Shares.get();
    }

    /// @notice Internal utility to perform an unchecked transfer
    /// @param _from Address sending the tokens
    /// @param _to Address receiving the tokens
    /// @param _value Amount of shares to be sent
    /// @return True if success
    function _transfer(address _from, address _to, uint256 _value) internal returns (bool) {
        SharesPerOwner.set(_from, SharesPerOwner.get(_from) - _value);
        SharesPerOwner.set(_to, SharesPerOwner.get(_to) + _value);

        emit Transfer(_from, _to, _value);

        return true;
    }

    /// @notice Internal utility to retrieve the underlying asset balance for the given shares
    /// @param _shares Amount of shares to convert
    /// @return The balance from the given shares
    function _balanceFromShares(uint256 _shares) internal view returns (uint256) {
        uint256 _totalSharesValue = Shares.get();

        if (_totalSharesValue == 0) {
            return 0;
        }

        return ((_shares * _assetBalance())) / _totalSharesValue;
    }

    /// @notice Internal utility to retrieve the shares count for a given underlying asset amount
    /// @param _balance Amount of underlying asset balance to convert
    /// @return The shares from the given balance
    function _sharesFromBalance(uint256 _balance) internal view returns (uint256) {
        uint256 _totalSharesValue = Shares.get();

        if (_totalSharesValue == 0) {
            return 0;
        }

        return (_balance * _totalSharesValue) / _assetBalance();
    }

    /// @notice Internal utility to mint shares for the specified user
    /// @dev This method assumes that funds received are now part of the _assetBalance()
    /// @param _owner Account that should receive the new shares
    /// @param _underlyingAssetValue Value of underlying asset received, to convert into shares
    /// @return sharesToMint The amnount of minted shares
    function _mintShares(address _owner, uint256 _underlyingAssetValue) internal returns (uint256 sharesToMint) {
        uint256 oldTotalAssetBalance = _assetBalance() - _underlyingAssetValue;

        if (oldTotalAssetBalance == 0) {
            sharesToMint = _underlyingAssetValue;
            _mintRawShares(_owner, _underlyingAssetValue);
        } else {
            sharesToMint = (_underlyingAssetValue * _totalSupply()) / oldTotalAssetBalance;
            _mintRawShares(_owner, sharesToMint);
        }
    }

    /// @notice Internal utility to mint shares without any conversion, and emits a mint Transfer event
    /// @param _owner Account that should receive the new shares
    /// @param _value Amount of shares to mint
    function _mintRawShares(address _owner, uint256 _value) internal {
        Shares.set(Shares.get() + _value);
        SharesPerOwner.set(_owner, SharesPerOwner.get(_owner) + _value);
        emit Transfer(address(0), _owner, _value);
    }

    /// @notice Internal utility to retrieve the amount of shares per owner
    /// @param _owner Account to be checked
    /// @return The balance of the account in shares
    function _balanceOf(address _owner) internal view returns (uint256) {
        return SharesPerOwner.get(_owner);
    }
}

File 7 of 45 : UserDepositManager.1.sol
//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.10;

import "../interfaces/components/IUserDepositManager.1.sol";

import "../libraries/LibSanitize.sol";

import "../state/river/BalanceToDeposit.sol";

/// @title User Deposit Manager (v1)
/// @author Kiln
/// @notice This contract handles the inbound transfers cases or the explicit submissions
abstract contract UserDepositManagerV1 is IUserDepositManagerV1 {
    /// @notice Handler called whenever a user has sent funds to the contract
    /// @dev Must be overridden
    /// @param _depositor Address that made the deposit
    /// @param _recipient Address that receives the minted shares
    /// @param _amount Amount deposited
    function _onDeposit(address _depositor, address _recipient, uint256 _amount) internal virtual;

    /// @inheritdoc IUserDepositManagerV1
    function deposit() external payable {
        _deposit(msg.sender);
    }

    /// @inheritdoc IUserDepositManagerV1
    function depositAndTransfer(address _recipient) external payable {
        LibSanitize._notZeroAddress(_recipient);
        _deposit(_recipient);
    }

    /// @inheritdoc IUserDepositManagerV1
    receive() external payable {
        _deposit(msg.sender);
    }

    /// @inheritdoc IUserDepositManagerV1
    fallback() external payable {
        revert LibErrors.InvalidCall();
    }

    /// @notice Internal utility calling the deposit handler and emitting the deposit details
    /// @param _recipient The account receiving the minted shares
    function _deposit(address _recipient) internal {
        if (msg.value == 0) {
            revert EmptyDeposit();
        }

        BalanceToDeposit.set(BalanceToDeposit.get() + msg.value);

        _onDeposit(msg.sender, _recipient, msg.value);

        emit UserDeposit(msg.sender, _recipient, msg.value);
    }
}

File 8 of 45 : IAdministrable.sol
//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.10;

/// @title Administrable Interface
/// @author Kiln
/// @notice This interface exposes methods to handle the ownership of the contracts
interface IAdministrable {
    /// @notice The pending admin address changed
    /// @param pendingAdmin New pending admin address
    event SetPendingAdmin(address indexed pendingAdmin);

    /// @notice The admin address changed
    /// @param admin New admin address
    event SetAdmin(address indexed admin);

    /// @notice Retrieves the current admin address
    /// @return The admin address
    function getAdmin() external view returns (address);

    /// @notice Retrieve the current pending admin address
    /// @return The pending admin address
    function getPendingAdmin() external view returns (address);

    /// @notice Proposes a new address as admin
    /// @dev This security prevents setting an invalid address as an admin. The pending
    /// @dev admin has to claim its ownership of the contract, and prove that the new
    /// @dev address is able to perform regular transactions.
    /// @param _newAdmin New admin address
    function proposeAdmin(address _newAdmin) external;

    /// @notice Accept the transfer of ownership
    /// @dev Only callable by the pending admin. Resets the pending admin if succesful.
    function acceptAdmin() external;
}

File 9 of 45 : IAllowlist.1.sol
//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.10;

/// @title Allowlist Interface (v1)
/// @author Kiln
/// @notice This interface exposes methods to handle the list of allowed recipients.
interface IAllowlistV1 {
    /// @notice The permissions of several accounts have changed
    /// @param accounts List of accounts
    /// @param permissions New permissions for each account at the same index
    event SetAllowlistPermissions(address[] indexed accounts, uint256[] permissions);

    /// @notice The stored allower address has been changed
    /// @param allower The new allower address
    event SetAllower(address indexed allower);

    /// @notice The provided accounts list is empty
    error InvalidAlloweeCount();

    /// @notice The account is denied access
    /// @param _account The denied account
    error Denied(address _account);

    /// @notice The provided accounts and permissions list have different lengths
    error MismatchedAlloweeAndStatusCount();

    /// @notice Initializes the allowlist
    /// @param _admin Address of the Allowlist administrator
    /// @param _allower Address of the allower
    function initAllowlistV1(address _admin, address _allower) external;

    /// @notice Retrieves the allower address
    /// @return The address of the allower
    function getAllower() external view returns (address);

    /// @notice This method returns true if the user has the expected permission and
    ///         is not in the deny list
    /// @param _account Recipient to verify
    /// @param _mask Combination of permissions to verify
    /// @return True if mask is respected and user is allowed
    function isAllowed(address _account, uint256 _mask) external view returns (bool);

    /// @notice This method returns true if the user is in the deny list
    /// @param _account Recipient to verify
    /// @return True if user is denied access
    function isDenied(address _account) external view returns (bool);

    /// @notice This method returns true if the user has the expected permission
    ///         ignoring any deny list membership
    /// @param _account Recipient to verify
    /// @param _mask Combination of permissions to verify
    /// @return True if mask is respected
    function hasPermission(address _account, uint256 _mask) external view returns (bool);

    /// @notice This method retrieves the raw permission value
    /// @param _account Recipient to verify
    /// @return The raw permissions value of the account
    function getPermissions(address _account) external view returns (uint256);

    /// @notice This method should be used as a modifier and is expected to revert
    ///         if the user hasn't got the required permission or if the user is
    ///         in the deny list.
    /// @param _account Recipient to verify
    /// @param _mask Combination of permissions to verify
    function onlyAllowed(address _account, uint256 _mask) external view;

    /// @notice Changes the allower address
    /// @param _newAllowerAddress New address allowed to edit the allowlist
    function setAllower(address _newAllowerAddress) external;

    /// @notice Sets the allowlisting status for one or more accounts
    /// @dev The permission value is overridden and not updated
    /// @param _accounts Accounts with statuses to edit
    /// @param _permissions Allowlist permissions for each account, in the same order as _accounts
    function allow(address[] calldata _accounts, uint256[] calldata _permissions) external;
}

File 10 of 45 : IDepositContract.sol
//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.10;

/// @title Deposit Contract Interface
/// @notice This interface exposes methods to perform validator deposits
interface IDepositContract {
    /// @notice Official deposit method to activate a validator on the consensus layer
    /// @param pubkey The 48 bytes long BLS Public key representing the validator
    /// @param withdrawalCredentials The 32 bytes long withdrawal credentials, configures the withdrawal recipient
    /// @param signature The 96 bytes long BLS Signature performed by the pubkey's private key
    /// @param depositDataRoot The root hash of the whole deposit data structure
    function deposit(
        bytes calldata pubkey,
        bytes calldata withdrawalCredentials,
        bytes calldata signature,
        bytes32 depositDataRoot
    ) external payable;
}

File 11 of 45 : IELFeeRecipient.1.sol
//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.10;

/// @title Execution Layer Fee Recipient Interface (v1)
/// @author Kiln
/// @notice This interface exposes methods to receive all the execution layer fees from the proposed blocks + bribes
interface IELFeeRecipientV1 {
    /// @notice The storage river address has changed
    /// @param river The new river address
    event SetRiver(address indexed river);

    /// @notice The fallback has been triggered
    error InvalidCall();

    /// @notice Initialize the fee recipient with the required arguments
    /// @param _riverAddress Address of River
    function initELFeeRecipientV1(address _riverAddress) external;

    /// @notice Pulls all the ETH to the River contract
    /// @dev Only callable by the River contract
    /// @param _maxAmount The maximum amount to pull into the system
    function pullELFees(uint256 _maxAmount) external;

    /// @notice Ether receiver
    receive() external payable;

    /// @notice Invalid fallback detector
    fallback() external payable;
}

File 12 of 45 : IOperatorRegistry.1.sol
//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.10;

import "../state/operatorsRegistry/Operators.sol";

/// @title Operators Registry Interface (v1)
/// @author Kiln
/// @notice This interface exposes methods to handle the list of operators and their keys
interface IOperatorsRegistryV1 {
    /// @notice A new operator has been added to the registry
    /// @param index The operator index
    /// @param name The operator display name
    /// @param operatorAddress The operator address
    event AddedOperator(uint256 indexed index, string name, address indexed operatorAddress);

    /// @notice The operator status has been changed
    /// @param index The operator index
    /// @param active True if the operator is active
    event SetOperatorStatus(uint256 indexed index, bool active);

    /// @notice The operator limit has been changed
    /// @param index The operator index
    /// @param newLimit The new operator staking limit
    event SetOperatorLimit(uint256 indexed index, uint256 newLimit);

    /// @notice The operator stopped validator count has been changed
    /// @param index The operator index
    /// @param newStoppedValidatorCount The new stopped validator count
    event SetOperatorStoppedValidatorCount(uint256 indexed index, uint256 newStoppedValidatorCount);

    /// @notice The operator address has been changed
    /// @param index The operator index
    /// @param newOperatorAddress The new operator address
    event SetOperatorAddress(uint256 indexed index, address indexed newOperatorAddress);

    /// @notice The operator display name has been changed
    /// @param index The operator index
    /// @param newName The new display name
    event SetOperatorName(uint256 indexed index, string newName);

    /// @notice The operator or the admin added new validator keys and signatures
    /// @dev The public keys and signatures are concatenated
    /// @dev A public key is 48 bytes long
    /// @dev A signature is 96 bytes long
    /// @dev [P1, S1, P2, S2, ..., PN, SN] where N is the bytes length divided by (96 + 48)
    /// @param index The operator index
    /// @param publicKeysAndSignatures The concatenated public keys and signatures
    event AddedValidatorKeys(uint256 indexed index, bytes publicKeysAndSignatures);

    /// @notice The operator or the admin removed a public key and its signature from the registry
    /// @param index The operator index
    /// @param publicKey The BLS public key that has been removed
    event RemovedValidatorKey(uint256 indexed index, bytes publicKey);

    /// @notice The stored river address has been changed
    /// @param river The new river address
    event SetRiver(address indexed river);

    /// @notice The operator edited its keys after the snapshot block
    /// @dev This means that we cannot assume that its key set is checked by the snapshot
    /// @dev This happens only if the limit was meant to be increased
    /// @param index The operator index
    /// @param currentLimit The current operator limit
    /// @param newLimit The new operator limit that was attempted to be set
    /// @param latestKeysEditBlockNumber The last block number at which the operator changed its keys
    /// @param snapshotBlock The block number of the snapshot
    event OperatorEditsAfterSnapshot(
        uint256 indexed index,
        uint256 currentLimit,
        uint256 newLimit,
        uint256 indexed latestKeysEditBlockNumber,
        uint256 indexed snapshotBlock
    );

    /// @notice The call didn't alter the limit of the operator
    /// @param index The operator index
    /// @param limit The limit of the operator
    event OperatorLimitUnchanged(uint256 indexed index, uint256 limit);

    /// @notice The calling operator is inactive
    /// @param index The operator index
    error InactiveOperator(uint256 index);

    /// @notice A funded key deletion has been attempted
    error InvalidFundedKeyDeletionAttempt();

    /// @notice The index provided are not sorted properly (descending order)
    error InvalidUnsortedIndexes();

    /// @notice The provided operator and limits array have different lengths
    error InvalidArrayLengths();

    /// @notice The provided operator and limits array are empty
    error InvalidEmptyArray();

    /// @notice The provided key count is 0
    error InvalidKeyCount();

    /// @notice The provided concatenated keys do not have the expected length
    error InvalidKeysLength();

    /// @notice The index that is removed is out of bounds
    error InvalidIndexOutOfBounds();

    /// @notice The value for the operator limit is too high
    /// @param index The operator index
    /// @param limit The new limit provided
    /// @param keyCount The operator key count
    error OperatorLimitTooHigh(uint256 index, uint256 limit, uint256 keyCount);

    /// @notice The value for the limit is too low
    /// @param index The operator index
    /// @param limit The new limit provided
    /// @param fundedKeyCount The operator funded key count
    error OperatorLimitTooLow(uint256 index, uint256 limit, uint256 fundedKeyCount);

    /// @notice The provided list of operators is not in increasing order
    error UnorderedOperatorList();

    /// @notice Initializes the operators registry
    /// @param _admin Admin in charge of managing operators
    /// @param _river Address of River system
    function initOperatorsRegistryV1(address _admin, address _river) external;

    /// @notice Retrieve the River address
    /// @return The address of River
    function getRiver() external view returns (address);

    /// @notice Get operator details
    /// @param _index The index of the operator
    /// @return The details of the operator
    function getOperator(uint256 _index) external view returns (Operators.Operator memory);

    /// @notice Get operator count
    /// @return The operator count
    function getOperatorCount() external view returns (uint256);

    /// @notice Get the details of a validator
    /// @param _operatorIndex The index of the operator
    /// @param _validatorIndex The index of the validator
    /// @return publicKey The public key of the validator
    /// @return signature The signature used during deposit
    /// @return funded True if validator has been funded
    function getValidator(uint256 _operatorIndex, uint256 _validatorIndex)
        external
        view
        returns (bytes memory publicKey, bytes memory signature, bool funded);

    /// @notice Retrieve the active operator set
    /// @return The list of active operators and their details
    function listActiveOperators() external view returns (Operators.Operator[] memory);

    /// @notice Adds an operator to the registry
    /// @dev Only callable by the administrator
    /// @param _name The name identifying the operator
    /// @param _operator The address representing the operator, receiving the rewards
    /// @return The index of the new operator
    function addOperator(string calldata _name, address _operator) external returns (uint256);

    /// @notice Changes the operator address of an operator
    /// @dev Only callable by the administrator or the previous operator address
    /// @param _index The operator index
    /// @param _newOperatorAddress The new address of the operator
    function setOperatorAddress(uint256 _index, address _newOperatorAddress) external;

    /// @notice Changes the operator name
    /// @dev Only callable by the administrator or the operator
    /// @param _index The operator index
    /// @param _newName The new operator name
    function setOperatorName(uint256 _index, string calldata _newName) external;

    /// @notice Changes the operator status
    /// @dev Only callable by the administrator
    /// @param _index The operator index
    /// @param _newStatus The new status of the operator
    function setOperatorStatus(uint256 _index, bool _newStatus) external;

    /// @notice Changes the operator stopped validator count
    /// @dev Only callable by the administrator
    /// @param _index The operator index
    /// @param _newStoppedValidatorCount The new stopped validator count of the operator
    function setOperatorStoppedValidatorCount(uint256 _index, uint256 _newStoppedValidatorCount) external;

    /// @notice Changes the operator staking limit
    /// @dev Only callable by the administrator
    /// @dev The operator indexes must be in increasing order and contain no duplicate
    /// @dev The limit cannot exceed the total key count of the operator
    /// @dev The _indexes and _newLimits must have the same length.
    /// @dev Each limit value is applied to the operator index at the same index in the _indexes array.
    /// @param _operatorIndexes The operator indexes, in increasing order and duplicate free
    /// @param _newLimits The new staking limit of the operators
    /// @param _snapshotBlock The block number at which the snapshot was computed
    function setOperatorLimits(
        uint256[] calldata _operatorIndexes,
        uint256[] calldata _newLimits,
        uint256 _snapshotBlock
    ) external;

    /// @notice Adds new keys for an operator
    /// @dev Only callable by the administrator or the operator address
    /// @param _index The operator index
    /// @param _keyCount The amount of keys provided
    /// @param _publicKeysAndSignatures Public keys of the validator, concatenated
    function addValidators(uint256 _index, uint256 _keyCount, bytes calldata _publicKeysAndSignatures) external;

    /// @notice Remove validator keys
    /// @dev Only callable by the administrator or the operator address
    /// @dev The indexes must be provided sorted in decreasing order and duplicate-free, otherwise the method will revert
    /// @dev The operator limit will be set to the lowest deleted key index if the operator's limit wasn't equal to its total key count
    /// @dev The operator or the admin cannot remove funded keys
    /// @dev When removing validators, the indexes of specific unfunded keys can be changed in order to properly
    /// @dev remove the keys from the storage array. Beware of this specific behavior when chaining calls as the
    /// @dev targeted public key indexes can point to a different key after a first call was made and performed
    /// @dev some swaps
    /// @param _index The operator index
    /// @param _indexes The indexes of the keys to remove
    function removeValidators(uint256 _index, uint256[] calldata _indexes) external;

    /// @notice Retrieve validator keys based on operator statuses
    /// @param _count Max amount of keys requested
    /// @return publicKeys An array of public keys
    /// @return signatures An array of signatures linked to the public keys
    function pickNextValidators(uint256 _count)
        external
        returns (bytes[] memory publicKeys, bytes[] memory signatures);
}

File 13 of 45 : IRiver.1.sol
//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.10;

import "./components/IConsensusLayerDepositManager.1.sol";
import "./components/IOracleManager.1.sol";
import "./components/ISharesManager.1.sol";
import "./components/IUserDepositManager.1.sol";

/// @title River Interface (v1)
/// @author Kiln
/// @notice The main system interface
interface IRiverV1 is IConsensusLayerDepositManagerV1, IUserDepositManagerV1, ISharesManagerV1, IOracleManagerV1 {
    /// @notice Funds have been pulled from the Execution Layer Fee Recipient
    /// @param amount The amount pulled
    event PulledELFees(uint256 amount);

    /// @notice The stored Execution Layer Fee Recipient has been changed
    /// @param elFeeRecipient The new Execution Layer Fee Recipient
    event SetELFeeRecipient(address indexed elFeeRecipient);

    /// @notice The stored Collector has been changed
    /// @param collector The new Collector
    event SetCollector(address indexed collector);

    /// @notice The stored Allowlist has been changed
    /// @param allowlist The new Allowlist
    event SetAllowlist(address indexed allowlist);

    /// @notice The stored Global Fee has been changed
    /// @param fee The new Global Fee
    event SetGlobalFee(uint256 fee);

    /// @notice The stored Operators Registry has been changed
    /// @param operatorRegistry The new Operators Registry
    event SetOperatorsRegistry(address indexed operatorRegistry);

    /// @notice The system underlying supply increased. This is a snapshot of the balances for accounting purposes
    /// @param _collector The address of the collector during this event
    /// @param _oldTotalUnderlyingBalance Old total ETH balance under management by River
    /// @param _oldTotalSupply Old total supply in shares
    /// @param _newTotalUnderlyingBalance New total ETH balance under management by River
    /// @param _newTotalSupply New total supply in shares
    event RewardsEarned(
        address indexed _collector,
        uint256 _oldTotalUnderlyingBalance,
        uint256 _oldTotalSupply,
        uint256 _newTotalUnderlyingBalance,
        uint256 _newTotalSupply
    );

    /// @notice The computed amount of shares to mint is 0
    error ZeroMintedShares();

    /// @notice The access was denied
    /// @param account The account that was denied
    error Denied(address account);

    /// @notice Initializes the River system
    /// @param _depositContractAddress Address to make Consensus Layer deposits
    /// @param _elFeeRecipientAddress Address that receives the execution layer fees
    /// @param _withdrawalCredentials Credentials to use for every validator deposit
    /// @param _oracleAddress The address of the Oracle contract
    /// @param _systemAdministratorAddress Administrator address
    /// @param _allowlistAddress Address of the allowlist contract
    /// @param _operatorRegistryAddress Address of the operator registry
    /// @param _collectorAddress Address receiving the the global fee on revenue
    /// @param _globalFee Amount retained when the ETH balance increases and sent to the collector
    function initRiverV1(
        address _depositContractAddress,
        address _elFeeRecipientAddress,
        bytes32 _withdrawalCredentials,
        address _oracleAddress,
        address _systemAdministratorAddress,
        address _allowlistAddress,
        address _operatorRegistryAddress,
        address _collectorAddress,
        uint256 _globalFee
    ) external;

    /// @notice Get the current global fee
    /// @return The global fee
    function getGlobalFee() external view returns (uint256);

    /// @notice Retrieve the allowlist address
    /// @return The allowlist address
    function getAllowlist() external view returns (address);

    /// @notice Retrieve the collector address
    /// @return The collector address
    function getCollector() external view returns (address);

    /// @notice Retrieve the execution layer fee recipient
    /// @return The execution layer fee recipient address
    function getELFeeRecipient() external view returns (address);

    /// @notice Retrieve the operators registry
    /// @return The operators registry address
    function getOperatorsRegistry() external view returns (address);

    /// @notice Changes the global fee parameter
    /// @param newFee New fee value
    function setGlobalFee(uint256 newFee) external;

    /// @notice Changes the allowlist address
    /// @param _newAllowlist New address for the allowlist
    function setAllowlist(address _newAllowlist) external;

    /// @notice Changes the collector address
    /// @param _newCollector New address for the collector
    function setCollector(address _newCollector) external;

    /// @notice Changes the execution layer fee recipient
    /// @param _newELFeeRecipient New address for the recipient
    function setELFeeRecipient(address _newELFeeRecipient) external;

    /// @notice Input for execution layer fee earnings
    function sendELFees() external payable;
}

File 14 of 45 : IConsensusLayerDepositManager.1.sol
//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.10;

/// @title Consensys Layer Deposit Manager Interface (v1)
/// @author Kiln
/// @notice This interface exposes methods to handle the interactions with the official deposit contract
interface IConsensusLayerDepositManagerV1 {
    /// @notice A validator key got funded on the deposit contract
    /// @param publicKey BLS Public key that got funded
    event FundedValidatorKey(bytes publicKey);

    /// @notice The stored deposit contract address changed
    /// @param depositContract Address of the deposit contract
    event SetDepositContractAddress(address indexed depositContract);

    /// @notice The stored withdrawal credentials changed
    /// @param withdrawalCredentials The withdrawal credentials to use for deposits
    event SetWithdrawalCredentials(bytes32 withdrawalCredentials);

    /// @notice Not enough funds to deposit one validator
    error NotEnoughFunds();

    /// @notice The length of the BLS Public key is invalid during deposit
    error InconsistentPublicKeys();

    /// @notice The length of the BLS Signature is invalid during deposit
    error InconsistentSignatures();

    /// @notice The internal key retrieval returned no keys
    error NoAvailableValidatorKeys();

    /// @notice The received count of public keys to deposit is invalid
    error InvalidPublicKeyCount();

    /// @notice The received count of signatures to deposit is invalid
    error InvalidSignatureCount();

    /// @notice The withdrawal credentials value is null
    error InvalidWithdrawalCredentials();

    /// @notice An error occured during the deposit
    error ErrorOnDeposit();

    /// @notice Returns the amount of pending ETH
    /// @return The amount of pending ETH
    function getBalanceToDeposit() external view returns (uint256);

    /// @notice Retrieve the withdrawal credentials
    /// @return The withdrawal credentials
    function getWithdrawalCredentials() external view returns (bytes32);

    /// @notice Get the deposited validator count (the count of deposits made by the contract)
    /// @return The deposited validator count
    function getDepositedValidatorCount() external view returns (uint256);

    /// @notice Deposits current balance to the Consensus Layer by batches of 32 ETH
    /// @param _maxCount The maximum amount of validator keys to fund
    function depositToConsensusLayer(uint256 _maxCount) external;
}

File 15 of 45 : IOracleManager.1.sol
//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.10;

/// @title Oracle Manager (v1)
/// @author Kiln
/// @notice This interface exposes methods to handle the inputs provided by the oracle
interface IOracleManagerV1 {
    /// @notice The stored oracle address changed
    /// @param oracleAddress The new oracle address
    event SetOracle(address indexed oracleAddress);

    /// @notice The consensus layer data provided by the oracle has been updated
    /// @param validatorCount The new count of validators running on the consensus layer
    /// @param validatorTotalBalance The new total balance sum of all validators
    /// @param roundId Round identifier
    event ConsensusLayerDataUpdate(uint256 validatorCount, uint256 validatorTotalBalance, bytes32 roundId);

    /// @notice The reported validator count is invalid
    /// @param providedValidatorCount The received validator count value
    /// @param depositedValidatorCount The number of deposits performed by the system
    error InvalidValidatorCountReport(uint256 providedValidatorCount, uint256 depositedValidatorCount);

    /// @notice Get oracle address
    /// @return The oracle address
    function getOracle() external view returns (address);

    /// @notice Get CL validator total balance
    /// @return The CL Validator total balance
    function getCLValidatorTotalBalance() external view returns (uint256);

    /// @notice Get CL validator count (the amount of validator reported by the oracles)
    /// @return The CL validator count
    function getCLValidatorCount() external view returns (uint256);

    /// @notice Set the oracle address
    /// @param _oracleAddress Address of the oracle
    function setOracle(address _oracleAddress) external;

    /// @notice Sets the validator count and validator total balance sum reported by the oracle
    /// @dev Can only be called by the oracle address
    /// @dev The round id is a blackbox value that should only be used to identify unique reports
    /// @dev When a report is performed, River computes the amount of fees that can be pulled
    /// @dev from the execution layer fee recipient. This amount is capped by the max allowed
    /// @dev increase provided during the report.
    /// @dev If the total asset balance increases (from the reported total balance and the pulled funds)
    /// @dev we then compute the share that must be taken for the collector on the positive delta.
    /// @dev The execution layer fees are taken into account here because they are the product of
    /// @dev node operator's work, just like consensus layer fees, and both should be handled in the
    /// @dev same manner, as a single revenue stream for the users and the collector.
    /// @param _validatorCount The number of active validators on the consensus layer
    /// @param _validatorTotalBalance The balance sum of the active validators on the consensus layer
    /// @param _roundId An identifier for this update
    /// @param _maxIncrease The maximum allowed increase in the total balance
    function setConsensusLayerData(
        uint256 _validatorCount,
        uint256 _validatorTotalBalance,
        bytes32 _roundId,
        uint256 _maxIncrease
    ) external;
}

File 16 of 45 : ISharesManager.1.sol
//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.10;

import "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";

/// @title Shares Manager Interface (v1)
/// @author Kiln
/// @notice This interface exposes methods to handle the shares of the depositor and the ERC20 interface
interface ISharesManagerV1 is IERC20 {
    /// @notice Balance too low to perform operation
    error BalanceTooLow();

    /// @notice Allowance too low to perform operation
    /// @param _from Account where funds are sent from
    /// @param _operator Account attempting the transfer
    /// @param _allowance Current allowance
    /// @param _value Requested transfer value in shares
    error AllowanceTooLow(address _from, address _operator, uint256 _allowance, uint256 _value);

    /// @notice Invalid empty transfer
    error NullTransfer();

    /// @notice Invalid transfer recipients
    /// @param _from Account sending the funds in the invalid transfer
    /// @param _to Account receiving the funds in the invalid transfer
    error UnauthorizedTransfer(address _from, address _to);

    /// @notice Retrieve the token name
    /// @return The token name
    function name() external pure returns (string memory);

    /// @notice Retrieve the token symbol
    /// @return The token symbol
    function symbol() external pure returns (string memory);

    /// @notice Retrieve the decimal count
    /// @return The decimal count
    function decimals() external pure returns (uint8);

    /// @notice Retrieve the total token supply
    /// @return The total supply in shares
    function totalSupply() external view returns (uint256);

    /// @notice Retrieve the total underlying asset supply
    /// @return The total underlying asset supply
    function totalUnderlyingSupply() external view returns (uint256);

    /// @notice Retrieve the balance of an account
    /// @param _owner Address to be checked
    /// @return The balance of the account in shares
    function balanceOf(address _owner) external view returns (uint256);

    /// @notice Retrieve the underlying asset balance of an account
    /// @param _owner Address to be checked
    /// @return The underlying balance of the account
    function balanceOfUnderlying(address _owner) external view returns (uint256);

    /// @notice Retrieve the underlying asset balance from an amount of shares
    /// @param _shares Amount of shares to convert
    /// @return The underlying asset balance represented by the shares
    function underlyingBalanceFromShares(uint256 _shares) external view returns (uint256);

    /// @notice Retrieve the shares count from an underlying asset amount
    /// @param _underlyingAssetAmount Amount of underlying asset to convert
    /// @return The amount of shares worth the underlying asset amopunt
    function sharesFromUnderlyingBalance(uint256 _underlyingAssetAmount) external view returns (uint256);

    /// @notice Retrieve the allowance value for a spender
    /// @param _owner Address that issued the allowance
    /// @param _spender Address that received the allowance
    /// @return The allowance in shares for a given spender
    function allowance(address _owner, address _spender) external view returns (uint256);

    /// @notice Performs a transfer from the message sender to the provided account
    /// @param _to Address receiving the tokens
    /// @param _value Amount of shares to be sent
    /// @return True if success
    function transfer(address _to, uint256 _value) external returns (bool);

    /// @notice Performs a transfer between two recipients
    /// @param _from Address sending the tokens
    /// @param _to Address receiving the tokens
    /// @param _value Amount of shares to be sent
    /// @return True if success
    function transferFrom(address _from, address _to, uint256 _value) external returns (bool);

    /// @notice Approves an account for future spendings
    /// @dev An approved account can use transferFrom to transfer funds on behalf of the token owner
    /// @param _spender Address that is allowed to spend the tokens
    /// @param _value The allowed amount in shares, will override previous value
    /// @return True if success
    function approve(address _spender, uint256 _value) external returns (bool);

    /// @notice Increase allowance to another account
    /// @param _spender Spender that receives the allowance
    /// @param _additionalValue Amount of shares to add
    /// @return True if success
    function increaseAllowance(address _spender, uint256 _additionalValue) external returns (bool);

    /// @notice Decrease allowance to another account
    /// @param _spender Spender that receives the allowance
    /// @param _subtractableValue Amount of shares to subtract
    /// @return True if success
    function decreaseAllowance(address _spender, uint256 _subtractableValue) external returns (bool);
}

File 17 of 45 : IUserDepositManager.1.sol
//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.10;

/// @title User Deposit Manager (v1)
/// @author Kiln
/// @notice This interface exposes methods to handle the inbound transfers cases or the explicit submissions
interface IUserDepositManagerV1 {
    /// @notice User deposited ETH in the system
    /// @param depositor Address performing the deposit
    /// @param recipient Address receiving the minted shares
    /// @param amount Amount in ETH deposited
    event UserDeposit(address indexed depositor, address indexed recipient, uint256 amount);

    /// @notice And empty deposit attempt was made
    error EmptyDeposit();

    /// @notice Explicit deposit method to mint on msg.sender
    function deposit() external payable;

    /// @notice Explicit deposit method to mint on msg.sender and transfer to _recipient
    /// @param _recipient Address receiving the minted LsETH
    function depositAndTransfer(address _recipient) external payable;

    /// @notice Implicit deposit method, when the user performs a regular transfer to the contract
    receive() external payable;

    /// @notice Invalid call, when the user sends a transaction with a data payload but no method matched
    fallback() external payable;
}

File 18 of 45 : LibAdministrable.sol
//SPDX-License-Identifier: MIT
pragma solidity 0.8.10;

import "../state/shared/AdministratorAddress.sol";
import "../state/shared/PendingAdministratorAddress.sol";

/// @title Lib Administrable
/// @author Kiln
/// @notice This library handles the admin and pending admin storage vars
library LibAdministrable {
    /// @notice Retrieve the system admin
    /// @return The address of the system admin
    function _getAdmin() internal view returns (address) {
        return AdministratorAddress.get();
    }

    /// @notice Retrieve the pending system admin
    /// @return The adress of the pending system admin
    function _getPendingAdmin() internal view returns (address) {
        return PendingAdministratorAddress.get();
    }

    /// @notice Sets the system admin
    /// @param _admin New system admin
    function _setAdmin(address _admin) internal {
        AdministratorAddress.set(_admin);
    }

    /// @notice Sets the pending system admin
    /// @param _pendingAdmin New pending system admin
    function _setPendingAdmin(address _pendingAdmin) internal {
        PendingAdministratorAddress.set(_pendingAdmin);
    }
}

File 19 of 45 : LibBasisPoints.sol
//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.10;

/// @title Lib Basis Points
/// @notice Holds the basis points max value
library LibBasisPoints {
    /// @notice The max value for basis points (represents 100%)
    uint256 internal constant BASIS_POINTS_MAX = 10_000;
}

File 20 of 45 : LibBytes.sol
//SPDX-License-Identifier: MIT
pragma solidity 0.8.10;

/// @title Lib Bytes
/// @notice This library helps manipulating bytes
library LibBytes {
    /// @notice The length overflows an uint
    error SliceOverflow();

    /// @notice The slice is outside of the initial bytes bounds
    error SliceOutOfBounds();

    /// @notice Slices the provided bytes
    /// @param _bytes Bytes to slice
    /// @param _start The starting index of the slice
    /// @param _length The length of the slice
    /// @return The slice of _bytes starting at _start of length _length
    function slice(bytes memory _bytes, uint256 _start, uint256 _length) internal pure returns (bytes memory) {
        unchecked {
            if (_length + 31 < _length) {
                revert SliceOverflow();
            }
        }
        if (_bytes.length < _start + _length) {
            revert SliceOutOfBounds();
        }

        bytes memory tempBytes;

        // solhint-disable-next-line no-inline-assembly
        assembly {
            switch iszero(_length)
            case 0 {
                // Get a location of some free memory and store it in tempBytes as
                // Solidity does for memory variables.
                tempBytes := mload(0x40)

                // The first word of the slice result is potentially a partial
                // word read from the original array. To read it, we calculate
                // the length of that partial word and start copying that many
                // bytes into the array. The first word we copy will start with
                // data we don't care about, but the last `lengthmod` bytes will
                // land at the beginning of the contents of the new array. When
                // we're done copying, we overwrite the full first word with
                // the actual length of the slice.
                let lengthmod := and(_length, 31)

                // The multiplication in the next line is necessary
                // because when slicing multiples of 32 bytes (lengthmod == 0)
                // the following copy loop was copying the origin's length
                // and then ending prematurely not copying everything it should.
                let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))
                let end := add(mc, _length)

                for {
                    // The multiplication in the next line has the same exact purpose
                    // as the one above.
                    let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)
                } lt(mc, end) {
                    mc := add(mc, 0x20)
                    cc := add(cc, 0x20)
                } { mstore(mc, mload(cc)) }

                mstore(tempBytes, _length)

                //update free-memory pointer
                //allocating the array padded to 32 bytes like the compiler does now
                mstore(0x40, and(add(mc, 31), not(31)))
            }
            //if we want a zero-length slice let's just return a zero-length array
            default {
                tempBytes := mload(0x40)
                //zero out the 32 bytes slice we are about to return
                //we need to do it because Solidity does not garbage collect
                mstore(tempBytes, 0)

                mstore(0x40, add(tempBytes, 0x20))
            }
        }

        return tempBytes;
    }
}

File 21 of 45 : LibErrors.sol
//SPDX-License-Identifier: MIT
pragma solidity 0.8.10;

/// @title Lib Errors
/// @notice Library of common errors
library LibErrors {
    /// @notice The operator is unauthorized for the caller
    /// @param caller Address performing the call
    error Unauthorized(address caller);

    /// @notice The call was invalid
    error InvalidCall();

    /// @notice The argument was invalid
    error InvalidArgument();

    /// @notice The address is zero
    error InvalidZeroAddress();

    /// @notice The string is empty
    error InvalidEmptyString();

    /// @notice The fee is invalid
    error InvalidFee();
}

File 22 of 45 : LibSanitize.sol
//SPDX-License-Identifier: MIT
pragma solidity 0.8.10;

import "./LibErrors.sol";
import "./LibBasisPoints.sol";

/// @title Lib Sanitize
/// @notice Utilities to sanitize input values
library LibSanitize {
    /// @notice Reverts if address is 0
    /// @param _address Address to check
    function _notZeroAddress(address _address) internal pure {
        if (_address == address(0)) {
            revert LibErrors.InvalidZeroAddress();
        }
    }

    /// @notice Reverts if string is empty
    /// @param _string String to check
    function _notEmptyString(string memory _string) internal pure {
        if (bytes(_string).length == 0) {
            revert LibErrors.InvalidEmptyString();
        }
    }

    /// @notice Reverts if fee is invalid
    /// @param _fee Fee to check
    function _validFee(uint256 _fee) internal pure {
        if (_fee > LibBasisPoints.BASIS_POINTS_MAX) {
            revert LibErrors.InvalidFee();
        }
    }
}

File 23 of 45 : LibUint256.sol
//SPDX-License-Identifier: MIT
pragma solidity 0.8.10;

/// @title Lib Uint256
/// @notice Utilities to perform uint operations
library LibUint256 {
    /// @notice Converts a value to little endian (64 bits)
    /// @param _value The value to convert
    /// @return result The converted value
    function toLittleEndian64(uint256 _value) internal pure returns (uint256 result) {
        result = 0;
        uint256 tempValue = _value;
        result = tempValue & 0xFF;
        tempValue >>= 8;

        result = (result << 8) | (tempValue & 0xFF);
        tempValue >>= 8;

        result = (result << 8) | (tempValue & 0xFF);
        tempValue >>= 8;

        result = (result << 8) | (tempValue & 0xFF);
        tempValue >>= 8;

        result = (result << 8) | (tempValue & 0xFF);
        tempValue >>= 8;

        result = (result << 8) | (tempValue & 0xFF);
        tempValue >>= 8;

        result = (result << 8) | (tempValue & 0xFF);
        tempValue >>= 8;

        result = (result << 8) | (tempValue & 0xFF);
        tempValue >>= 8;

        assert(0 == tempValue); // fully converted
        result <<= (24 * 8);
    }

    /// @notice Returns the minimum value
    /// @param _a First value
    /// @param _b Second value
    /// @return Smallest value between _a and _b
    function min(uint256 _a, uint256 _b) internal pure returns (uint256) {
        return (_a > _b ? _b : _a);
    }
}

File 24 of 45 : LibUnstructuredStorage.sol
// SPDX-License-Identifier:    MIT

pragma solidity 0.8.10;

/// @title Lib Unstructured Storage
/// @notice Utilities to work with unstructured storage
library LibUnstructuredStorage {
    /// @notice Retrieve a bool value at a storage slot
    /// @param _position The storage slot to retrieve
    /// @return data The bool value
    function getStorageBool(bytes32 _position) internal view returns (bool data) {
        // solhint-disable-next-line no-inline-assembly
        assembly {
            data := sload(_position)
        }
    }

    /// @notice Retrieve an address value at a storage slot
    /// @param _position The storage slot to retrieve
    /// @return data The address value
    function getStorageAddress(bytes32 _position) internal view returns (address data) {
        // solhint-disable-next-line no-inline-assembly
        assembly {
            data := sload(_position)
        }
    }

    /// @notice Retrieve a bytes32 value at a storage slot
    /// @param _position The storage slot to retrieve
    /// @return data The bytes32 value
    function getStorageBytes32(bytes32 _position) internal view returns (bytes32 data) {
        // solhint-disable-next-line no-inline-assembly
        assembly {
            data := sload(_position)
        }
    }

    /// @notice Retrieve an uint256 value at a storage slot
    /// @param _position The storage slot to retrieve
    /// @return data The uint256 value
    function getStorageUint256(bytes32 _position) internal view returns (uint256 data) {
        // solhint-disable-next-line no-inline-assembly
        assembly {
            data := sload(_position)
        }
    }

    /// @notice Sets a bool value at a storage slot
    /// @param _position The storage slot to set
    /// @param _data The bool value to set
    function setStorageBool(bytes32 _position, bool _data) internal {
        // solhint-disable-next-line no-inline-assembly
        assembly {
            sstore(_position, _data)
        }
    }

    /// @notice Sets an address value at a storage slot
    /// @param _position The storage slot to set
    /// @param _data The address value to set
    function setStorageAddress(bytes32 _position, address _data) internal {
        // solhint-disable-next-line no-inline-assembly
        assembly {
            sstore(_position, _data)
        }
    }

    /// @notice Sets a bytes32 value at a storage slot
    /// @param _position The storage slot to set
    /// @param _data The bytes32 value to set
    function setStorageBytes32(bytes32 _position, bytes32 _data) internal {
        // solhint-disable-next-line no-inline-assembly
        assembly {
            sstore(_position, _data)
        }
    }

    /// @notice Sets an uint256 value at a storage slot
    /// @param _position The storage slot to set
    /// @param _data The uint256 value to set
    function setStorageUint256(bytes32 _position, uint256 _data) internal {
        // solhint-disable-next-line no-inline-assembly
        assembly {
            sstore(_position, _data)
        }
    }
}

File 25 of 45 : Operators.sol
//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.10;

import "../../libraries/LibSanitize.sol";

/// @title Operators Storage
/// @notice Utility to manage the Operators in storage
library Operators {
    /// @notice Storage slot of the Operators
    bytes32 internal constant OPERATORS_SLOT = bytes32(uint256(keccak256("river.state.operators")) - 1);

    /// @notice The Operator structure in storage
    struct Operator {
        /// @custom:attribute True if the operator is active and allowed to operate on River
        bool active;
        /// @custom:attribute Display name of the operator
        string name;
        /// @custom:attribute Address of the operator
        address operator;
        /// @dev The following values respect this invariant:
        /// @dev     keys >= limit >= funded >= stopped

        /// @custom:attribute Staking limit of the operator
        uint256 limit;
        /// @custom:attribute The count of funded validators
        uint256 funded;
        /// @custom:attribute The total count of keys of the operator
        uint256 keys;
        /// @custom:attribute The count of stopped validators. Stopped validators are validators
        ///                   that exited the consensus layer (voluntary or slashed)
        uint256 stopped;
        uint256 latestKeysEditBlockNumber;
    }

    /// @notice The Operator structure when loaded in memory
    struct CachedOperator {
        /// @custom:attribute True if the operator is active and allowed to operate on River
        bool active;
        /// @custom:attribute Display name of the operator
        string name;
        /// @custom:attribute Address of the operator
        address operator;
        /// @custom:attribute Staking limit of the operator
        uint256 limit;
        /// @custom:attribute The count of funded validators
        uint256 funded;
        /// @custom:attribute The total count of keys of the operator
        uint256 keys;
        /// @custom:attribute The count of stopped validators
        uint256 stopped;
        /// @custom:attribute The count of stopped validators. Stopped validators are validators
        ///                   that exited the consensus layer (voluntary or slashed)
        uint256 index;
        /// @custom:attribute The amount of picked keys, buffer used before changing funded in storage
        uint256 picked;
    }

    /// @notice The structure at the storage slot
    struct SlotOperator {
        /// @custom:attribute Array containing all the operators
        Operator[] value;
    }

    /// @notice The operator was not found
    /// @param index The provided index
    error OperatorNotFound(uint256 index);

    /// @notice Retrieve the operator in storage
    /// @param _index The index of the operator
    /// @return The Operator structure
    function get(uint256 _index) internal view returns (Operator storage) {
        bytes32 slot = OPERATORS_SLOT;

        SlotOperator storage r;

        // solhint-disable-next-line no-inline-assembly
        assembly {
            r.slot := slot
        }

        if (r.value.length <= _index) {
            revert OperatorNotFound(_index);
        }

        return r.value[_index];
    }

    /// @notice Retrieve the operator count in storage
    /// @return The count of operators in storage
    function getCount() internal view returns (uint256) {
        bytes32 slot = OPERATORS_SLOT;

        SlotOperator storage r;

        // solhint-disable-next-line no-inline-assembly
        assembly {
            r.slot := slot
        }

        return r.value.length;
    }

    /// @notice Retrieve all the active operators
    /// @return The list of active operator structures
    function getAllActive() internal view returns (Operator[] memory) {
        bytes32 slot = OPERATORS_SLOT;

        SlotOperator storage r;

        // solhint-disable-next-line no-inline-assembly
        assembly {
            r.slot := slot
        }

        uint256 activeCount = 0;
        uint256 operatorCount = r.value.length;

        for (uint256 idx = 0; idx < operatorCount;) {
            if (r.value[idx].active) {
                unchecked {
                    ++activeCount;
                }
            }
            unchecked {
                ++idx;
            }
        }

        Operator[] memory activeOperators = new Operator[](activeCount);

        uint256 activeIdx = 0;
        for (uint256 idx = 0; idx < operatorCount;) {
            if (r.value[idx].active) {
                activeOperators[activeIdx] = r.value[idx];
                unchecked {
                    ++activeIdx;
                }
            }
            unchecked {
                ++idx;
            }
        }

        return activeOperators;
    }

    /// @notice Retrieve all the active and fundable operators
    /// @return The list of active and fundable operators
    function getAllFundable() internal view returns (CachedOperator[] memory) {
        bytes32 slot = OPERATORS_SLOT;

        SlotOperator storage r;

        // solhint-disable-next-line no-inline-assembly
        assembly {
            r.slot := slot
        }

        uint256 activeCount = 0;
        uint256 operatorCount = r.value.length;

        for (uint256 idx = 0; idx < operatorCount;) {
            if (_hasFundableKeys(r.value[idx])) {
                unchecked {
                    ++activeCount;
                }
            }
            unchecked {
                ++idx;
            }
        }

        CachedOperator[] memory activeOperators = new CachedOperator[](activeCount);

        uint256 activeIdx = 0;
        for (uint256 idx = 0; idx < operatorCount;) {
            Operator memory op = r.value[idx];
            if (_hasFundableKeys(op)) {
                activeOperators[activeIdx] = CachedOperator({
                    active: op.active,
                    name: op.name,
                    operator: op.operator,
                    limit: op.limit,
                    funded: op.funded,
                    keys: op.keys,
                    stopped: op.stopped,
                    index: idx,
                    picked: 0
                });
                unchecked {
                    ++activeIdx;
                }
            }
            unchecked {
                ++idx;
            }
        }

        return activeOperators;
    }

    /// @notice Add a new operator in storage
    /// @param _newOperator Value of the new operator
    /// @return The size of the operator array after the operation
    function push(Operator memory _newOperator) internal returns (uint256) {
        LibSanitize._notZeroAddress(_newOperator.operator);
        LibSanitize._notEmptyString(_newOperator.name);
        bytes32 slot = OPERATORS_SLOT;

        SlotOperator storage r;

        // solhint-disable-next-line no-inline-assembly
        assembly {
            r.slot := slot
        }

        r.value.push(_newOperator);

        return r.value.length;
    }

    /// @notice Atomic operation to set the key count and update the latestKeysEditBlockNumber field at the same time
    /// @param _index The operator index
    /// @param _newKeys The new value for the key count
    function setKeys(uint256 _index, uint256 _newKeys) internal {
        Operator storage op = get(_index);

        op.keys = _newKeys;
        op.latestKeysEditBlockNumber = block.number;
    }

    /// @notice Checks if an operator is active and has fundable keys
    /// @param _operator The operator details
    /// @return True if active and fundable
    function _hasFundableKeys(Operators.Operator memory _operator) internal pure returns (bool) {
        return (_operator.active && _operator.limit > _operator.funded);
    }
}

File 26 of 45 : AllowlistAddress.sol
//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.10;

import "../../libraries/LibUnstructuredStorage.sol";
import "../../libraries/LibSanitize.sol";

/// @title Allowlist Address Storage
/// @notice Utility to manage the Allowlist Address in storage
library AllowlistAddress {
    /// @notice Storage slot of the Allowlist Address
    bytes32 internal constant ALLOWLIST_ADDRESS_SLOT = bytes32(uint256(keccak256("river.state.allowlistAddress")) - 1);

    /// @notice Retrieve the Allowlist Address
    /// @return The Allowlist Address
    function get() internal view returns (address) {
        return LibUnstructuredStorage.getStorageAddress(ALLOWLIST_ADDRESS_SLOT);
    }

    /// @notice Sets the Allowlist Address
    /// @param _newValue New Allowlist Address
    function set(address _newValue) internal {
        LibSanitize._notZeroAddress(_newValue);
        LibUnstructuredStorage.setStorageAddress(ALLOWLIST_ADDRESS_SLOT, _newValue);
    }
}

File 27 of 45 : BalanceToDeposit.sol
//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.10;

import "../../libraries/LibUnstructuredStorage.sol";

library BalanceToDeposit {
    bytes32 internal constant BALANCE_TO_DEPOSIT_SLOT = bytes32(uint256(keccak256("river.state.balanceToDeposit")) - 1);

    function get() internal view returns (uint256) {
        return LibUnstructuredStorage.getStorageUint256(BALANCE_TO_DEPOSIT_SLOT);
    }

    function set(uint256 newValue) internal {
        LibUnstructuredStorage.setStorageUint256(BALANCE_TO_DEPOSIT_SLOT, newValue);
    }
}

File 28 of 45 : CLValidatorCount.sol
//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.10;

import "../../libraries/LibUnstructuredStorage.sol";

/// @title Consensus Layer Validator Count Storage
/// @notice Utility to manage the Consensus Layer Validator Count in storage
library CLValidatorCount {
    /// @notice Storage slot of the Consensus Layer Validator Count
    bytes32 internal constant CL_VALIDATOR_COUNT_SLOT = bytes32(uint256(keccak256("river.state.clValidatorCount")) - 1);

    /// @notice Retrieve the Consensus Layer Validator Count
    /// @return The Consensus Layer Validator Count
    function get() internal view returns (uint256) {
        return LibUnstructuredStorage.getStorageUint256(CL_VALIDATOR_COUNT_SLOT);
    }

    /// @notice Sets the Consensus Layer Validator Count
    /// @param _newValue New Consensus Layer Validator Count
    function set(uint256 _newValue) internal {
        LibUnstructuredStorage.setStorageUint256(CL_VALIDATOR_COUNT_SLOT, _newValue);
    }
}

File 29 of 45 : CLValidatorTotalBalance.sol
//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.10;

import "../../libraries/LibUnstructuredStorage.sol";

/// @title Consensus Layer Validator Total Balance Storage
/// @notice Utility to manage the Consensus Layer Validator Total Balance in storage
library CLValidatorTotalBalance {
    /// @notice Storage slot of the Consensus Layer Validator Total Balance
    bytes32 internal constant CL_VALIDATOR_TOTAL_BALANCE_SLOT =
        bytes32(uint256(keccak256("river.state.clValidatorTotalBalance")) - 1);

    /// @notice Retrieve the Consensus Layer Validator Total Balance
    /// @return The Consensus Layer Validator Total Balance
    function get() internal view returns (uint256) {
        return LibUnstructuredStorage.getStorageUint256(CL_VALIDATOR_TOTAL_BALANCE_SLOT);
    }

    /// @notice Sets the Consensus Layer Validator Total Balance
    /// @param _newValue New Consensus Layer Validator Total Balance
    function set(uint256 _newValue) internal {
        LibUnstructuredStorage.setStorageUint256(CL_VALIDATOR_TOTAL_BALANCE_SLOT, _newValue);
    }
}

File 30 of 45 : CollectorAddress.sol
//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.10;

import "../../libraries/LibUnstructuredStorage.sol";
import "../../libraries/LibSanitize.sol";

/// @title Collector Address Storage
/// @notice Utility to manage the Collector Address in storage
library CollectorAddress {
    /// @notice Storage slot of the Collector Address
    bytes32 internal constant COLLECTOR_ADDRESS_SLOT = bytes32(uint256(keccak256("river.state.collectorAddress")) - 1);

    /// @notice Retrieve the Collector Address
    /// @return The Collector Address
    function get() internal view returns (address) {
        return LibUnstructuredStorage.getStorageAddress(COLLECTOR_ADDRESS_SLOT);
    }

    /// @notice Sets the Collector Address
    /// @param _newValue New Collector Address
    function set(address _newValue) internal {
        LibSanitize._notZeroAddress(_newValue);
        LibUnstructuredStorage.setStorageAddress(COLLECTOR_ADDRESS_SLOT, _newValue);
    }
}

File 31 of 45 : DepositContractAddress.sol
//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.10;

import "../../libraries/LibSanitize.sol";
import "../../libraries/LibUnstructuredStorage.sol";

/// @title Deposit Contract Address Storage
/// @notice Utility to manage the Deposit Contract Address in storage
library DepositContractAddress {
    /// @notice Storage slot of the Deposit Contract Address
    bytes32 internal constant DEPOSIT_CONTRACT_ADDRESS_SLOT =
        bytes32(uint256(keccak256("river.state.depositContractAddress")) - 1);

    /// @notice Retrieve the Deposit Contract Address
    /// @return The Deposit Contract Address
    function get() internal view returns (address) {
        return LibUnstructuredStorage.getStorageAddress(DEPOSIT_CONTRACT_ADDRESS_SLOT);
    }

    /// @notice Sets the Deposit Contract Address
    /// @param _newValue New Deposit Contract Address
    function set(address _newValue) internal {
        LibSanitize._notZeroAddress(_newValue);
        LibUnstructuredStorage.setStorageAddress(DEPOSIT_CONTRACT_ADDRESS_SLOT, _newValue);
    }
}

File 32 of 45 : DepositedValidatorCount.sol
//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.10;

import "../../libraries/LibUnstructuredStorage.sol";

/// @title Deposited Validator Count Storage
/// @notice Utility to manage the Deposited Validator Count in storage
library DepositedValidatorCount {
    /// @notice Storage slot of the Deposited Validator Count
    bytes32 internal constant DEPOSITED_VALIDATOR_COUNT_SLOT =
        bytes32(uint256(keccak256("river.state.depositedValidatorCount")) - 1);

    /// @notice Retrieve the Deposited Validator Count
    /// @return The Deposited Validator Count
    function get() internal view returns (uint256) {
        return LibUnstructuredStorage.getStorageUint256(DEPOSITED_VALIDATOR_COUNT_SLOT);
    }

    /// @notice Sets the Deposited Validator Count
    /// @param _newValue New Deposited Validator Count
    function set(uint256 _newValue) internal {
        LibUnstructuredStorage.setStorageUint256(DEPOSITED_VALIDATOR_COUNT_SLOT, _newValue);
    }
}

File 33 of 45 : ELFeeRecipientAddress.sol
//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.10;

import "../../libraries/LibUnstructuredStorage.sol";

/// @title Execution Layer Fee Recipient Address Storage
/// @notice Utility to manage the Execution Layer Fee Recipient Address in storage
library ELFeeRecipientAddress {
    /// @notice Storage slot of the Execution Layer Fee Recipient Address
    bytes32 internal constant EL_FEE_RECIPIENT_ADDRESS =
        bytes32(uint256(keccak256("river.state.elFeeRecipientAddress")) - 1);

    /// @notice Retrieve the Execution Layer Fee Recipient Address
    /// @return The Execution Layer Fee Recipient Address
    function get() internal view returns (address) {
        return LibUnstructuredStorage.getStorageAddress(EL_FEE_RECIPIENT_ADDRESS);
    }

    /// @notice Sets the Execution Layer Fee Recipient Address
    /// @param _newValue New Execution Layer Fee Recipient Address
    function set(address _newValue) internal {
        LibUnstructuredStorage.setStorageAddress(EL_FEE_RECIPIENT_ADDRESS, _newValue);
    }
}

File 34 of 45 : GlobalFee.sol
//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.10;

import "../../libraries/LibSanitize.sol";
import "../../libraries/LibUnstructuredStorage.sol";

/// @title Global Fee Storage
/// @notice Utility to manage the Global Fee in storage
library GlobalFee {
    /// @notice Storage slot of the Global Fee
    bytes32 internal constant GLOBAL_FEE_SLOT = bytes32(uint256(keccak256("river.state.globalFee")) - 1);

    /// @notice Retrieve the Global Fee
    /// @return The Global Fee
    function get() internal view returns (uint256) {
        return LibUnstructuredStorage.getStorageUint256(GLOBAL_FEE_SLOT);
    }

    /// @notice Sets the Global Fee
    /// @param _newValue New Global Fee
    function set(uint256 _newValue) internal {
        LibSanitize._validFee(_newValue);
        LibUnstructuredStorage.setStorageUint256(GLOBAL_FEE_SLOT, _newValue);
    }
}

File 35 of 45 : LastOracleRoundId.sol
//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.10;

import "../../libraries/LibUnstructuredStorage.sol";

/// @title Last Oracle Round Id Storage
/// @notice Utility to manage the Last Oracle Round Id in storage
library LastOracleRoundId {
    /// @notice Storage slot of the Last Oracle Round Id
    bytes32 internal constant LAST_ORACLE_ROUND_ID_SLOT =
        bytes32(uint256(keccak256("river.state.lastOracleRoundId")) - 1);

    /// @notice Retrieve the Last Oracle Round Id
    /// @return The Last Oracle Round Id
    function get() internal view returns (bytes32) {
        return LibUnstructuredStorage.getStorageBytes32(LAST_ORACLE_ROUND_ID_SLOT);
    }

    /// @notice Sets the Last Oracle Round Id
    /// @param _newValue New Last Oracle Round Id
    function set(bytes32 _newValue) internal {
        LibUnstructuredStorage.setStorageBytes32(LAST_ORACLE_ROUND_ID_SLOT, _newValue);
    }
}

File 36 of 45 : OperatorsRegistryAddress.sol
//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.10;

import "../../libraries/LibUnstructuredStorage.sol";
import "../../libraries/LibSanitize.sol";

/// @title Operators Registry Address Storage
/// @notice Utility to manage the Operators Registry Address in storage
library OperatorsRegistryAddress {
    /// @notice Storage slot of the Operators Registry Address
    bytes32 internal constant OPERATORS_REGISTRY_ADDRESS_SLOT =
        bytes32(uint256(keccak256("river.state.operatorsRegistryAddress")) - 1);

    /// @notice Retrieve the Operators Registry Address
    /// @return The Operators Registry Address
    function get() internal view returns (address) {
        return LibUnstructuredStorage.getStorageAddress(OPERATORS_REGISTRY_ADDRESS_SLOT);
    }

    /// @notice Sets the Operators Registry Address
    /// @param _newValue New Operators Registry Address
    function set(address _newValue) internal {
        LibSanitize._notZeroAddress(_newValue);
        LibUnstructuredStorage.setStorageAddress(OPERATORS_REGISTRY_ADDRESS_SLOT, _newValue);
    }
}

File 37 of 45 : OracleAddress.sol
//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.10;

import "../../libraries/LibUnstructuredStorage.sol";
import "../../libraries/LibSanitize.sol";

/// @title Oracle Address Storage
/// @notice Utility to manage the Oracle Address in storage
library OracleAddress {
    /// @notice Storage slot of the Oracle Address
    bytes32 internal constant ORACLE_ADDRESS_SLOT = bytes32(uint256(keccak256("river.state.oracleAddress")) - 1);

    /// @notice Retrieve the Oracle Address
    /// @return The Oracle Address
    function get() internal view returns (address) {
        return LibUnstructuredStorage.getStorageAddress(ORACLE_ADDRESS_SLOT);
    }

    /// @notice Sets the Oracle Address
    /// @param _newValue New Oracle Address
    function set(address _newValue) internal {
        LibSanitize._notZeroAddress(_newValue);
        LibUnstructuredStorage.setStorageAddress(ORACLE_ADDRESS_SLOT, _newValue);
    }
}

File 38 of 45 : Shares.sol
//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.10;

import "../../libraries/LibUnstructuredStorage.sol";

/// @title Shares Count Storage
/// @notice Utility to manage the Shares Count in storage
library Shares {
    /// @notice Storage slot of the Shares Count
    bytes32 internal constant SHARES_SLOT = bytes32(uint256(keccak256("river.state.shares")) - 1);

    /// @notice Retrieve the Shares Count
    /// @return The Shares Count
    function get() internal view returns (uint256) {
        return LibUnstructuredStorage.getStorageUint256(SHARES_SLOT);
    }

    /// @notice Sets the Shares Count
    /// @param _newValue New Shares Count
    function set(uint256 _newValue) internal {
        LibUnstructuredStorage.setStorageUint256(SHARES_SLOT, _newValue);
    }
}

File 39 of 45 : SharesPerOwner.sol
//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.10;

/// @title Shares Per Owner Storage
/// @notice Utility to manage the Shares Per Owner in storage
library SharesPerOwner {
    /// @notice Storage slot of the Shares Per Owner
    bytes32 internal constant SHARES_PER_OWNER_SLOT = bytes32(uint256(keccak256("river.state.sharesPerOwner")) - 1);

    /// @notice Structure in storage
    struct Slot {
        /// @custom:attribute The mapping from an owner to its share count
        mapping(address => uint256) value;
    }

    /// @notice Retrieve the share count for given owner
    /// @param _owner The address to get the balance of
    /// @return The amount of shares
    function get(address _owner) internal view returns (uint256) {
        bytes32 slot = SHARES_PER_OWNER_SLOT;

        Slot storage r;

        // solhint-disable-next-line no-inline-assembly
        assembly {
            r.slot := slot
        }

        return r.value[_owner];
    }

    /// @notice Set the amount of shares for an owner
    /// @param _owner The owner of the shares to edit
    /// @param _newValue The new shares value for the owner
    function set(address _owner, uint256 _newValue) internal {
        bytes32 slot = SHARES_PER_OWNER_SLOT;

        Slot storage r;

        // solhint-disable-next-line no-inline-assembly
        assembly {
            r.slot := slot
        }

        r.value[_owner] = _newValue;
    }
}

File 40 of 45 : WithdrawalCredentials.sol
//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.10;

import "../../libraries/LibErrors.sol";
import "../../libraries/LibUnstructuredStorage.sol";

/// @title Withdrawal Credentials Storage
/// @notice Utility to manage the Withdrawal Credentials in storage
library WithdrawalCredentials {
    /// @notice Storage slot of the Withdrawal Credentials
    bytes32 internal constant WITHDRAWAL_CREDENTIALS_SLOT =
        bytes32(uint256(keccak256("river.state.withdrawalCredentials")) - 1);

    /// @notice Retrieve the Withdrawal Credentials
    /// @return The Withdrawal Credentials
    function get() internal view returns (bytes32) {
        return LibUnstructuredStorage.getStorageBytes32(WITHDRAWAL_CREDENTIALS_SLOT);
    }

    /// @notice Sets the Withdrawal Credentials
    /// @param _newValue New Withdrawal Credentials
    function set(bytes32 _newValue) internal {
        if (_newValue == bytes32(0)) {
            revert LibErrors.InvalidArgument();
        }
        LibUnstructuredStorage.setStorageBytes32(WITHDRAWAL_CREDENTIALS_SLOT, _newValue);
    }
}

File 41 of 45 : AdministratorAddress.sol
//SPDX-License-Identifier: MIT
pragma solidity 0.8.10;

import "../../libraries/LibUnstructuredStorage.sol";
import "../../libraries/LibSanitize.sol";

/// @title Administrator Address Storage
/// @notice Utility to manage the Administrator Address in storage
library AdministratorAddress {
    /// @notice Storage slot of the Administrator Address
    bytes32 public constant ADMINISTRATOR_ADDRESS_SLOT =
        bytes32(uint256(keccak256("river.state.administratorAddress")) - 1);

    /// @notice Retrieve the Administrator Address
    /// @return The Administrator Address
    function get() internal view returns (address) {
        return LibUnstructuredStorage.getStorageAddress(ADMINISTRATOR_ADDRESS_SLOT);
    }

    /// @notice Sets the Administrator Address
    /// @param _newValue New Administrator Address
    function set(address _newValue) internal {
        LibSanitize._notZeroAddress(_newValue);
        LibUnstructuredStorage.setStorageAddress(ADMINISTRATOR_ADDRESS_SLOT, _newValue);
    }
}

File 42 of 45 : ApprovalsPerOwner.sol
//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.10;

/// @title Approvals Per Owner Storage
/// @notice Utility to manage the Approvals Per Owner in storage
library ApprovalsPerOwner {
    /// @notice Storage slot of the Approvals Per Owner
    bytes32 internal constant APPROVALS_PER_OWNER_SLOT =
        bytes32(uint256(keccak256("river.state.approvalsPerOwner")) - 1);

    /// @notice The structure in storage
    struct Slot {
        /// @custom:attribute The mapping from an owner to an operator to the approval amount
        mapping(address => mapping(address => uint256)) value;
    }

    /// @notice Retrieve the approval for an owner to an operator
    /// @param _owner The account that gave the approval
    /// @param _operator The account receiving the approval
    /// @return The value of the approval
    function get(address _owner, address _operator) internal view returns (uint256) {
        bytes32 slot = APPROVALS_PER_OWNER_SLOT;

        Slot storage r;

        // solhint-disable-next-line no-inline-assembly
        assembly {
            r.slot := slot
        }

        return r.value[_owner][_operator];
    }

    /// @notice Set the approval value for an owner to an operator
    /// @param _owner The account that gives the approval
    /// @param _operator The account receiving the approval
    /// @param _newValue The value of the approval
    function set(address _owner, address _operator, uint256 _newValue) internal {
        bytes32 slot = APPROVALS_PER_OWNER_SLOT;

        Slot storage r;

        // solhint-disable-next-line no-inline-assembly
        assembly {
            r.slot := slot
        }

        r.value[_owner][_operator] = _newValue;
    }
}

File 43 of 45 : PendingAdministratorAddress.sol
//SPDX-License-Identifier: MIT
pragma solidity 0.8.10;

import "../../libraries/LibUnstructuredStorage.sol";

/// @title Pending Administrator Address Storage
/// @notice Utility to manage the Pending Administrator Address in storage
library PendingAdministratorAddress {
    /// @notice Storage slot of the Pending Administrator Address
    bytes32 public constant PENDING_ADMINISTRATOR_ADDRESS_SLOT =
        bytes32(uint256(keccak256("river.state.pendingAdministratorAddress")) - 1);

    /// @notice Retrieve the Pending Administrator Address
    /// @return The Pending Administrator Address
    function get() internal view returns (address) {
        return LibUnstructuredStorage.getStorageAddress(PENDING_ADMINISTRATOR_ADDRESS_SLOT);
    }

    /// @notice Sets the Pending Administrator Address
    /// @param _newValue New Pending Administrator Address
    function set(address _newValue) internal {
        LibUnstructuredStorage.setStorageAddress(PENDING_ADMINISTRATOR_ADDRESS_SLOT, _newValue);
    }
}

File 44 of 45 : Version.sol
//SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.10;

import "../../libraries/LibUnstructuredStorage.sol";

/// @title Version Storage
/// @notice Utility to manage the Version in storage
library Version {
    /// @notice Storage slot of the Version
    bytes32 public constant VERSION_SLOT = bytes32(uint256(keccak256("river.state.version")) - 1);

    /// @notice Retrieve the Version
    /// @return The Version
    function get() internal view returns (uint256) {
        return LibUnstructuredStorage.getStorageUint256(VERSION_SLOT);
    }

    /// @notice Sets the Version
    /// @param _newValue New Version
    function set(uint256 _newValue) internal {
        LibUnstructuredStorage.setStorageUint256(VERSION_SLOT, _newValue);
    }
}

File 45 of 45 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `from` to `to` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) external returns (bool);
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 100
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_operator","type":"address"},{"internalType":"uint256","name":"_allowance","type":"uint256"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"AllowanceTooLow","type":"error"},{"inputs":[],"name":"BalanceTooLow","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"Denied","type":"error"},{"inputs":[],"name":"EmptyDeposit","type":"error"},{"inputs":[],"name":"ErrorOnDeposit","type":"error"},{"inputs":[],"name":"InconsistentPublicKeys","type":"error"},{"inputs":[],"name":"InconsistentSignatures","type":"error"},{"inputs":[],"name":"InvalidArgument","type":"error"},{"inputs":[],"name":"InvalidCall","type":"error"},{"inputs":[],"name":"InvalidFee","type":"error"},{"inputs":[{"internalType":"uint256","name":"version","type":"uint256"},{"internalType":"uint256","name":"expectedVersion","type":"uint256"}],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"InvalidPublicKeyCount","type":"error"},{"inputs":[],"name":"InvalidSignatureCount","type":"error"},{"inputs":[{"internalType":"uint256","name":"providedValidatorCount","type":"uint256"},{"internalType":"uint256","name":"depositedValidatorCount","type":"uint256"}],"name":"InvalidValidatorCountReport","type":"error"},{"inputs":[],"name":"InvalidWithdrawalCredentials","type":"error"},{"inputs":[],"name":"InvalidZeroAddress","type":"error"},{"inputs":[],"name":"NoAvailableValidatorKeys","type":"error"},{"inputs":[],"name":"NotEnoughFunds","type":"error"},{"inputs":[],"name":"NullTransfer","type":"error"},{"inputs":[],"name":"SliceOutOfBounds","type":"error"},{"inputs":[],"name":"SliceOverflow","type":"error"},{"inputs":[{"internalType":"address","name":"caller","type":"address"}],"name":"Unauthorized","type":"error"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"}],"name":"UnauthorizedTransfer","type":"error"},{"inputs":[],"name":"ZeroMintedShares","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"validatorCount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"validatorTotalBalance","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"roundId","type":"bytes32"}],"name":"ConsensusLayerDataUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"publicKey","type":"bytes"}],"name":"FundedValidatorKey","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"version","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"cdata","type":"bytes"}],"name":"Initialize","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"PulledELFees","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_collector","type":"address"},{"indexed":false,"internalType":"uint256","name":"_oldTotalUnderlyingBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_oldTotalSupply","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newTotalUnderlyingBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_newTotalSupply","type":"uint256"}],"name":"RewardsEarned","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"}],"name":"SetAdmin","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"allowlist","type":"address"}],"name":"SetAllowlist","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"collector","type":"address"}],"name":"SetCollector","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"depositContract","type":"address"}],"name":"SetDepositContractAddress","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"elFeeRecipient","type":"address"}],"name":"SetELFeeRecipient","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"}],"name":"SetGlobalFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operatorRegistry","type":"address"}],"name":"SetOperatorsRegistry","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oracleAddress","type":"address"}],"name":"SetOracle","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingAdmin","type":"address"}],"name":"SetPendingAdmin","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"withdrawalCredentials","type":"bytes32"}],"name":"SetWithdrawalCredentials","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"depositor","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"UserDeposit","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"DEPOSIT_SIZE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PUBLIC_KEY_LENGTH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SIGNATURE_LENGTH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"balanceOfUnderlying","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_subtractableValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"deposit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_recipient","type":"address"}],"name":"depositAndTransfer","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxCount","type":"uint256"}],"name":"depositToConsensusLayer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllowlist","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBalanceToDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCLValidatorCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCLValidatorTotalBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCollector","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDepositedValidatorCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getELFeeRecipient","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getGlobalFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOperatorsRegistry","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOracle","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPendingAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWithdrawalCredentials","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_additionalValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_depositContractAddress","type":"address"},{"internalType":"address","name":"_elFeeRecipientAddress","type":"address"},{"internalType":"bytes32","name":"_withdrawalCredentials","type":"bytes32"},{"internalType":"address","name":"_oracleAddress","type":"address"},{"internalType":"address","name":"_systemAdministratorAddress","type":"address"},{"internalType":"address","name":"_allowlistAddress","type":"address"},{"internalType":"address","name":"_operatorRegistryAddress","type":"address"},{"internalType":"address","name":"_collectorAddress","type":"address"},{"internalType":"uint256","name":"_globalFee","type":"uint256"}],"name":"initRiverV1","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_newAdmin","type":"address"}],"name":"proposeAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sendELFees","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_newAllowlist","type":"address"}],"name":"setAllowlist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newCollector","type":"address"}],"name":"setCollector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_validatorCount","type":"uint256"},{"internalType":"uint256","name":"_validatorTotalBalance","type":"uint256"},{"internalType":"bytes32","name":"_roundId","type":"bytes32"},{"internalType":"uint256","name":"_maxIncrease","type":"uint256"}],"name":"setConsensusLayerData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newELFeeRecipient","type":"address"}],"name":"setELFeeRecipient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newFee","type":"uint256"}],"name":"setGlobalFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_oracleAddress","type":"address"}],"name":"setOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_underlyingAssetAmount","type":"uint256"}],"name":"sharesFromUnderlyingBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalUnderlyingSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_shares","type":"uint256"}],"name":"underlyingBalanceFromShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]

608060405234801561001057600080fd5b50613054806100206000396000f3fe60806040526004361061026b5760003560e01c80635639671511610144578063a9059cbb116100b6578063d04681561161007a578063d0468156146106e6578063d0e30db0146106fb578063dd62ed3e14610703578063efd6034714610723578063f79c3f021461072b578063fb5b82d01461074b5761027b565b8063a9059cbb14610669578063ac232bde14610689578063bf15af561461069c578063c5eff3d0146106b1578063cc48cd31146106c65761027b565b80637adbf973116101085780637adbf973146105bc578063833b1fce146105dc57806387f2adfb146105f157806395d89b41146106065780639b498e2614610634578063a457c2d7146106495761027b565b8063563967151461053257806358bf3c7f146105475780636e9960c31461056757806370a082311461057c578063799a19541461059c5761027b565b806323b872dd116101dd57806336bf3325116101a157806336bf33251461049657806339509351146104b35780633af9e669146104d357806346425ef0146104f35780635022820114610508578063540bc5ea1461051d5761027b565b806323b872dd146103f8578063281a312214610418578063291206f6146104385780632cb562e114610458578063313ce5671461047a5761027b565b80631311cf8d1161022f5780631311cf8d1461035957806313d86aed14610379578063143a08d414610399578063147bf6c4146103ae57806318160ddd146103ce5780631bcbfaba146103e35761027b565b806304843a171461029457806306fdde03146102bc578063095ea7b3146102ff5780630e18b6811461032f578063107d7fa0146103445761027b565b3661027b576102793361076b565b005b60405163574b16a760e11b815260040160405180910390fd5b3480156102a057600080fd5b506102a96107f2565b6040519081526020015b60405180910390f35b3480156102c857600080fd5b50604080518082019091526011815270098d2e2ead2c840a6e8c2d6cac8408aa89607b1b60208201525b6040516102b39190612ad7565b34801561030b57600080fd5b5061031f61031a366004612b06565b610801565b60405190151581526020016102b3565b34801561033b57600080fd5b50610279610817565b34801561035057600080fd5b506102a9610877565b34801561036557600080fd5b50610279610374366004612b30565b610881565b34801561038557600080fd5b50610279610394366004612b4b565b6108fc565b3480156103a557600080fd5b506102a9610ab5565b3480156103ba57600080fd5b506102796103c9366004612b30565b610abf565b3480156103da57600080fd5b506102a9610b06565b3480156103ef57600080fd5b506102a9610b10565b34801561040457600080fd5b5061031f610413366004612b64565b610b1a565b34801561042457600080fd5b50610279610433366004612ba0565b610bcd565b34801561044457600080fd5b50610279610453366004612b4b565b610daf565b34801561046457600080fd5b5061046d610e29565b6040516102b39190612c3a565b34801561048657600080fd5b50604051601281526020016102b3565b3480156104a257600080fd5b506102a96801bc16d674ec80000081565b3480156104bf57600080fd5b5061031f6104ce366004612b06565b610e33565b3480156104df57600080fd5b506102a96104ee366004612b30565b610e54565b3480156104ff57600080fd5b506102a9610e6d565b34801561051457600080fd5b5061046d610e77565b34801561052957600080fd5b506102a9606081565b34801561053e57600080fd5b506102a9610e81565b34801561055357600080fd5b50610279610562366004612b30565b610e8b565b34801561057357600080fd5b5061046d610f06565b34801561058857600080fd5b506102a9610597366004612b30565b610f10565b3480156105a857600080fd5b506102a96105b7366004612b4b565b610f1b565b3480156105c857600080fd5b506102796105d7366004612b30565b610f26565b3480156105e857600080fd5b5061046d610fa1565b3480156105fd57600080fd5b506102a9610fab565b34801561061257600080fd5b50604080518082019091526005815264098e68aa8960db1b60208201526102f2565b34801561064057600080fd5b5061046d610fb5565b34801561065557600080fd5b5061031f610664366004612b06565b610fbf565b34801561067557600080fd5b5061031f610684366004612b06565b610fdb565b610279610697366004612b30565b61107a565b3480156106a857600080fd5b506102a9603081565b3480156106bd57600080fd5b5061046d61108c565b3480156106d257600080fd5b506102796106e1366004612c4e565b611096565b3480156106f257600080fd5b5061046d611210565b61027961121a565b34801561070f57600080fd5b506102a961071e366004612c80565b611223565b610279611236565b34801561073757600080fd5b506102a9610746366004612b4b565b611271565b34801561075757600080fd5b50610279610766366004612b30565b61127c565b34610789576040516395b66fe960e01b815260040160405180910390fd5b6107a4346107956112f7565b61079f9190612cc9565b61132b565b6107af33823461135e565b6040513481526001600160a01b0382169033907f3bc57f469ad6d10d7723ea226cd22bd2b9e527def2b529f6ab44645a166895829060200160405180910390a350565b60006107fc6112f7565b905090565b600061080e3384846114f8565b50600192915050565b61081f611567565b6001600160a01b0316336001600160a01b03161461085b573360405163472511eb60e11b81526004016108529190612c3a565b60405180910390fd5b61086b610866611567565b611571565b61087560006115ba565b565b60006107fc6115fa565b61088961162a565b6001600160a01b0316336001600160a01b0316146108bc573360405163472511eb60e11b81526004016108529190612c3a565b6108c581611634565b6040516001600160a01b038216907f1da4c245099590dc40be61880c9b97792f3694d970acc1e67ac0e6cc90f3780d90600090a250565b610904611662565b6001600160a01b0316336001600160a01b031614610937573360405163472511eb60e11b81526004016108529190612c3a565b60006109416112f7565b9050600061096161095b6801bc16d674ec80000084612ce1565b8461166c565b90508061098157604051631036b5ad60e31b815260040160405180910390fd5b60008061098d83611681565b81519193509150806109b25760405163200149ad60e21b815260040160405180910390fd5b838111156109d357604051635993bd5760e01b815260040160405180910390fd5b81518181146109f5576040516322e5ce4360e21b815260040160405180910390fd5b60006109ff611709565b905080610a1f57604051639be7315960e01b815260040160405180910390fd5b60005b83811015610a6f57610a67868281518110610a3f57610a3f612d03565b6020026020010151868381518110610a5957610a59612d03565b602002602001015184611739565b600101610a22565b50610a90610a86846801bc16d674ec800000612d19565b61079f9089612d38565b610aab83610a9c611bc1565b610aa69190612cc9565b611bf1565b5050505050505050565b60006107fc611c1f565b610ac761162a565b6001600160a01b0316336001600160a01b031614610afa573360405163472511eb60e11b81526004016108529190612c3a565b610b03816115ba565b50565b60006107fc611c99565b60006107fc611ca3565b60008383610b288282611cd3565b8380610b47576040516336b216db60e21b815260040160405180910390fd5b868580610b5383611dff565b1015610b72576040516351940b3960e11b815260040160405180910390fd5b6001600160a01b038816610bab57604051637617407560e11b81526001600160a01b038a16600482015260006024820152604401610852565b610bb58988611e0a565b610bc0898989611e70565b9998505050505050505050565b6000610bd7611efe565b8114610c085780610be6611efe565b604051631cfd276760e31b815260048101929092526024820152604401610852565b610c1b610c16826001612cc9565b611f2e565b610c2486611571565b610c2d83611f5c565b6040516001600160a01b038416907f0cc5437d7c9c1d9eab549acbb533eea3e9868e9443dd75309ed5820b33a3774e90600090a2610c6a82611f93565b6040518281527fbd533e726baaf59b36f3914d950053f7e78f527057c97cd3f0043257fc0fc8849060200160405180910390a1610ca689611634565b6040516001600160a01b038a16907f1da4c245099590dc40be61880c9b97792f3694d970acc1e67ac0e6cc90f3780d90600090a2610ce385611fca565b6040516001600160a01b038616907f30f015a5d3c72c0a9414538199baa022323a483fa9e4ba2cd581596cf8ca042490600090a2610d2084612001565b6040516001600160a01b038516907fffc0721ef0563a1b0a51a0dc92113025f33ca434ada9ee3eebff2f385d2a8f9a90600090a2610d5e8a89612038565b610d6787610f61565b7f1809e49bba43f2d39fa57894b50cd6ccb428cc438230e065cac3eb24a1355a7181600036604051610d9b93929190612d4f565b60405180910390a150505050505050505050565b610db761162a565b6001600160a01b0316336001600160a01b031614610dea573360405163472511eb60e11b81526004016108529190612c3a565b610df381611f93565b6040518181527fbd533e726baaf59b36f3914d950053f7e78f527057c97cd3f0043257fc0fc8849060200160405180910390a150565b60006107fc6120b4565b600061080e338484610e4533886120e4565b610e4f9190612cc9565b6114f8565b6000610e67610e628361213c565b61218a565b92915050565b60006107fc6121c2565b60006107fc6121f2565b60006107fc611709565b610e9361162a565b6001600160a01b0316336001600160a01b031614610ec6573360405163472511eb60e11b81526004016108529190612c3a565b610ecf81611fca565b6040516001600160a01b038216907f30f015a5d3c72c0a9414538199baa022323a483fa9e4ba2cd581596cf8ca042490600090a250565b60006107fc61162a565b6000610e6782611dff565b6000610e6782612222565b610f2e611662565b6001600160a01b0316336001600160a01b031614610f61573360405163472511eb60e11b81526004016108529190612c3a565b610f6a8161224f565b6040516001600160a01b038216907fd3b5d1e0ffaeff528910f3663f0adace7694ab8241d58e17a91351ced2e0803190600090a250565b60006107fc612286565b60006107fc611bc1565b60006107fc6122b6565b600061080e338484610fd133886120e4565b610e4f9190612d38565b60003383610fe98282611cd3565b8380611008576040516336b216db60e21b815260040160405180910390fd5b33858061101483611dff565b1015611033576040516351940b3960e11b815260040160405180910390fd5b6001600160a01b03881661106357604051637617407560e11b815233600482015260006024820152604401610852565b61106e338989611e70565b98975050505050505050565b611083816122e6565b610b038161076b565b60006107fc61230d565b61109e612286565b6001600160a01b0316336001600160a01b0316146110d1573360405163472511eb60e11b81526004016108529190612c3a565b6110d9611bc1565b84111561110b57836110e9611bc1565b6040516376179ac560e01b815260048101929092526024820152604401610852565b60006111156115fa565b61111f9086612d38565b90506000611136826801bc16d674ec800000612d19565b61113e6121c2565b6111489190612cc9565b90506111538561233d565b61115c8661236b565b61116584612399565b6000856111728386612cc9565b111561119857611195866111868487612cc9565b6111909190612d38565b6123c7565b90505b6111a28187612cc9565b8210156111c6576111c6826111b78389612cc9565b6111c19190612d38565b61249e565b60408051888152602081018890529081018690527f25d7358447891786a139ae7149548f3232a8c95f2ea6065c69c5bd7c39cd386c9060600160405180910390a150505050505050565b60006107fc611567565b6108753361076b565b600061122f83836120e4565b9392505050565b61123e6120b4565b6001600160a01b0316336001600160a01b031614610875573360405163472511eb60e11b81526004016108529190612c3a565b6000610e678261218a565b61128461162a565b6001600160a01b0316336001600160a01b0316146112b7573360405163472511eb60e11b81526004016108529190612c3a565b6112c081611f5c565b6040516001600160a01b038216907f0cc5437d7c9c1d9eab549acbb533eea3e9868e9443dd75309ed5820b33a3774e90600090a250565b60006107fc61132760017f2b6136e423ab70d76431e2a635e877e16ea2dd9a895e054ad7f35f89d6c7b711612d38565b5490565b610b0361135960017f2b6136e423ab70d76431e2a635e877e16ea2dd9a895e054ad7f35f89d6c7b711612d38565b829055565b600061136a84836125d0565b9050600061137661230d565b9050836001600160a01b0316856001600160a01b031614156113f757604051632d20488160e11b81526001600160a01b03868116600483015260016024830152821690635a4091029060440160006040518083038186803b1580156113da57600080fd5b505afa1580156113ee573d6000803e3d6000fd5b505050506114f1565b604051632d20488160e11b81526001600160a01b03868116600483015260016024830152821690635a4091029060440160006040518083038186803b15801561143f57600080fd5b505afa158015611453573d6000803e3d6000fd5b505060405163e838dfbb60e01b81526001600160a01b038416925063e838dfbb9150611483908790600401612c3a565b602060405180830381865afa1580156114a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114c49190612d85565b156114e4578360405163e7d05e2760e01b81526004016108529190612c3a565b6114ef858584611e70565b505b5050505050565b611501836122e6565b61150a826122e6565b61151583838361262f565b816001600160a01b0316836001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258360405161155a91815260200190565b60405180910390a3505050565b60006107fc612686565b61157a816122e6565b611583816126b6565b6040516001600160a01b038216907f5a272403b402d892977df56625f4164ccaf70ca3863991c43ecfe76a6905b0a190600090a250565b6115c3816126bf565b6040516001600160a01b038216907f2a0f8515de3fa34ef68b99300347b8793c01683350743e96fe440594528298f490600090a250565b60006107fc61132760017f0f1e7733641e4d843128fea0d2ec90d3d06a40b0fe244ff603d8c1aa200dc0f9612d38565b60006107fc6126c8565b610b0361135960017f8e9e2a1d30fed357d8a000c1131fc77ed65d2052918caf1ccc6eb1e7af3d13b6612d38565b60006107fc610f06565b600081831161167b578261122f565b50919050565b60608061168c6122b6565b6001600160a01b031663a1947323846040518263ffffffff1660e01b81526004016116b991815260200190565b6000604051808303816000875af11580156116d8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526117009190810190612ed3565b91509150915091565b60006107fc61132760017fb649e50315f962b32d487e696a81b4828631b11f8424daaaa37e9e97766a2c42612d38565b603083511461175b5760405163050cb55360e41b815260040160405180910390fd5b606082511461177d5760405163408ebd3960e01b815260040160405180910390fd5b6801bc16d674ec8000006000611797633b9aca0083612ce1565b90506000600286600060801b6040516020016117b4929190612f37565b60408051601f19818403018152908290526117ce91612f66565b602060405180830381855afa1580156117eb573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061180e9190612f82565b9050600060028061182288600060406126f8565b60405161182f9190612f66565b602060405180830381855afa15801561184c573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061186f9190612f82565b6002611887896040611882816060612d38565b6126f8565b60405161189a9190600090602001612f9b565b60408051601f19818403018152908290526118b491612f66565b602060405180830381855afa1580156118d1573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906118f49190612f82565b60408051602081019390935282015260600160408051601f198184030181529082905261192091612f66565b602060405180830381855afa15801561193d573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906119609190612f82565b905060006002808488604051602001611983929190918252602082015260400190565b60408051601f198184030181529082905261199d91612f66565b602060405180830381855afa1580156119ba573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906119dd9190612f82565b60026119e8876127bb565b604080516020810192909252810186905260600160408051601f1981840301815290829052611a1691612f66565b602060405180830381855afa158015611a33573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190611a569190612f82565b60408051602081019390935282015260600160408051601f1981840301815290829052611a8291612f66565b602060405180830381855afa158015611a9f573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190611ac29190612f82565b90506000611ad08647612d38565b9050611ada612828565b6001600160a01b03166322895118878b8a604051602001611afd91815260200190565b6040516020818303038152906040528c876040518663ffffffff1660e01b8152600401611b2d9493929190612fbd565b6000604051808303818588803b158015611b4657600080fd5b505af1158015611b5a573d6000803e3d6000fd5b5050505050804714611b7f57604051638051a6bb60e01b815260040160405180910390fd5b7f11553d182c6d24df901ccbb837d640c1ee9994876a88dccc8ddfd7ebab9b6ce189604051611bae9190612ad7565b60405180910390a1505050505050505050565b60006107fc61132760017fc77078e3530c08cdb2440817c81de4836500b4708ea4d15672b7fe98956423a8612d38565b610b0361135960017fc77078e3530c08cdb2440817c81de4836500b4708ea4d15672b7fe98956423a8612d38565b600080611c2a6115fa565b90506000611c36611bc1565b905080821015611c89576801bc16d674ec800000611c548383612d38565b611c5e9190612d19565b611c666112f7565b611c6e6121c2565b611c789190612cc9565b611c829190612cc9565b9250505090565b611c916112f7565b611c786121c2565b60006107fc612858565b60006107fc61132760017f094efef62d2ce60c14ffacd35a1b50546d3a9d503aff1df040176fffd6c92a37612d38565b6000611cdd61230d565b60405163e838dfbb60e01b81529091506001600160a01b0382169063e838dfbb90611d0c908690600401612c3a565b602060405180830381865afa158015611d29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d4d9190612d85565b15611d6d578260405163e7d05e2760e01b81526004016108529190612c3a565b60405163e838dfbb60e01b81526001600160a01b0382169063e838dfbb90611d99908590600401612c3a565b602060405180830381865afa158015611db6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dda9190612d85565b15611dfa578160405163e7d05e2760e01b81526004016108529190612c3a565b505050565b6000610e678261213c565b6000611e1683336120e4565b905081811015611e5857604051637b936de360e01b81526001600160a01b03841660048201523360248201526044810182905260648101839052608401610852565b6000198114611dfa57611dfa8333610e4f8585612d38565b6000611e8f8483611e808761213c565b611e8a9190612d38565b612888565b611ea78383611e9d8661213c565b611e8a9190612cc9565b826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051611eec91815260200190565b60405180910390a35060019392505050565b60006107fc61132760017f82055909238c0f5e63d6f174068ebb8f51bcec9bd37de63bb68f6551feec0cfd612d38565b610b0361135960017f82055909238c0f5e63d6f174068ebb8f51bcec9bd37de63bb68f6551feec0cfd612d38565b611f65816122e6565b610b0361135960017f082b6d18de7b10e438e6b1002141db737519cb4ceed679bc815e3aac00cd2227612d38565b611f9c816128d4565b610b0361135960017f094efef62d2ce60c14ffacd35a1b50546d3a9d503aff1df040176fffd6c92a37612d38565b611fd3816122e6565b610b0361135960017f867d8f1a5e39d11d5bebde854d5359a509530ad32450f581da63c06ec8d1a780612d38565b61200a816122e6565b610b0361135960017f3f075dea7ef99b1e5db245018e5e4ed8d2a0d93953f5932b2176bef59bd69061612d38565b612041826128f7565b6040516001600160a01b038316907e043cf7635f276413ae358250286a479a631abd9d74d57d4aa0bb87ebc7d11790600090a261207d8161292e565b6040518181527f4c86ba184ea1a1558f84835ca34f6d67e222e8ee5cc4f324b8861dda4cf1740c9060200160405180910390a15050565b60006107fc61132760017f8e9e2a1d30fed357d8a000c1131fc77ed65d2052918caf1ccc6eb1e7af3d13b6612d38565b60008061211260017fc852254d5b703a16bb13b3e233a335d6459c5da5db0ca732d7a684ee05407847612d38565b6001600160a01b039485166000908152602091825260408082209590961681529390525050205490565b60008061216a60017f0fb4a5ac9287f4f508aa7253ee2d57c6a228b1b30e210d73fffd59389d3a8838612d38565b6001600160a01b0390931660009081526020939093525050604090205490565b600080612195612858565b9050806121a55750600092915050565b806121ae611c1f565b6121b89085612d19565b61122f9190612ce1565b60006107fc61132760017ffedfd2c285a57fb23bf45a3fe9ac02d36a76ebb72801b1c8aaf553d74e9d4653612d38565b60006107fc61132760017f082b6d18de7b10e438e6b1002141db737519cb4ceed679bc815e3aac00cd2227612d38565b60008061222d612858565b90508061223d5750600092915050565b612245611c1f565b6121b88285612d19565b612258816122e6565b610b0361135960017fc8cbea9407c380ae944f052b5a442330057683c5abdbd453493f9750806afecb612d38565b60006107fc61132760017fc8cbea9407c380ae944f052b5a442330057683c5abdbd453493f9750806afecb612d38565b60006107fc61132760017f3f075dea7ef99b1e5db245018e5e4ed8d2a0d93953f5932b2176bef59bd69061612d38565b6001600160a01b038116610b035760405163f6b2911f60e01b815260040160405180910390fd5b60006107fc61132760017f867d8f1a5e39d11d5bebde854d5359a509530ad32450f581da63c06ec8d1a780612d38565b610b0361135960017ffedfd2c285a57fb23bf45a3fe9ac02d36a76ebb72801b1c8aaf553d74e9d4653612d38565b610b0361135960017f0f1e7733641e4d843128fea0d2ec90d3d06a40b0fe244ff603d8c1aa200dc0f9612d38565b610b0361135960017fd7f2d45e512a86049f7a113657b39731b6b558609584243063a52cd31a8eb529612d38565b6000806123d26120b4565b90506001600160a01b0381166123eb5750600092915050565b60405163c8a6dfd360e01b81526004810184905247906001600160a01b0383169063c8a6dfd390602401600060405180830381600087803b15801561242f57600080fd5b505af1158015612443573d6000803e3d6000fd5b50505050600081476124559190612d38565b9050612463816107956112f7565b6040518181527fda841d3042d792e2509a333b9dcbd4b3dd9b9047d382011f8788fab90ca7e3c79060200160405180910390a1949350505050565b60006124a8611c99565b9050806124c857604051630d35acd760e21b815260040160405180910390fd5b60006124d2611c1f565b905060006124de611ca3565b90506000816124ed8587612d19565b6124f79190612d19565b905060006125058387612d19565b61251161271086612d19565b61251b9190612d38565b9050600081156125345761252f8284612ce1565b612537565b60005b905080156125c75760006125496121f2565b9050612555818361297a565b600061255f611c99565b9050600061256d8a89612d38565b60408051828152602081018c90529081018a9052606081018490529091506001600160a01b038416907f3d1669e813a9845c288f0e1f642a4343a451103b87886d12de37e63b39bbd9429060800160405180910390a25050505b50505050505050565b600080826125dc611c1f565b6125e69190612d38565b9050806125ff578291506125fa848461297a565b612628565b80612608611c99565b6126129085612d19565b61261c9190612ce1565b9150612628848361297a565b5092915050565b600061265c60017fc852254d5b703a16bb13b3e233a335d6459c5da5db0ca732d7a684ee05407847612d38565b6001600160a01b039485166000908152602091825260408082209590961681529390525091902055565b60006107fc61132760017f6e6ab8b7c7aaba79eef8cc633522d606bb008c101cf9832c9ad05d10a9847281612d38565b610b03816129e8565b610b0381612a1f565b60006107fc61132760017fb5b37715a3e346e996104f0086703f19825def429233930fd9399c38e05fb113612d38565b60608182601f01101561271e576040516323d5783d60e11b815260040160405180910390fd5b6127288284612cc9565b8451101561274957604051633b99b53d60e01b815260040160405180910390fd5b60608215801561276857604051915060008252602082016040526127b2565b6040519150601f8416801560200281840101858101878315602002848b0101015b818310156127a1578051835260209283019201612789565b5050858452601f01601f1916604052505b50949350505050565b603881901c60ff908116603083901c8216602884901c8316602085901c8416601886901c8516601087901c8616600888811c9790971688881b61ff001617871b17861b17851b17841b17831b1790911b17604082901c801561281f5761281f613008565b5060c01b919050565b60006107fc61132760017f35efb61d8784060218d9d6aa40eae55904de43779c1afc79c74dfefcfdf91260612d38565b60006107fc61132760017f6b842b424335d94ccad97e54548dfa02673c1268aba38d3c3c32d28c8988b70b612d38565b60006128b560017f0fb4a5ac9287f4f508aa7253ee2d57c6a228b1b30e210d73fffd59389d3a8838612d38565b6001600160a01b03909316600090815260209390935250604090912055565b612710811115610b03576040516358d620b360e01b815260040160405180910390fd5b612900816122e6565b610b0361135960017f35efb61d8784060218d9d6aa40eae55904de43779c1afc79c74dfefcfdf91260612d38565b8061294c5760405163a9cb9e0d60e01b815260040160405180910390fd5b610b0361135960017fb649e50315f962b32d487e696a81b4828631b11f8424daaaa37e9e97766a2c42612d38565b61299581612986612858565b6129909190612cc9565b612a4d565b6129a38282611e9d8561213c565b6040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b6129f1816122e6565b610b0361135960017fb5b37715a3e346e996104f0086703f19825def429233930fd9399c38e05fb113612d38565b610b0361135960017f6e6ab8b7c7aaba79eef8cc633522d606bb008c101cf9832c9ad05d10a9847281612d38565b610b0361135960017f6b842b424335d94ccad97e54548dfa02673c1268aba38d3c3c32d28c8988b70b612d38565b60005b83811015612a96578181015183820152602001612a7e565b83811115612aa5576000848401525b50505050565b60008151808452612ac3816020860160208601612a7b565b601f01601f19169290920160200192915050565b60208152600061122f6020830184612aab565b80356001600160a01b0381168114612b0157600080fd5b919050565b60008060408385031215612b1957600080fd5b612b2283612aea565b946020939093013593505050565b600060208284031215612b4257600080fd5b61122f82612aea565b600060208284031215612b5d57600080fd5b5035919050565b600080600060608486031215612b7957600080fd5b612b8284612aea565b9250612b9060208501612aea565b9150604084013590509250925092565b60008060008060008060008060006101208a8c031215612bbf57600080fd5b612bc88a612aea565b9850612bd660208b01612aea565b975060408a01359650612beb60608b01612aea565b9550612bf960808b01612aea565b9450612c0760a08b01612aea565b9350612c1560c08b01612aea565b9250612c2360e08b01612aea565b91506101008a013590509295985092959850929598565b6001600160a01b0391909116815260200190565b60008060008060808587031215612c6457600080fd5b5050823594602084013594506040840135936060013592509050565b60008060408385031215612c9357600080fd5b612c9c83612aea565b9150612caa60208401612aea565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b60008219821115612cdc57612cdc612cb3565b500190565b600082612cfe57634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052603260045260246000fd5b6000816000190483118215151615612d3357612d33612cb3565b500290565b600082821015612d4a57612d4a612cb3565b500390565b83815260406020820152816040820152818360608301376000818301606090810191909152601f909201601f1916010192915050565b600060208284031215612d9757600080fd5b8151801515811461122f57600080fd5b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612de657612de6612da7565b604052919050565b6000601f8381840112612e0057600080fd5b8251602067ffffffffffffffff80831115612e1d57612e1d612da7565b8260051b612e2c838201612dbd565b9384528681018301938381019089861115612e4657600080fd5b84890192505b85831015610bc057825184811115612e645760008081fd5b8901603f81018b13612e765760008081fd5b85810151604086821115612e8c57612e8c612da7565b612e9d828b01601f19168901612dbd565b8281528d82848601011115612eb25760008081fd5b612ec1838a8301848701612a7b565b85525050509184019190840190612e4c565b60008060408385031215612ee657600080fd5b825167ffffffffffffffff80821115612efe57600080fd5b612f0a86838701612dee565b93506020850151915080821115612f2057600080fd5b50612f2d85828601612dee565b9150509250929050565b60008351612f49818460208801612a7b565b6001600160801b0319939093169190920190815260100192915050565b60008251612f78818460208701612a7b565b9190910192915050565b600060208284031215612f9457600080fd5b5051919050565b60008351612fad818460208801612a7b565b9190910191825250602001919050565b608081526000612fd06080830187612aab565b8281036020840152612fe28187612aab565b90508281036040840152612ff68186612aab565b91505082606083015295945050505050565b634e487b7160e01b600052600160045260246000fdfea26469706673582212204c98ac4f477f06f69f4028fa9440dd9c691d20f120c69e574b4c9dd17f97219264736f6c634300080a0033

Deployed Bytecode

0x60806040526004361061026b5760003560e01c80635639671511610144578063a9059cbb116100b6578063d04681561161007a578063d0468156146106e6578063d0e30db0146106fb578063dd62ed3e14610703578063efd6034714610723578063f79c3f021461072b578063fb5b82d01461074b5761027b565b8063a9059cbb14610669578063ac232bde14610689578063bf15af561461069c578063c5eff3d0146106b1578063cc48cd31146106c65761027b565b80637adbf973116101085780637adbf973146105bc578063833b1fce146105dc57806387f2adfb146105f157806395d89b41146106065780639b498e2614610634578063a457c2d7146106495761027b565b8063563967151461053257806358bf3c7f146105475780636e9960c31461056757806370a082311461057c578063799a19541461059c5761027b565b806323b872dd116101dd57806336bf3325116101a157806336bf33251461049657806339509351146104b35780633af9e669146104d357806346425ef0146104f35780635022820114610508578063540bc5ea1461051d5761027b565b806323b872dd146103f8578063281a312214610418578063291206f6146104385780632cb562e114610458578063313ce5671461047a5761027b565b80631311cf8d1161022f5780631311cf8d1461035957806313d86aed14610379578063143a08d414610399578063147bf6c4146103ae57806318160ddd146103ce5780631bcbfaba146103e35761027b565b806304843a171461029457806306fdde03146102bc578063095ea7b3146102ff5780630e18b6811461032f578063107d7fa0146103445761027b565b3661027b576102793361076b565b005b60405163574b16a760e11b815260040160405180910390fd5b3480156102a057600080fd5b506102a96107f2565b6040519081526020015b60405180910390f35b3480156102c857600080fd5b50604080518082019091526011815270098d2e2ead2c840a6e8c2d6cac8408aa89607b1b60208201525b6040516102b39190612ad7565b34801561030b57600080fd5b5061031f61031a366004612b06565b610801565b60405190151581526020016102b3565b34801561033b57600080fd5b50610279610817565b34801561035057600080fd5b506102a9610877565b34801561036557600080fd5b50610279610374366004612b30565b610881565b34801561038557600080fd5b50610279610394366004612b4b565b6108fc565b3480156103a557600080fd5b506102a9610ab5565b3480156103ba57600080fd5b506102796103c9366004612b30565b610abf565b3480156103da57600080fd5b506102a9610b06565b3480156103ef57600080fd5b506102a9610b10565b34801561040457600080fd5b5061031f610413366004612b64565b610b1a565b34801561042457600080fd5b50610279610433366004612ba0565b610bcd565b34801561044457600080fd5b50610279610453366004612b4b565b610daf565b34801561046457600080fd5b5061046d610e29565b6040516102b39190612c3a565b34801561048657600080fd5b50604051601281526020016102b3565b3480156104a257600080fd5b506102a96801bc16d674ec80000081565b3480156104bf57600080fd5b5061031f6104ce366004612b06565b610e33565b3480156104df57600080fd5b506102a96104ee366004612b30565b610e54565b3480156104ff57600080fd5b506102a9610e6d565b34801561051457600080fd5b5061046d610e77565b34801561052957600080fd5b506102a9606081565b34801561053e57600080fd5b506102a9610e81565b34801561055357600080fd5b50610279610562366004612b30565b610e8b565b34801561057357600080fd5b5061046d610f06565b34801561058857600080fd5b506102a9610597366004612b30565b610f10565b3480156105a857600080fd5b506102a96105b7366004612b4b565b610f1b565b3480156105c857600080fd5b506102796105d7366004612b30565b610f26565b3480156105e857600080fd5b5061046d610fa1565b3480156105fd57600080fd5b506102a9610fab565b34801561061257600080fd5b50604080518082019091526005815264098e68aa8960db1b60208201526102f2565b34801561064057600080fd5b5061046d610fb5565b34801561065557600080fd5b5061031f610664366004612b06565b610fbf565b34801561067557600080fd5b5061031f610684366004612b06565b610fdb565b610279610697366004612b30565b61107a565b3480156106a857600080fd5b506102a9603081565b3480156106bd57600080fd5b5061046d61108c565b3480156106d257600080fd5b506102796106e1366004612c4e565b611096565b3480156106f257600080fd5b5061046d611210565b61027961121a565b34801561070f57600080fd5b506102a961071e366004612c80565b611223565b610279611236565b34801561073757600080fd5b506102a9610746366004612b4b565b611271565b34801561075757600080fd5b50610279610766366004612b30565b61127c565b34610789576040516395b66fe960e01b815260040160405180910390fd5b6107a4346107956112f7565b61079f9190612cc9565b61132b565b6107af33823461135e565b6040513481526001600160a01b0382169033907f3bc57f469ad6d10d7723ea226cd22bd2b9e527def2b529f6ab44645a166895829060200160405180910390a350565b60006107fc6112f7565b905090565b600061080e3384846114f8565b50600192915050565b61081f611567565b6001600160a01b0316336001600160a01b03161461085b573360405163472511eb60e11b81526004016108529190612c3a565b60405180910390fd5b61086b610866611567565b611571565b61087560006115ba565b565b60006107fc6115fa565b61088961162a565b6001600160a01b0316336001600160a01b0316146108bc573360405163472511eb60e11b81526004016108529190612c3a565b6108c581611634565b6040516001600160a01b038216907f1da4c245099590dc40be61880c9b97792f3694d970acc1e67ac0e6cc90f3780d90600090a250565b610904611662565b6001600160a01b0316336001600160a01b031614610937573360405163472511eb60e11b81526004016108529190612c3a565b60006109416112f7565b9050600061096161095b6801bc16d674ec80000084612ce1565b8461166c565b90508061098157604051631036b5ad60e31b815260040160405180910390fd5b60008061098d83611681565b81519193509150806109b25760405163200149ad60e21b815260040160405180910390fd5b838111156109d357604051635993bd5760e01b815260040160405180910390fd5b81518181146109f5576040516322e5ce4360e21b815260040160405180910390fd5b60006109ff611709565b905080610a1f57604051639be7315960e01b815260040160405180910390fd5b60005b83811015610a6f57610a67868281518110610a3f57610a3f612d03565b6020026020010151868381518110610a5957610a59612d03565b602002602001015184611739565b600101610a22565b50610a90610a86846801bc16d674ec800000612d19565b61079f9089612d38565b610aab83610a9c611bc1565b610aa69190612cc9565b611bf1565b5050505050505050565b60006107fc611c1f565b610ac761162a565b6001600160a01b0316336001600160a01b031614610afa573360405163472511eb60e11b81526004016108529190612c3a565b610b03816115ba565b50565b60006107fc611c99565b60006107fc611ca3565b60008383610b288282611cd3565b8380610b47576040516336b216db60e21b815260040160405180910390fd5b868580610b5383611dff565b1015610b72576040516351940b3960e11b815260040160405180910390fd5b6001600160a01b038816610bab57604051637617407560e11b81526001600160a01b038a16600482015260006024820152604401610852565b610bb58988611e0a565b610bc0898989611e70565b9998505050505050505050565b6000610bd7611efe565b8114610c085780610be6611efe565b604051631cfd276760e31b815260048101929092526024820152604401610852565b610c1b610c16826001612cc9565b611f2e565b610c2486611571565b610c2d83611f5c565b6040516001600160a01b038416907f0cc5437d7c9c1d9eab549acbb533eea3e9868e9443dd75309ed5820b33a3774e90600090a2610c6a82611f93565b6040518281527fbd533e726baaf59b36f3914d950053f7e78f527057c97cd3f0043257fc0fc8849060200160405180910390a1610ca689611634565b6040516001600160a01b038a16907f1da4c245099590dc40be61880c9b97792f3694d970acc1e67ac0e6cc90f3780d90600090a2610ce385611fca565b6040516001600160a01b038616907f30f015a5d3c72c0a9414538199baa022323a483fa9e4ba2cd581596cf8ca042490600090a2610d2084612001565b6040516001600160a01b038516907fffc0721ef0563a1b0a51a0dc92113025f33ca434ada9ee3eebff2f385d2a8f9a90600090a2610d5e8a89612038565b610d6787610f61565b7f1809e49bba43f2d39fa57894b50cd6ccb428cc438230e065cac3eb24a1355a7181600036604051610d9b93929190612d4f565b60405180910390a150505050505050505050565b610db761162a565b6001600160a01b0316336001600160a01b031614610dea573360405163472511eb60e11b81526004016108529190612c3a565b610df381611f93565b6040518181527fbd533e726baaf59b36f3914d950053f7e78f527057c97cd3f0043257fc0fc8849060200160405180910390a150565b60006107fc6120b4565b600061080e338484610e4533886120e4565b610e4f9190612cc9565b6114f8565b6000610e67610e628361213c565b61218a565b92915050565b60006107fc6121c2565b60006107fc6121f2565b60006107fc611709565b610e9361162a565b6001600160a01b0316336001600160a01b031614610ec6573360405163472511eb60e11b81526004016108529190612c3a565b610ecf81611fca565b6040516001600160a01b038216907f30f015a5d3c72c0a9414538199baa022323a483fa9e4ba2cd581596cf8ca042490600090a250565b60006107fc61162a565b6000610e6782611dff565b6000610e6782612222565b610f2e611662565b6001600160a01b0316336001600160a01b031614610f61573360405163472511eb60e11b81526004016108529190612c3a565b610f6a8161224f565b6040516001600160a01b038216907fd3b5d1e0ffaeff528910f3663f0adace7694ab8241d58e17a91351ced2e0803190600090a250565b60006107fc612286565b60006107fc611bc1565b60006107fc6122b6565b600061080e338484610fd133886120e4565b610e4f9190612d38565b60003383610fe98282611cd3565b8380611008576040516336b216db60e21b815260040160405180910390fd5b33858061101483611dff565b1015611033576040516351940b3960e11b815260040160405180910390fd5b6001600160a01b03881661106357604051637617407560e11b815233600482015260006024820152604401610852565b61106e338989611e70565b98975050505050505050565b611083816122e6565b610b038161076b565b60006107fc61230d565b61109e612286565b6001600160a01b0316336001600160a01b0316146110d1573360405163472511eb60e11b81526004016108529190612c3a565b6110d9611bc1565b84111561110b57836110e9611bc1565b6040516376179ac560e01b815260048101929092526024820152604401610852565b60006111156115fa565b61111f9086612d38565b90506000611136826801bc16d674ec800000612d19565b61113e6121c2565b6111489190612cc9565b90506111538561233d565b61115c8661236b565b61116584612399565b6000856111728386612cc9565b111561119857611195866111868487612cc9565b6111909190612d38565b6123c7565b90505b6111a28187612cc9565b8210156111c6576111c6826111b78389612cc9565b6111c19190612d38565b61249e565b60408051888152602081018890529081018690527f25d7358447891786a139ae7149548f3232a8c95f2ea6065c69c5bd7c39cd386c9060600160405180910390a150505050505050565b60006107fc611567565b6108753361076b565b600061122f83836120e4565b9392505050565b61123e6120b4565b6001600160a01b0316336001600160a01b031614610875573360405163472511eb60e11b81526004016108529190612c3a565b6000610e678261218a565b61128461162a565b6001600160a01b0316336001600160a01b0316146112b7573360405163472511eb60e11b81526004016108529190612c3a565b6112c081611f5c565b6040516001600160a01b038216907f0cc5437d7c9c1d9eab549acbb533eea3e9868e9443dd75309ed5820b33a3774e90600090a250565b60006107fc61132760017f2b6136e423ab70d76431e2a635e877e16ea2dd9a895e054ad7f35f89d6c7b711612d38565b5490565b610b0361135960017f2b6136e423ab70d76431e2a635e877e16ea2dd9a895e054ad7f35f89d6c7b711612d38565b829055565b600061136a84836125d0565b9050600061137661230d565b9050836001600160a01b0316856001600160a01b031614156113f757604051632d20488160e11b81526001600160a01b03868116600483015260016024830152821690635a4091029060440160006040518083038186803b1580156113da57600080fd5b505afa1580156113ee573d6000803e3d6000fd5b505050506114f1565b604051632d20488160e11b81526001600160a01b03868116600483015260016024830152821690635a4091029060440160006040518083038186803b15801561143f57600080fd5b505afa158015611453573d6000803e3d6000fd5b505060405163e838dfbb60e01b81526001600160a01b038416925063e838dfbb9150611483908790600401612c3a565b602060405180830381865afa1580156114a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114c49190612d85565b156114e4578360405163e7d05e2760e01b81526004016108529190612c3a565b6114ef858584611e70565b505b5050505050565b611501836122e6565b61150a826122e6565b61151583838361262f565b816001600160a01b0316836001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258360405161155a91815260200190565b60405180910390a3505050565b60006107fc612686565b61157a816122e6565b611583816126b6565b6040516001600160a01b038216907f5a272403b402d892977df56625f4164ccaf70ca3863991c43ecfe76a6905b0a190600090a250565b6115c3816126bf565b6040516001600160a01b038216907f2a0f8515de3fa34ef68b99300347b8793c01683350743e96fe440594528298f490600090a250565b60006107fc61132760017f0f1e7733641e4d843128fea0d2ec90d3d06a40b0fe244ff603d8c1aa200dc0f9612d38565b60006107fc6126c8565b610b0361135960017f8e9e2a1d30fed357d8a000c1131fc77ed65d2052918caf1ccc6eb1e7af3d13b6612d38565b60006107fc610f06565b600081831161167b578261122f565b50919050565b60608061168c6122b6565b6001600160a01b031663a1947323846040518263ffffffff1660e01b81526004016116b991815260200190565b6000604051808303816000875af11580156116d8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526117009190810190612ed3565b91509150915091565b60006107fc61132760017fb649e50315f962b32d487e696a81b4828631b11f8424daaaa37e9e97766a2c42612d38565b603083511461175b5760405163050cb55360e41b815260040160405180910390fd5b606082511461177d5760405163408ebd3960e01b815260040160405180910390fd5b6801bc16d674ec8000006000611797633b9aca0083612ce1565b90506000600286600060801b6040516020016117b4929190612f37565b60408051601f19818403018152908290526117ce91612f66565b602060405180830381855afa1580156117eb573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061180e9190612f82565b9050600060028061182288600060406126f8565b60405161182f9190612f66565b602060405180830381855afa15801561184c573d6000803e3d6000fd5b5050506040513d601f19601f8201168201806040525081019061186f9190612f82565b6002611887896040611882816060612d38565b6126f8565b60405161189a9190600090602001612f9b565b60408051601f19818403018152908290526118b491612f66565b602060405180830381855afa1580156118d1573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906118f49190612f82565b60408051602081019390935282015260600160408051601f198184030181529082905261192091612f66565b602060405180830381855afa15801561193d573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906119609190612f82565b905060006002808488604051602001611983929190918252602082015260400190565b60408051601f198184030181529082905261199d91612f66565b602060405180830381855afa1580156119ba573d6000803e3d6000fd5b5050506040513d601f19601f820116820180604052508101906119dd9190612f82565b60026119e8876127bb565b604080516020810192909252810186905260600160408051601f1981840301815290829052611a1691612f66565b602060405180830381855afa158015611a33573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190611a569190612f82565b60408051602081019390935282015260600160408051601f1981840301815290829052611a8291612f66565b602060405180830381855afa158015611a9f573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190611ac29190612f82565b90506000611ad08647612d38565b9050611ada612828565b6001600160a01b03166322895118878b8a604051602001611afd91815260200190565b6040516020818303038152906040528c876040518663ffffffff1660e01b8152600401611b2d9493929190612fbd565b6000604051808303818588803b158015611b4657600080fd5b505af1158015611b5a573d6000803e3d6000fd5b5050505050804714611b7f57604051638051a6bb60e01b815260040160405180910390fd5b7f11553d182c6d24df901ccbb837d640c1ee9994876a88dccc8ddfd7ebab9b6ce189604051611bae9190612ad7565b60405180910390a1505050505050505050565b60006107fc61132760017fc77078e3530c08cdb2440817c81de4836500b4708ea4d15672b7fe98956423a8612d38565b610b0361135960017fc77078e3530c08cdb2440817c81de4836500b4708ea4d15672b7fe98956423a8612d38565b600080611c2a6115fa565b90506000611c36611bc1565b905080821015611c89576801bc16d674ec800000611c548383612d38565b611c5e9190612d19565b611c666112f7565b611c6e6121c2565b611c789190612cc9565b611c829190612cc9565b9250505090565b611c916112f7565b611c786121c2565b60006107fc612858565b60006107fc61132760017f094efef62d2ce60c14ffacd35a1b50546d3a9d503aff1df040176fffd6c92a37612d38565b6000611cdd61230d565b60405163e838dfbb60e01b81529091506001600160a01b0382169063e838dfbb90611d0c908690600401612c3a565b602060405180830381865afa158015611d29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d4d9190612d85565b15611d6d578260405163e7d05e2760e01b81526004016108529190612c3a565b60405163e838dfbb60e01b81526001600160a01b0382169063e838dfbb90611d99908590600401612c3a565b602060405180830381865afa158015611db6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dda9190612d85565b15611dfa578160405163e7d05e2760e01b81526004016108529190612c3a565b505050565b6000610e678261213c565b6000611e1683336120e4565b905081811015611e5857604051637b936de360e01b81526001600160a01b03841660048201523360248201526044810182905260648101839052608401610852565b6000198114611dfa57611dfa8333610e4f8585612d38565b6000611e8f8483611e808761213c565b611e8a9190612d38565b612888565b611ea78383611e9d8661213c565b611e8a9190612cc9565b826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051611eec91815260200190565b60405180910390a35060019392505050565b60006107fc61132760017f82055909238c0f5e63d6f174068ebb8f51bcec9bd37de63bb68f6551feec0cfd612d38565b610b0361135960017f82055909238c0f5e63d6f174068ebb8f51bcec9bd37de63bb68f6551feec0cfd612d38565b611f65816122e6565b610b0361135960017f082b6d18de7b10e438e6b1002141db737519cb4ceed679bc815e3aac00cd2227612d38565b611f9c816128d4565b610b0361135960017f094efef62d2ce60c14ffacd35a1b50546d3a9d503aff1df040176fffd6c92a37612d38565b611fd3816122e6565b610b0361135960017f867d8f1a5e39d11d5bebde854d5359a509530ad32450f581da63c06ec8d1a780612d38565b61200a816122e6565b610b0361135960017f3f075dea7ef99b1e5db245018e5e4ed8d2a0d93953f5932b2176bef59bd69061612d38565b612041826128f7565b6040516001600160a01b038316907e043cf7635f276413ae358250286a479a631abd9d74d57d4aa0bb87ebc7d11790600090a261207d8161292e565b6040518181527f4c86ba184ea1a1558f84835ca34f6d67e222e8ee5cc4f324b8861dda4cf1740c9060200160405180910390a15050565b60006107fc61132760017f8e9e2a1d30fed357d8a000c1131fc77ed65d2052918caf1ccc6eb1e7af3d13b6612d38565b60008061211260017fc852254d5b703a16bb13b3e233a335d6459c5da5db0ca732d7a684ee05407847612d38565b6001600160a01b039485166000908152602091825260408082209590961681529390525050205490565b60008061216a60017f0fb4a5ac9287f4f508aa7253ee2d57c6a228b1b30e210d73fffd59389d3a8838612d38565b6001600160a01b0390931660009081526020939093525050604090205490565b600080612195612858565b9050806121a55750600092915050565b806121ae611c1f565b6121b89085612d19565b61122f9190612ce1565b60006107fc61132760017ffedfd2c285a57fb23bf45a3fe9ac02d36a76ebb72801b1c8aaf553d74e9d4653612d38565b60006107fc61132760017f082b6d18de7b10e438e6b1002141db737519cb4ceed679bc815e3aac00cd2227612d38565b60008061222d612858565b90508061223d5750600092915050565b612245611c1f565b6121b88285612d19565b612258816122e6565b610b0361135960017fc8cbea9407c380ae944f052b5a442330057683c5abdbd453493f9750806afecb612d38565b60006107fc61132760017fc8cbea9407c380ae944f052b5a442330057683c5abdbd453493f9750806afecb612d38565b60006107fc61132760017f3f075dea7ef99b1e5db245018e5e4ed8d2a0d93953f5932b2176bef59bd69061612d38565b6001600160a01b038116610b035760405163f6b2911f60e01b815260040160405180910390fd5b60006107fc61132760017f867d8f1a5e39d11d5bebde854d5359a509530ad32450f581da63c06ec8d1a780612d38565b610b0361135960017ffedfd2c285a57fb23bf45a3fe9ac02d36a76ebb72801b1c8aaf553d74e9d4653612d38565b610b0361135960017f0f1e7733641e4d843128fea0d2ec90d3d06a40b0fe244ff603d8c1aa200dc0f9612d38565b610b0361135960017fd7f2d45e512a86049f7a113657b39731b6b558609584243063a52cd31a8eb529612d38565b6000806123d26120b4565b90506001600160a01b0381166123eb5750600092915050565b60405163c8a6dfd360e01b81526004810184905247906001600160a01b0383169063c8a6dfd390602401600060405180830381600087803b15801561242f57600080fd5b505af1158015612443573d6000803e3d6000fd5b50505050600081476124559190612d38565b9050612463816107956112f7565b6040518181527fda841d3042d792e2509a333b9dcbd4b3dd9b9047d382011f8788fab90ca7e3c79060200160405180910390a1949350505050565b60006124a8611c99565b9050806124c857604051630d35acd760e21b815260040160405180910390fd5b60006124d2611c1f565b905060006124de611ca3565b90506000816124ed8587612d19565b6124f79190612d19565b905060006125058387612d19565b61251161271086612d19565b61251b9190612d38565b9050600081156125345761252f8284612ce1565b612537565b60005b905080156125c75760006125496121f2565b9050612555818361297a565b600061255f611c99565b9050600061256d8a89612d38565b60408051828152602081018c90529081018a9052606081018490529091506001600160a01b038416907f3d1669e813a9845c288f0e1f642a4343a451103b87886d12de37e63b39bbd9429060800160405180910390a25050505b50505050505050565b600080826125dc611c1f565b6125e69190612d38565b9050806125ff578291506125fa848461297a565b612628565b80612608611c99565b6126129085612d19565b61261c9190612ce1565b9150612628848361297a565b5092915050565b600061265c60017fc852254d5b703a16bb13b3e233a335d6459c5da5db0ca732d7a684ee05407847612d38565b6001600160a01b039485166000908152602091825260408082209590961681529390525091902055565b60006107fc61132760017f6e6ab8b7c7aaba79eef8cc633522d606bb008c101cf9832c9ad05d10a9847281612d38565b610b03816129e8565b610b0381612a1f565b60006107fc61132760017fb5b37715a3e346e996104f0086703f19825def429233930fd9399c38e05fb113612d38565b60608182601f01101561271e576040516323d5783d60e11b815260040160405180910390fd5b6127288284612cc9565b8451101561274957604051633b99b53d60e01b815260040160405180910390fd5b60608215801561276857604051915060008252602082016040526127b2565b6040519150601f8416801560200281840101858101878315602002848b0101015b818310156127a1578051835260209283019201612789565b5050858452601f01601f1916604052505b50949350505050565b603881901c60ff908116603083901c8216602884901c8316602085901c8416601886901c8516601087901c8616600888811c9790971688881b61ff001617871b17861b17851b17841b17831b1790911b17604082901c801561281f5761281f613008565b5060c01b919050565b60006107fc61132760017f35efb61d8784060218d9d6aa40eae55904de43779c1afc79c74dfefcfdf91260612d38565b60006107fc61132760017f6b842b424335d94ccad97e54548dfa02673c1268aba38d3c3c32d28c8988b70b612d38565b60006128b560017f0fb4a5ac9287f4f508aa7253ee2d57c6a228b1b30e210d73fffd59389d3a8838612d38565b6001600160a01b03909316600090815260209390935250604090912055565b612710811115610b03576040516358d620b360e01b815260040160405180910390fd5b612900816122e6565b610b0361135960017f35efb61d8784060218d9d6aa40eae55904de43779c1afc79c74dfefcfdf91260612d38565b8061294c5760405163a9cb9e0d60e01b815260040160405180910390fd5b610b0361135960017fb649e50315f962b32d487e696a81b4828631b11f8424daaaa37e9e97766a2c42612d38565b61299581612986612858565b6129909190612cc9565b612a4d565b6129a38282611e9d8561213c565b6040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b6129f1816122e6565b610b0361135960017fb5b37715a3e346e996104f0086703f19825def429233930fd9399c38e05fb113612d38565b610b0361135960017f6e6ab8b7c7aaba79eef8cc633522d606bb008c101cf9832c9ad05d10a9847281612d38565b610b0361135960017f6b842b424335d94ccad97e54548dfa02673c1268aba38d3c3c32d28c8988b70b612d38565b60005b83811015612a96578181015183820152602001612a7e565b83811115612aa5576000848401525b50505050565b60008151808452612ac3816020860160208601612a7b565b601f01601f19169290920160200192915050565b60208152600061122f6020830184612aab565b80356001600160a01b0381168114612b0157600080fd5b919050565b60008060408385031215612b1957600080fd5b612b2283612aea565b946020939093013593505050565b600060208284031215612b4257600080fd5b61122f82612aea565b600060208284031215612b5d57600080fd5b5035919050565b600080600060608486031215612b7957600080fd5b612b8284612aea565b9250612b9060208501612aea565b9150604084013590509250925092565b60008060008060008060008060006101208a8c031215612bbf57600080fd5b612bc88a612aea565b9850612bd660208b01612aea565b975060408a01359650612beb60608b01612aea565b9550612bf960808b01612aea565b9450612c0760a08b01612aea565b9350612c1560c08b01612aea565b9250612c2360e08b01612aea565b91506101008a013590509295985092959850929598565b6001600160a01b0391909116815260200190565b60008060008060808587031215612c6457600080fd5b5050823594602084013594506040840135936060013592509050565b60008060408385031215612c9357600080fd5b612c9c83612aea565b9150612caa60208401612aea565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b60008219821115612cdc57612cdc612cb3565b500190565b600082612cfe57634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052603260045260246000fd5b6000816000190483118215151615612d3357612d33612cb3565b500290565b600082821015612d4a57612d4a612cb3565b500390565b83815260406020820152816040820152818360608301376000818301606090810191909152601f909201601f1916010192915050565b600060208284031215612d9757600080fd5b8151801515811461122f57600080fd5b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612de657612de6612da7565b604052919050565b6000601f8381840112612e0057600080fd5b8251602067ffffffffffffffff80831115612e1d57612e1d612da7565b8260051b612e2c838201612dbd565b9384528681018301938381019089861115612e4657600080fd5b84890192505b85831015610bc057825184811115612e645760008081fd5b8901603f81018b13612e765760008081fd5b85810151604086821115612e8c57612e8c612da7565b612e9d828b01601f19168901612dbd565b8281528d82848601011115612eb25760008081fd5b612ec1838a8301848701612a7b565b85525050509184019190840190612e4c565b60008060408385031215612ee657600080fd5b825167ffffffffffffffff80821115612efe57600080fd5b612f0a86838701612dee565b93506020850151915080821115612f2057600080fd5b50612f2d85828601612dee565b9150509250929050565b60008351612f49818460208801612a7b565b6001600160801b0319939093169190920190815260100192915050565b60008251612f78818460208701612a7b565b9190910192915050565b600060208284031215612f9457600080fd5b5051919050565b60008351612fad818460208801612a7b565b9190910191825250602001919050565b608081526000612fd06080830187612aab565b8281036020840152612fe28187612aab565b90508281036040840152612ff68186612aab565b91505082606083015295945050505050565b634e487b7160e01b600052600160045260246000fdfea26469706673582212204c98ac4f477f06f69f4028fa9440dd9c691d20f120c69e574b4c9dd17f97219264736f6c634300080a0033

Deployed Bytecode Sourcemap

4154:8235:2:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1195:20:6;1204:10;1195:8;:20::i;:::-;4154:8235:2;;1315:23:6;;-1:-1:-1;;;1315:23:6;;;;;;;;;;;2874:109:3;;;;;;;;;;;;;:::i;:::-;;;160:25:45;;;148:2;133:18;2874:109:3;;;;;;;;1945:97:5;;;;;;;;;;-1:-1:-1;2009:26:5;;;;;;;;;;;;-1:-1:-1;;;2009:26:5;;;;1945:97;;;;;;;:::i;4385:151::-;;;;;;;;;;-1:-1:-1;4385:151:5;;;;;:::i;:::-;;:::i;:::-;;;1549:14:45;;1542:22;1524:41;;1512:2;1497:18;4385:151:5;1384:187:45;1276:150:0;;;;;;;;;;;;;:::i;2478:109:4:-;;;;;;;;;;;;;:::i;6754:188:2:-;;;;;;;;;;-1:-1:-1;6754:188:2;;;;;:::i;:::-;;:::i;3399:1463:3:-;;;;;;;;;;-1:-1:-1;3399:1463:3;;;;;:::i;:::-;;:::i;2470:104:5:-;;;;;;;;;;;;;:::i;1131::0:-;;;;;;;;;;-1:-1:-1;1131:104:0;;;;;:::i;:::-;;:::i;2334:93:5:-;;;;;;;;;;;;;:::i;5652:95:2:-;;;;;;;;;;;;;:::i;3942:400:5:-;;;;;;;;;;-1:-1:-1;3942:400:5;;;;;:::i;:::-;;:::i;4462:1155:2:-;;;;;;;;;;-1:-1:-1;4462:1155:2;;;;;:::i;:::-;;:::i;6203:130::-;;;;;;;;;;-1:-1:-1;6203:130:2;;;;;:::i;:::-;;:::i;6056:112::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;2215:76:5:-;;;;;;;;;;-1:-1:-1;2215:76:5;;2282:2;3412:36:45;;3400:2;3385:18;2215:76:5;3270:184:45;1392:47:3;;;;;;;;;;;;1431:8;1392:47;;4579:227:5;;;;;;;;;;-1:-1:-1;4579:227:5;;;;;:::i;:::-;;:::i;2769:145::-;;;;;;;;;;-1:-1:-1;2769:145:5;;;;;:::i;:::-;;:::i;2312:123:4:-;;;;;;;;;;;;;:::i;5919:102:2:-;;;;;;;;;;;;;:::i;1300:45:3:-;;;;;;;;;;;;1343:2;1300:45;;3041:119;;;;;;;;;;;;;:::i;6368:158:2:-;;;;;;;;;;-1:-1:-1;6368:158:2;;;;;:::i;:::-;;:::i;827:104:0:-;;;;;;;;;;;;;:::i;2617:109:5:-;;;;;;;;;;-1:-1:-1;2617:109:5;;;;;:::i;:::-;;:::i;3137:167::-;;;;;;;;;;-1:-1:-1;3137:167:5;;;;;:::i;:::-;;:::i;2630:157:4:-;;;;;;;;;;-1:-1:-1;2630:157:4;;;;;:::i;:::-;;:::i;2173:96::-;;;;;;;;;;;;;:::i;3218:123:3:-;;;;;;;;;;;;;:::i;2085:87:5:-;;;;;;;;;;-1:-1:-1;2151:14:5;;;;;;;;;;;;-1:-1:-1;;;2151:14:5;;;;2085:87;;6977:118:2;;;;;;;;;;;;;:::i;4849:231:5:-;;;;;;;;;;-1:-1:-1;4849:231:5;;;;;:::i;:::-;;:::i;3538:361::-;;;;;;;;;;-1:-1:-1;3538:361:5;;;;;:::i;:::-;;:::i;959:151:6:-;;;;;;:::i;:::-;;:::i;1199:46:3:-;;;;;;;;;;;;1243:2;1199:46;;5782:102:2;;;;;;;;;;;;;:::i;2830:1493:4:-;;;;;;;;;;-1:-1:-1;2830:1493:4;;;;;:::i;:::-;;:::i;972:118:0:-;;;;;;;;;;;;;:::i;838:73:6:-;;;:::i;3347:148:5:-;;;;;;;;;;-1:-1:-1;3347:148:5;;;;;:::i;:::-;;:::i;7130:168:2:-;;;:::i;2957:137:5:-;;;;;;;;;;-1:-1:-1;2957:137:5;;;;;:::i;:::-;;:::i;6561:158:2:-;;;;;;;;;;-1:-1:-1;6561:158:2;;;;;:::i;:::-;;:::i;1511:314:6:-;1572:9;1568:66;;1609:14;;-1:-1:-1;;;1609:14:6;;;;;;;;;;;1568:66;1644:56;1690:9;1665:22;:20;:22::i;:::-;:34;;;;:::i;:::-;1644:20;:56::i;:::-;1711:45;1722:10;1734;1746:9;1711:10;:45::i;:::-;1772:46;;1808:9;160:25:45;;-1:-1:-1;;;;;1772:46:6;;;1784:10;;1772:46;;148:2:45;133:18;1772:46:6;;;;;;;1511:314;:::o;2874:109:3:-;2928:7;2954:22;:20;:22::i;:::-;2947:29;;2874:109;:::o;4385:151:5:-;4454:4;4470:38;4479:10;4491:8;4501:6;4470:8;:38::i;:::-;-1:-1:-1;4525:4:5;4385:151;;;;:::o;1276:150:0:-;666:35;:33;:35::i;:::-;-1:-1:-1;;;;;652:49:0;:10;-1:-1:-1;;;;;652:49:0;;648:121;;747:10;724:34;;-1:-1:-1;;;724:34:0;;;;;;;;:::i;:::-;;;;;;;;648:121;1335:46:::1;1345:35;:33;:35::i;:::-;1335:9;:46::i;:::-;1391:28;1416:1;1391:16;:28::i;:::-;1276:150::o:0;2478:109:4:-;2532:7;2558:22;:20;:22::i;6754:188:2:-;447:28:0;:26;:28::i;:::-;-1:-1:-1;;;;;433:42:0;:10;-1:-1:-1;;;;;433:42:0;;429:114;;521:10;498:34;;-1:-1:-1;;;498:34:0;;;;;;;;:::i;429:114::-;6838:45:2::1;6864:18;6838:25;:45::i;:::-;6898:37;::::0;-1:-1:-1;;;;;6898:37:2;::::1;::::0;::::1;::::0;;;::::1;6754:188:::0;:::o;3399:1463:3:-;1724:16;:14;:16::i;:::-;-1:-1:-1;;;;;1710:30:3;:10;-1:-1:-1;;;;;1710:30:3;;1706:102;;1786:10;1763:34;;-1:-1:-1;;;1763:34:3;;;;;;;;:::i;1706:102::-;3486:24:::1;3513:22;:20;:22::i;:::-;3486:49:::0;-1:-1:-1;3545:25:3::1;3573:58;3588:31;1431:8;3486:49:::0;3588:31:::1;:::i;:::-;3621:9;3573:14;:58::i;:::-;3545:86:::0;-1:-1:-1;3646:22:3;3642:76:::1;;3691:16;;-1:-1:-1::0;;;3691:16:3::1;;;;;;;;;;;3642:76;3729:25;3756::::0;3785:37:::1;3804:17;3785:18;:37::i;:::-;3866:17:::0;;3728:94;;-1:-1:-1;3728:94:3;-1:-1:-1;3898:27:3;3894:91:::1;;3948:26;;-1:-1:-1::0;;;3948:26:3::1;;;;;;;;;;;3894:91;4024:17;3999:22;:42;3995:103;;;4064:23;;-1:-1:-1::0;;;4064:23:3::1;;;;;;;;;;;3995:103;4141:17:::0;;4173:48;;::::1;4169:109;;4244:23;;-1:-1:-1::0;;;4244:23:3::1;;;;;;;;;;;4169:109;4288:29;4320:27;:25;:27::i;:::-;4288:59:::0;-1:-1:-1;4362:26:3;4358:94:::1;;4411:30;;-1:-1:-1::0;;;4411:30:3::1;;;;;;;;;;;4358:94;4467:11;4462:213;4490:22;4484:3;:28;4462:213;;;4529:74;4547:10;4558:3;4547:15;;;;;;;;:::i;:::-;;;;;;;4564:10;4575:3;4564:15;;;;;;;;:::i;:::-;;;;;;;4581:21;4529:17;:74::i;:::-;4645:5;;4462:213;;;-1:-1:-1::0;4684:78:3::1;4724:37;4739:22:::0;1431:8:::1;4724:37;:::i;:::-;4705:56;::::0;:16;:56:::1;:::i;4684:78::-;4772:83;4832:22;4800:29;:27;:29::i;:::-;:54;;;;:::i;:::-;4772:27;:83::i;:::-;3476:1386;;;;;;;3399:1463:::0;:::o;2470:104:5:-;2526:7;2552:15;:13;:15::i;1131:104:0:-;447:28;:26;:28::i;:::-;-1:-1:-1;;;;;433:42:0;:10;-1:-1:-1;;;;;433:42:0;;429:114;;521:10;498:34;;-1:-1:-1;;;498:34:0;;;;;;;;:::i;429:114::-;1201:27:::1;1218:9;1201:16;:27::i;:::-;1131:104:::0;:::o;2334:93:5:-;2380:7;2406:14;:12;:14::i;5652:95:2:-;5699:7;5725:15;:13;:15::i;3942:400:5:-;4136:4;4049:5;4056:3;1267:23;1279:5;1286:3;1267:11;:23::i;:::-;4079:6;1473:11;1469:63:::1;;1507:14;;-1:-1:-1::0;;;1507:14:5::1;;;;;;;;;;;1469:63;4104:5:::2;4111:6;1830;1809:18;1820:6;1809:10;:18::i;:::-;:27;1805:80;;;1859:15;;-1:-1:-1::0;;;1859:15:5::2;;;;;;;;;;;1805:80;-1:-1:-1::0;;;;;4160:17:5;::::3;4156:94;;4200:39;::::0;-1:-1:-1;;;4200:39:5;;-1:-1:-1;;;;;5448:15:45;;4200:39:5::3;::::0;::::3;5430:34:45::0;4236:1:5::3;5480:18:45::0;;;5473:43;5365:18;;4200:39:5::3;5218:304:45::0;4156:94:5::3;4259:30;4275:5;4282:6;4259:15;:30::i;:::-;4306:29;4316:5;4323:3;4328:6;4306:9;:29::i;:::-;4299:36:::0;3942:400;-1:-1:-1;;;;;;;;;3942:400:5:o;4462:1155:2:-;4841:1;967:13:1;:11;:13::i;:::-;955:8;:25;951:109;;1025:8;1035:13;:11;:13::i;:::-;1003:46;;-1:-1:-1;;;1003:46:1;;;;;5701:25:45;;;;5742:18;;;5735:34;5674:18;;1003:46:1;5527:248:45;951:109:1;1069:25;1081:12;:8;1092:1;1081:12;:::i;:::-;1069:11;:25::i;:::-;4854:38:2::1;4864:27;4854:9;:38::i;:::-;4903:39;4924:17;4903:20;:39::i;:::-;4957:31;::::0;-1:-1:-1;;;;;4957:31:2;::::1;::::0;::::1;::::0;;;::::1;4999:25;5013:10;4999:13;:25::i;:::-;5039:24;::::0;160:25:45;;;5039:24:2::1;::::0;148:2:45;133:18;5039:24:2::1;;;;;;;5074:49;5100:22;5074:25;:49::i;:::-;5138:41;::::0;-1:-1:-1;;;;;5138:41:2;::::1;::::0;::::1;::::0;;;::::1;5190:39;5211:17;5190:20;:39::i;:::-;5244:31;::::0;-1:-1:-1;;;;;5244:31:2;::::1;::::0;::::1;::::0;;;::::1;5286:54;5315:24;5286:28;:54::i;:::-;5355:46;::::0;-1:-1:-1;;;;;5355:46:2;::::1;::::0;::::1;::::0;;;::::1;5412:136;5491:23;5516:22;5412:65;:136::i;:::-;5559:51;5595:14;5559:35;:51::i;:::-;1164:30:1::0;1175:8;1185;;1164:30;;;;;;;;:::i;:::-;;;;;;;;4462:1155:2;;;;;;;;;;:::o;6203:130::-;447:28:0;:26;:28::i;:::-;-1:-1:-1;;;;;433:42:0;:10;-1:-1:-1;;;;;433:42:0;;429:114;;521:10;498:34;;-1:-1:-1;;;498:34:0;;;;;;;;:::i;429:114::-;6270:21:2::1;6284:6;6270:13;:21::i;:::-;6306:20;::::0;160:25:45;;;6306:20:2::1;::::0;148:2:45;133:18;6306:20:2::1;;;;;;;6203:130:::0;:::o;6056:112::-;6108:7;6134:27;:25;:27::i;4579:227:5:-;4668:4;4684:94;4693:10;4705:8;4761:16;4715:43;4737:10;4749:8;4715:21;:43::i;:::-;:62;;;;:::i;:::-;4684:8;:94::i;2769:145::-;2835:7;2861:46;2880:26;2899:6;2880:18;:26::i;:::-;2861:18;:46::i;:::-;2854:53;2769:145;-1:-1:-1;;2769:145:5:o;2312:123:4:-;2373:7;2399:29;:27;:29::i;5919:102:2:-;5966:7;5992:22;:20;:22::i;3041:119:3:-;3100:7;3126:27;:25;:27::i;6368:158:2:-;447:28:0;:26;:28::i;:::-;-1:-1:-1;;;;;433:42:0;:10;-1:-1:-1;;;;;433:42:0;;429:114;;521:10;498:34;;-1:-1:-1;;;498:34:0;;;;;;;;:::i;429:114::-;6442:35:2::1;6463:13;6442:20;:35::i;:::-;6492:27;::::0;-1:-1:-1;;;;;6492:27:2;::::1;::::0;::::1;::::0;;;::::1;6368:158:::0;:::o;827:104:0:-;870:7;896:28;:26;:28::i;2617:109:5:-;2675:7;2701:18;2712:6;2701:10;:18::i;3137:167::-;3229:7;3255:42;3274:22;3255:18;:42::i;2630:157:4:-;1800:16;:14;:16::i;:::-;-1:-1:-1;;;;;1786:30:4;:10;-1:-1:-1;;;;;1786:30:4;;1782:102;;1862:10;1839:34;;-1:-1:-1;;;1839:34:4;;;;;;;;:::i;1782:102::-;2707:33:::1;2725:14;2707:17;:33::i;:::-;2755:25;::::0;-1:-1:-1;;;;;2755:25:4;::::1;::::0;::::1;::::0;;;::::1;2630:157:::0;:::o;2173:96::-;2217:7;2243:19;:17;:19::i;3218:123:3:-;3279:7;3305:29;:27;:29::i;6977:118:2:-;7032:7;7058:30;:28;:30::i;4849:231:5:-;4940:4;4956:96;4965:10;4977:8;5033:18;4987:43;5009:10;5021:8;4987:21;:43::i;:::-;:64;;;;:::i;3538:361::-;3723:4;3626:10;3638:3;1267:23;1279:5;1286:3;1267:11;:23::i;:::-;3661:6;1473:11;1469:63:::1;;1507:14;;-1:-1:-1::0;;;1507:14:5::1;;;;;;;;;;;1469:63;3686:10:::2;3698:6;1830;1809:18;1820:6;1809:10;:18::i;:::-;:27;1805:80;;;1859:15;;-1:-1:-1::0;;;1859:15:5::2;;;;;;;;;;;1805:80;-1:-1:-1::0;;;;;3747:17:5;::::3;3743:99;;3787:44;::::0;-1:-1:-1;;;3787:44:5;;3808:10:::3;3787:44;::::0;::::3;5430:34:45::0;3828:1:5::3;5480:18:45::0;;;5473:43;5365:18;;3787:44:5::3;5218:304:45::0;3743:99:5::3;3858:34;3868:10;3880:3;3885:6;3858:9;:34::i;:::-;3851:41:::0;3538:361;-1:-1:-1;;;;;;;;3538:361:5:o;959:151:6:-;1034:39;1062:10;1034:27;:39::i;:::-;1083:20;1092:10;1083:8;:20::i;5782:102:2:-;5829:7;5855:22;:20;:22::i;2830:1493:4:-;3033:19;:17;:19::i;:::-;-1:-1:-1;;;;;3019:33:4;:10;-1:-1:-1;;;;;3019:33:4;;3015:105;;3098:10;3075:34;;-1:-1:-1;;;3075:34:4;;;;;;;;:::i;3015:105::-;3152:29;:27;:29::i;:::-;3134:15;:47;3130:160;;;3232:15;3249:29;:27;:29::i;:::-;3204:75;;-1:-1:-1;;;3204:75:4;;;;;5701:25:45;;;;5742:18;;;5735:34;5674:18;;3204:75:4;5527:248:45;3130:160:4;3300:21;3342:22;:20;:22::i;:::-;3324:40;;:15;:40;:::i;:::-;3300:64;-1:-1:-1;3374:37:4;3447:24;3300:64;3463:8;3447:24;:::i;:::-;3414:29;:27;:29::i;:::-;:58;;;;:::i;:::-;3374:98;;3483:51;3511:22;3483:27;:51::i;:::-;3544:37;3565:15;3544:20;:37::i;:::-;3591:31;3613:8;3591:21;:31::i;:::-;3633:26;3866:22;3818:44;3833:29;3818:12;:44;:::i;:::-;3817:71;3813:207;;;3925:84;3986:22;3938:44;3953:29;3938:12;:44;:::i;:::-;3937:71;;;;:::i;:::-;3925:11;:84::i;:::-;3904:105;;3813:207;4066:43;4091:18;4066:22;:43;:::i;:::-;4034:29;:75;4030:196;;;4125:90;4185:29;4138:43;4163:18;4138:22;:43;:::i;:::-;4137:77;;;;:::i;:::-;4125:11;:90::i;:::-;4241:75;;;6446:25:45;;;6502:2;6487:18;;6480:34;;;6530:18;;;6523:34;;;4241:75:4;;6434:2:45;6419:18;4241:75:4;;;;;;;3005:1318;;;2830:1493;;;;:::o;972:118:0:-;1022:7;1048:35;:33;:35::i;838:73:6:-;884:20;893:10;884:8;:20::i;3347:148:5:-;3423:7;3449:39;3471:6;3479:8;3449:21;:39::i;:::-;3442:46;3347:148;-1:-1:-1;;;3347:148:5:o;7130:168:2:-;7197:27;:25;:27::i;:::-;-1:-1:-1;;;;;7183:41:2;:10;-1:-1:-1;;;;;7183:41:2;;7179:113;;7270:10;7247:34;;-1:-1:-1;;;7247:34:2;;;;;;;;:::i;2957:137:5:-;3034:7;3060:27;3079:7;3060:18;:27::i;6561:158:2:-;447:28:0;:26;:28::i;:::-;-1:-1:-1;;;;;433:42:0;:10;-1:-1:-1;;;;;433:42:0;;429:114;;521:10;498:34;;-1:-1:-1;;;498:34:0;;;;;;;;:::i;429:114::-;6635:35:2::1;6656:13;6635:20;:35::i;:::-;6685:27;::::0;-1:-1:-1;;;;;6685:27:2;::::1;::::0;::::1;::::0;;;::::1;6561:158:::0;:::o;268:136:26:-;306:7;332:65;206:54;259:1;214:41;206:54;:::i;:::-;1622:16:23;;1442:212;410:132:26;460:75;206:54;259:1;214:41;206:54;:::i;:::-;526:8;3024:24:23;;2865:199;8330:705:2;8435:20;8458:48;8486:10;8498:7;8458:27;:48::i;:::-;8435:71;;8516:22;8554;:20;:22::i;:::-;8516:61;;8605:10;-1:-1:-1;;;;;8591:24:2;:10;-1:-1:-1;;;;;8591:24:2;;8587:442;;;8631:47;;-1:-1:-1;;;8631:47:2;;-1:-1:-1;;;;;6760:32:45;;;8631:47:2;;;6742:51:45;4423:3:2;6809:18:45;;;6802:34;8631:21:2;;;;;6715:18:45;;8631:47:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8587:442;;;8756:47;;-1:-1:-1;;;8756:47:2;;-1:-1:-1;;;;;6760:32:45;;;8756:47:2;;;6742:51:45;4423:3:2;6809:18:45;;;6802:34;8756:21:2;;;;;6715:18:45;;8756:47:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;8868:30:2;;-1:-1:-1;;;8868:30:2;;-1:-1:-1;;;;;8868:18:2;;;-1:-1:-1;8868:18:2;;-1:-1:-1;8868:30:2;;8887:10;;8868:30;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;8864:94;;;8932:10;8925:18;;-1:-1:-1;;;8925:18:2;;;;;;;;:::i;8864:94::-;8971:47;8981:10;8993;9005:12;8971:9;:47::i;:::-;;8587:442;8425:610;;8330:705;;;:::o;5941:282:5:-;6028:35;6056:6;6028:27;:35::i;:::-;6073:37;6101:8;6073:27;:37::i;:::-;6120:47;6142:6;6150:8;6160:6;6120:21;:47::i;:::-;6199:8;-1:-1:-1;;;;;6182:34:5;6191:6;-1:-1:-1;;;;;6182:34:5;;6209:6;6182:34;;;;160:25:45;;148:2;133:18;;14:177;6182:34:5;;;;;;;;5941:282;;;:::o;621:117:17:-;672:7;698:33;:31;:33::i;1536:171:0:-;1590:35;1618:6;1590:27;:35::i;:::-;1635:34;1662:6;1635:26;:34::i;:::-;1684:16;;-1:-1:-1;;;;;1684:16:0;;;;;;;;1536:171;:::o;1840:168::-;1908:48;1942:13;1908:33;:48::i;:::-;1971:30;;-1:-1:-1;;;;;1971:30:0;;;;;;;;1840:168;:::o;577:136:27:-;615:7;641:65;402:54;455:1;410:41;402:54;:::i;407:103:17:-;451:7;477:26;:24;:26::i;899:135:32:-;950:77;434:59;492:1;442:46;434:59;:::i;7422:202:2:-;7562:7;7592:25;:23;:25::i;1295:112:22:-;1355:7;1387:2;1382;:7;:17;;1397:2;1382:17;;;-1:-1:-1;1392:2:22;1295:112;-1:-1:-1;1295:112:22:o;9423:276:2:-;9528:25;9555;9624:30;:28;:30::i;:::-;-1:-1:-1;;;;;9603:71:2;;9675:16;9603:89;;;;;;;;;;;;;160:25:45;;148:2;133:18;;14:177;9603:89:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;9603:89:2;;;;;;;;;;;;:::i;:::-;9596:96;;;;9423:276;;;:::o;594:140:39:-;632:7;658:69;432:59;490:1;440:46;432:59;:::i;5139:1439:3:-;1243:2;5283:10;:17;:38;5279:100;;5344:24;;-1:-1:-1;;;5344:24:3;;;;;;;;;;;5279:100;1343:2;5393:10;:17;:37;5389:99;;5453:24;;-1:-1:-1;;;5453:24:3;;;;;;;;;;;5389:99;1431:8;5497:13;5560:14;5568:6;1431:8;5560:14;:::i;:::-;5536:38;;5585:18;5606:44;5626:10;5646:1;5638:10;;5613:36;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;5613:36:3;;;;;;;;;;5606:44;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5585:65;;5660:21;5684:220;5734:41;5741:33;5756:10;5768:1;5771:2;5741:14;:33::i;:::-;5734:41;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5793:87;5813:53;5828:10;5840:2;5844:21;5840:2;1343;5844:21;:::i;:::-;5813:14;:53::i;:::-;5800:79;;;;;5876:1;;5800:79;;;:::i;:::-;;;;-1:-1:-1;;5800:79:3;;;;;;;;;;5793:87;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5704:190;;;;;;11105:19:45;;;;11140:12;;11133:28;11177:12;;5704:190:3;;;-1:-1:-1;;5704:190:3;;;;;;;;;;5684:220;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5660:244;;5915:23;5941:236;5991:56;6011:10;6023:22;5998:48;;;;;;;;11105:19:45;;;11149:2;11140:12;;11133:28;11186:2;11177:12;;10948:247;5998:48:3;;;;-1:-1:-1;;5998:48:3;;;;;;;;;;5991:56;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;6065:88;6093:42;6121:13;6093:27;:42::i;:::-;6072:80;;;;;;11105:19:45;;;;11140:12;;11133:28;;;11177:12;;6072:80:3;;;-1:-1:-1;;6072:80:3;;;;;;;;;;6065:88;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5961:206;;;;;;11105:19:45;;;;11140:12;;11133:28;11177:12;;5961:206:3;;;-1:-1:-1;;5961:206:3;;;;;;;;;;5941:236;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5915:262;-1:-1:-1;6188:21:3;6212:29;6236:5;6212:21;:29;:::i;:::-;6188:53;;6269:28;:26;:28::i;:::-;-1:-1:-1;;;;;6252:54:3;;6314:5;6334:10;6363:22;6346:40;;;;;;11329:19:45;;11373:2;11364:12;;11200:182;6346:40:3;;;;;;;;;;;;;6388:10;6400:15;6252:173;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6464:13;6439:21;:38;6435:92;;6500:16;;-1:-1:-1;;;6500:16:3;;;;;;;;;;;6435:92;6541:30;6560:10;6541:30;;;;;;:::i;:::-;;;;;;;;5269:1309;;;;;;5139:1439;;;:::o;576:143:31:-;614:7;640:72;406:61;466:1;414:48;406:61;:::i;831:141::-;882:83;406:61;466:1;414:48;406:61;:::i;11838:549:2:-;11895:7;11914:24;11941:22;:20;:22::i;:::-;11914:49;;11973:31;12007:29;:27;:29::i;:::-;11973:63;;12069:23;12050:16;:42;12046:335;;;1431:8:3;12189:42:2;12215:16;12189:23;:42;:::i;:::-;12188:90;;;;:::i;:::-;12147:22;:20;:22::i;:::-;12115:29;:27;:29::i;:::-;:54;;;;:::i;:::-;:163;;;;:::i;:::-;12108:170;;;;11838:549;:::o;12046:335::-;12348:22;:20;:22::i;:::-;12316:29;:27;:29::i;6334:92:5:-;6381:7;6407:12;:10;:12::i;492:128:33:-;530:7;556:57;366:47;412:1;374:34;366:47;:::i;7778:316:2:-;7860:22;7898;:20;:22::i;:::-;7935:25;;-1:-1:-1;;;7935:25:2;;7860:61;;-1:-1:-1;;;;;;7935:18:2;;;;;:25;;7954:5;;7935:25;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;7931:76;;;7990:5;7983:13;;-1:-1:-1;;;7983:13:2;;;;;;;;:::i;7931:76::-;8020:23;;-1:-1:-1;;;8020:23:2;;-1:-1:-1;;;;;8020:18:2;;;;;:23;;8039:3;;8020:23;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;8016:72;;;8073:3;8066:11;;-1:-1:-1;;;8066:11:2;;;;;;;;:::i;8016:72::-;7850:244;7778:316;;:::o;9484:118:5:-;9543:7;9569:26;9588:6;9569:18;:26::i;5291:412::-;5366:24;5393:40;5415:5;5422:10;5393:21;:40::i;:::-;5366:67;;5466:6;5447:16;:25;5443:123;;;5495:60;;-1:-1:-1;;;5495:60:5;;-1:-1:-1;;;;;12515:15:45;;5495:60:5;;;12497:34:45;5518:10:5;12547:18:45;;;12540:43;12599:18;;;12592:34;;;12642:18;;;12635:34;;;12431:19;;5495:60:5;12228:447:45;5443:123:5;-1:-1:-1;;5579:16:5;:37;5575:122;;5632:54;5641:5;5648:10;5660:25;5679:6;5660:16;:25;:::i;6676:298::-;6757:4;6773:61;6792:5;6827:6;6799:25;6818:5;6799:18;:25::i;:::-;:34;;;;:::i;:::-;6773:18;:61::i;:::-;6844:57;6863:3;6894:6;6868:23;6887:3;6868:18;:23::i;:::-;:32;;;;:::i;6844:57::-;6933:3;-1:-1:-1;;;;;6917:28:5;6926:5;-1:-1:-1;;;;;6917:28:5;;6938:6;6917:28;;;;160:25:45;;148:2;133:18;;14:177;6917:28:5;;;;;;;;-1:-1:-1;6963:4:5;6676:298;;;;;:::o;426:125:43:-;464:7;490:54;308:45;352:1;316:32;308:45;:::i;627:123::-;678:65;308:45;352:1;316:32;308:45;:::i;779:181:29:-;830:38;858:9;830:27;:38::i;:::-;878:75;401:54;454:1;409:41;401:54;:::i;702:168:33:-;753:32;775:9;753:21;:32::i;:::-;795:68;366:47;412:1;374:34;366:47;:::i;779:181:25:-;830:38;858:9;830:27;:38::i;:::-;878:75;401:54;454:1;409:41;401:54;:::i;884:190:35:-;935:38;963:9;935:27;:38::i;:::-;983:84;453:62;514:1;461:49;453:62;:::i;2430:386:3:-;2570:51;2597:23;2570:26;:51::i;:::-;2636:50;;-1:-1:-1;;;;;2636:50:3;;;;;;;;2697:49;2723:22;2697:25;:49::i;:::-;2761:48;;160:25:45;;;2761:48:3;;148:2:45;133:18;2761:48:3;;;;;;;2430:386;;:::o;626:137:32:-;664:7;690:66;434:59;492:1;442:46;434:59;:::i;833:318:41:-;904:7;;322:55;376:1;330:42;322:55;:::i;:::-;-1:-1:-1;;;;;1118:15:41;;;314:64;1118:15;;;;;;;;;;;:26;;;;;;;;;-1:-1:-1;;1118:26:41;;;833:318::o;689:285:38:-;741:7;;299:52;350:1;307:39;299:52;:::i;:::-;-1:-1:-1;;;;;952:15:38;;;291:61;952:15;;;;;;;;-1:-1:-1;;952:15:38;;;;;689:285::o;7176:272:5:-;7244:7;7263:25;7291:12;:10;:12::i;:::-;7263:40;-1:-1:-1;7318:22:5;7314:61;;-1:-1:-1;7363:1:5;;7176:272;-1:-1:-1;;7176:272:5:o;7314:61::-;7424:17;7404:15;:13;:15::i;:::-;7394:25;;:7;:25;:::i;:::-;7392:49;;;;:::i;647:144:28:-;685:7;711:73;449:61;509:1;457:48;449:61;:::i;548:135:29:-;586:7;612:64;401:54;454:1;409:41;401:54;:::i;7672:272:5:-;7741:7;7760:25;7788:12;:10;:12::i;:::-;7760:40;-1:-1:-1;7815:22:5;7811:61;;-1:-1:-1;7860:1:5;;7672:272;-1:-1:-1;;7672:272:5:o;7811:61::-;7922:15;:13;:15::i;:::-;7890:28;7901:17;7890:8;:28;:::i;746:178:36:-;797:38;825:9;797:27;:38::i;:::-;845:72;386:51;436:1;394:38;386:51;:::i;524:132::-;562:7;588:61;386:51;436:1;394:38;386:51;:::i;626:144:35:-;664:7;690:73;453:62;514:1;461:49;453:62;:::i;292:163:21:-;-1:-1:-1;;;;;363:22:21;;359:90;;408:30;;-1:-1:-1;;;408:30:21;;;;;;;;;;;548:135:25;586:7;612:64;401:54;454:1;409:41;401:54;:::i;931:142:28:-;982:84;449:61;509:1;457:48;449:61;:::i;837:134:27:-;888:76;402:54;455:1;410:41;402:54;:::i;774:136:34:-;825:78;380:55;434:1;388:42;380:55;:::i;9996:563:2:-;10058:7;10077:22;10102:27;:25;:27::i;:::-;10077:52;-1:-1:-1;;;;;;10143:28:2;;10139:67;;-1:-1:-1;10194:1:2;;9996:563;-1:-1:-1;;9996:563:2:o;10139:67::-;10271:59;;-1:-1:-1;;;10271:59:2;;;;;160:25:45;;;10240:21:2;;-1:-1:-1;;;;;10271:53:2;;;;;133:18:45;;10271:59:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10340:23;10390:14;10366:21;:38;;;;:::i;:::-;10340:64;;10414:62;10460:15;10435:22;:20;:22::i;10414:62::-;10491:29;;160:25:45;;;10491:29:2;;148:2:45;133:18;10491:29:2;;;;;;;10537:15;9996:563;-1:-1:-1;;;;9996:563:2:o;10754:925::-;10820:22;10845:14;:12;:14::i;:::-;10820:39;-1:-1:-1;10873:19:2;10869:75;;10915:18;;-1:-1:-1;;;10915:18:2;;;;;;;;;;;10869:75;10953:23;10979:15;:13;:15::i;:::-;10953:41;;11004:17;11024:15;:13;:15::i;:::-;11004:35;-1:-1:-1;11049:17:2;11004:35;11069:24;11079:14;11069:7;:24;:::i;:::-;:36;;;;:::i;:::-;11049:56;-1:-1:-1;11115:19:2;11192;11202:9;11192:7;:19;:::i;:::-;11138:49;273:6:18;11138:15:2;:49;:::i;:::-;11137:75;;;;:::i;:::-;11115:97;-1:-1:-1;11222:20:2;11245:16;;:48;;11269:23;11281:11;11269:9;:23;:::i;:::-;11245:48;;;11264:1;11245:48;11222:71;-1:-1:-1;11308:16:2;;11304:369;;11340:17;11360:22;:20;:22::i;:::-;11340:42;;11396:39;11411:9;11422:12;11396:14;:39::i;:::-;11449:22;11474:14;:12;:14::i;:::-;11449:39;-1:-1:-1;11502:23:2;11528:25;11546:7;11528:15;:25;:::i;:::-;11572:90;;;12911:25:45;;;12967:2;12952:18;;12945:34;;;12995:18;;;12988:34;;;13053:2;13038:18;;13031:34;;;11502:51:2;;-1:-1:-1;;;;;;11572:90:2;;;;;12898:3:45;12883:19;11572:90:2;;;;;;;11326:347;;;11304:369;10810:869;;;;;;10754:925;:::o;8329:515:5:-;8415:20;8447:28;8496:21;8478:15;:13;:15::i;:::-;:39;;;;:::i;:::-;8447:70;-1:-1:-1;8532:25:5;8528:310;;8588:21;8573:36;;8623:45;8638:6;8646:21;8623:14;:45::i;:::-;8528:310;;;8757:20;8739:14;:12;:14::i;:::-;8715:38;;:21;:38;:::i;:::-;8714:63;;;;:::i;:::-;8699:78;;8791:36;8806:6;8814:12;8791:14;:36::i;:::-;8437:407;8329:515;;;;:::o;1393:319:41:-;1479:12;322:55;376:1;330:42;322:55;:::i;:::-;-1:-1:-1;;;;;1667:15:41;;;314:64;1667:15;;;;;;;;;;;:26;;;;;;;;;-1:-1:-1;1667:26:41;;;:38;1393:319::o;601:147:42:-;639:7;665:76;419:65;483:1;427:52;419:65;:::i;821:93:17:-;875:32;900:6;875:24;:32::i;1020:121::-;1088:46;1120:13;1088:31;:46::i;581:139:40:-;619:7;645:68;422:58;479:1;430:45;422:58;:::i;572:2856:19:-;664:12;731:7;716;726:2;716:12;:22;712:83;;;765:15;;-1:-1:-1;;;765:15:19;;;;;;;;;;;712:83;834:16;843:7;834:6;:16;:::i;:::-;818:6;:13;:32;814:88;;;873:18;;-1:-1:-1;;;873:18:19;;;;;;;;;;;814:88;912:22;1031:15;;1059:1931;;;;3131:4;3125:11;3112:24;;3317:1;3306:9;3299:20;3365:4;3354:9;3350:20;3344:4;3337:34;1024:2361;;1059:1931;1241:4;1235:11;1222:24;;1900:2;1891:7;1887:16;2282:9;2275:17;2269:4;2265:28;2253:9;2242;2238:25;2234:60;2330:7;2326:2;2322:16;2582:6;2568:9;2561:17;2555:4;2551:28;2539:9;2531:6;2527:22;2523:57;2519:70;2356:389;2615:3;2611:2;2608:11;2356:389;;;2733:9;;2722:21;;2656:4;2648:13;;;;2688;2356:389;;;-1:-1:-1;;2763:26:19;;;2971:2;2954:11;-1:-1:-1;;2950:25:19;2944:4;2937:39;-1:-1:-1;1024:2361:19;-1:-1:-1;3412:9:19;572:2856;-1:-1:-1;;;;572:2856:19:o;299:838:22:-;955:15;;;;467:4;1007:16;;;876:15;;;;928:16;;797:15;;;;849:16;;718:15;;;;770:16;;639:15;;;;691:16;;560:15;;;;612:16;;495:1;481:15;;;533:16;;;;517:11;;;;;516:34;596:11;;595:34;675:11;;674:34;754:11;;753:34;833:11;;832:34;912:11;;911:34;991:11;;;990:34;1034:15;;;;1067:14;;1060:22;;;;:::i;:::-;-1:-1:-1;1123:6:22;1111:19;;299:838;-1:-1:-1;299:838:22:o;610:142:30:-;648:7;674:71;443:60;502:1;451:47;443:60;:::i;450:124:37:-;488:7;514:53;323:44;366:1;331:31;323:44;:::i;1148:286:38:-;1215:12;299:52;350:1;307:39;299:52;:::i;:::-;-1:-1:-1;;;;;1400:15:38;;;291:61;1400:15;;;;;;;;-1:-1:-1;1400:15:38;;;;:27;1148:286::o;796:161:21:-;273:6:18;857:4:21;:38;853:98;;;918:22;;-1:-1:-1;;;918:22:21;;;;;;;;;;;862:188:30;913:38;941:9;913:27;:38::i;:::-;961:82;443:60;502:1;451:47;443:60;:::i;840:235:39:-;895:23;891:88;;941:27;;-1:-1:-1;;;941:27:39;;;;;;;;;;;891:88;988:80;432:59;490:1;440:46;432:59;:::i;9066:239:5:-;9141:33;9167:6;9152:12;:10;:12::i;:::-;:21;;;;:::i;:::-;9141:10;:33::i;:::-;9184:63;9203:6;9240;9211:26;9230:6;9211:18;:26::i;9184:63::-;9262:36;;160:25:45;;;-1:-1:-1;;;;;9262:36:5;;;9279:1;;9262:36;;148:2:45;133:18;9262:36:5;;;;;;;9066:239;;:::o;824:185:40:-;875:38;903:9;875:27;:38::i;:::-;923:79;422:58;479:1;430:45;422:58;:::i;868:145:42:-;919:87;419:65;483:1;427:52;419:65;:::i;660:122:37:-;711:64;323:44;366:1;331:31;323:44;:::i;196:258:45:-;268:1;278:113;292:6;289:1;286:13;278:113;;;368:11;;;362:18;349:11;;;342:39;314:2;307:10;278:113;;;409:6;406:1;403:13;400:48;;;444:1;435:6;430:3;426:16;419:27;400:48;;196:258;;;:::o;459:::-;501:3;539:5;533:12;566:6;561:3;554:19;582:63;638:6;631:4;626:3;622:14;615:4;608:5;604:16;582:63;:::i;:::-;699:2;678:15;-1:-1:-1;;674:29:45;665:39;;;;706:4;661:50;;459:258;-1:-1:-1;;459:258:45:o;722:220::-;871:2;860:9;853:21;834:4;891:45;932:2;921:9;917:18;909:6;891:45;:::i;947:173::-;1015:20;;-1:-1:-1;;;;;1064:31:45;;1054:42;;1044:70;;1110:1;1107;1100:12;1044:70;947:173;;;:::o;1125:254::-;1193:6;1201;1254:2;1242:9;1233:7;1229:23;1225:32;1222:52;;;1270:1;1267;1260:12;1222:52;1293:29;1312:9;1293:29;:::i;:::-;1283:39;1369:2;1354:18;;;;1341:32;;-1:-1:-1;;;1125:254:45:o;1576:186::-;1635:6;1688:2;1676:9;1667:7;1663:23;1659:32;1656:52;;;1704:1;1701;1694:12;1656:52;1727:29;1746:9;1727:29;:::i;1767:180::-;1826:6;1879:2;1867:9;1858:7;1854:23;1850:32;1847:52;;;1895:1;1892;1885:12;1847:52;-1:-1:-1;1918:23:45;;1767:180;-1:-1:-1;1767:180:45:o;1952:328::-;2029:6;2037;2045;2098:2;2086:9;2077:7;2073:23;2069:32;2066:52;;;2114:1;2111;2104:12;2066:52;2137:29;2156:9;2137:29;:::i;:::-;2127:39;;2185:38;2219:2;2208:9;2204:18;2185:38;:::i;:::-;2175:48;;2270:2;2259:9;2255:18;2242:32;2232:42;;1952:328;;;;;:::o;2285:772::-;2416:6;2424;2432;2440;2448;2456;2464;2472;2480;2533:3;2521:9;2512:7;2508:23;2504:33;2501:53;;;2550:1;2547;2540:12;2501:53;2573:29;2592:9;2573:29;:::i;:::-;2563:39;;2621:38;2655:2;2644:9;2640:18;2621:38;:::i;:::-;2611:48;;2706:2;2695:9;2691:18;2678:32;2668:42;;2729:38;2763:2;2752:9;2748:18;2729:38;:::i;:::-;2719:48;;2786:39;2820:3;2809:9;2805:19;2786:39;:::i;:::-;2776:49;;2844:39;2878:3;2867:9;2863:19;2844:39;:::i;:::-;2834:49;;2902:39;2936:3;2925:9;2921:19;2902:39;:::i;:::-;2892:49;;2960:39;2994:3;2983:9;2979:19;2960:39;:::i;:::-;2950:49;;3046:3;3035:9;3031:19;3018:33;3008:43;;2285:772;;;;;;;;;;;:::o;3062:203::-;-1:-1:-1;;;;;3226:32:45;;;;3208:51;;3196:2;3181:18;;3062:203::o;3641:385::-;3727:6;3735;3743;3751;3804:3;3792:9;3783:7;3779:23;3775:33;3772:53;;;3821:1;3818;3811:12;3772:53;-1:-1:-1;;3844:23:45;;;3914:2;3899:18;;3886:32;;-1:-1:-1;3965:2:45;3950:18;;3937:32;;4016:2;4001:18;3988:32;;-1:-1:-1;3641:385:45;-1:-1:-1;3641:385:45:o;4031:260::-;4099:6;4107;4160:2;4148:9;4139:7;4135:23;4131:32;4128:52;;;4176:1;4173;4166:12;4128:52;4199:29;4218:9;4199:29;:::i;:::-;4189:39;;4247:38;4281:2;4270:9;4266:18;4247:38;:::i;:::-;4237:48;;4031:260;;;;;:::o;4296:127::-;4357:10;4352:3;4348:20;4345:1;4338:31;4388:4;4385:1;4378:15;4412:4;4409:1;4402:15;4428:128;4468:3;4499:1;4495:6;4492:1;4489:13;4486:39;;;4505:18;;:::i;:::-;-1:-1:-1;4541:9:45;;4428:128::o;4561:217::-;4601:1;4627;4617:132;;4671:10;4666:3;4662:20;4659:1;4652:31;4706:4;4703:1;4696:15;4734:4;4731:1;4724:15;4617:132;-1:-1:-1;4763:9:45;;4561:217::o;4783:127::-;4844:10;4839:3;4835:20;4832:1;4825:31;4875:4;4872:1;4865:15;4899:4;4896:1;4889:15;4915:168;4955:7;5021:1;5017;5013:6;5009:14;5006:1;5003:21;4998:1;4991:9;4984:17;4980:45;4977:71;;;5028:18;;:::i;:::-;-1:-1:-1;5068:9:45;;4915:168::o;5088:125::-;5128:4;5156:1;5153;5150:8;5147:34;;;5161:18;;:::i;:::-;-1:-1:-1;5198:9:45;;5088:125::o;5780:459::-;5965:6;5954:9;5947:25;6008:2;6003;5992:9;5988:18;5981:30;6047:6;6042:2;6031:9;6027:18;6020:34;6104:6;6096;6091:2;6080:9;6076:18;6063:48;6160:1;6131:22;;;6155:2;6127:31;;;6120:42;;;;6223:2;6202:15;;;-1:-1:-1;;6198:29:45;6183:45;6179:54;;5780:459;-1:-1:-1;;5780:459:45:o;6847:277::-;6914:6;6967:2;6955:9;6946:7;6942:23;6938:32;6935:52;;;6983:1;6980;6973:12;6935:52;7015:9;7009:16;7068:5;7061:13;7054:21;7047:5;7044:32;7034:60;;7090:1;7087;7080:12;7129:127;7190:10;7185:3;7181:20;7178:1;7171:31;7221:4;7218:1;7211:15;7245:4;7242:1;7235:15;7261:275;7332:2;7326:9;7397:2;7378:13;;-1:-1:-1;;7374:27:45;7362:40;;7432:18;7417:34;;7453:22;;;7414:62;7411:88;;;7479:18;;:::i;:::-;7515:2;7508:22;7261:275;;-1:-1:-1;7261:275:45:o;7541:1522::-;7604:5;7634:4;7678:3;7673:2;7665:6;7661:15;7657:25;7647:53;;7696:1;7693;7686:12;7647:53;7725:6;7719:13;7751:4;7774:18;7811:2;7807;7804:10;7801:36;;;7817:18;;:::i;:::-;7863:2;7860:1;7856:10;7886:28;7910:2;7906;7902:11;7886:28;:::i;:::-;7948:15;;;8018;;;8014:24;;;7979:12;;;;8050:15;;;8047:35;;;8078:1;8075;8068:12;8047:35;8114:2;8106:6;8102:15;8091:26;;8126:908;8142:6;8137:3;8134:15;8126:908;;;8221:3;8215:10;8257:2;8244:11;8241:19;8238:109;;;8301:1;8330:2;8326;8319:14;8238:109;8370:24;;8429:2;8421:11;;8417:21;-1:-1:-1;8407:119:45;;8480:1;8509:2;8505;8498:14;8407:119;8563:2;8559;8555:11;8549:18;8591:2;8616;8612;8609:10;8606:36;;;8622:18;;:::i;:::-;8670:51;8694:11;;;-1:-1:-1;;8690:25:45;8686:34;;8670:51;:::i;:::-;8750:2;8741:7;8734:19;8795:3;8789;8784:2;8780;8776:11;8772:21;8769:30;8766:123;;;8841:1;8871:3;8866;8859:16;8766:123;8902:57;8956:2;8951;8942:7;8938:16;8932:3;8928:2;8924:12;8902:57;:::i;:::-;8972:20;;-1:-1:-1;;;8159:12:45;;;;9012;;;;8126:908;;9068:628;9215:6;9223;9276:2;9264:9;9255:7;9251:23;9247:32;9244:52;;;9292:1;9289;9282:12;9244:52;9325:9;9319:16;9354:18;9395:2;9387:6;9384:14;9381:34;;;9411:1;9408;9401:12;9381:34;9434:70;9496:7;9487:6;9476:9;9472:22;9434:70;:::i;:::-;9424:80;;9550:2;9539:9;9535:18;9529:25;9513:41;;9579:2;9569:8;9566:16;9563:36;;;9595:1;9592;9585:12;9563:36;;9618:72;9682:7;9671:8;9660:9;9656:24;9618:72;:::i;:::-;9608:82;;;9068:628;;;;;:::o;9701:399::-;9858:3;9896:6;9890:13;9912:53;9958:6;9953:3;9946:4;9938:6;9934:17;9912:53;:::i;:::-;-1:-1:-1;;;;;;10026:37:45;;;;9987:16;;;;10012:52;;;10091:2;10080:14;;9701:399;-1:-1:-1;;9701:399:45:o;10105:274::-;10234:3;10272:6;10266:13;10288:53;10334:6;10329:3;10322:4;10314:6;10310:17;10288:53;:::i;:::-;10357:16;;;;;10105:274;-1:-1:-1;;10105:274:45:o;10384:184::-;10454:6;10507:2;10495:9;10486:7;10482:23;10478:32;10475:52;;;10523:1;10520;10513:12;10475:52;-1:-1:-1;10546:16:45;;10384:184;-1:-1:-1;10384:184:45:o;10573:370::-;10730:3;10768:6;10762:13;10784:53;10830:6;10825:3;10818:4;10810:6;10806:17;10784:53;:::i;:::-;10859:16;;;;10884:21;;;-1:-1:-1;10932:4:45;10921:16;;10573:370;-1:-1:-1;10573:370:45:o;11387:613::-;11654:3;11643:9;11636:22;11617:4;11681:46;11722:3;11711:9;11707:19;11699:6;11681:46;:::i;:::-;11775:9;11767:6;11763:22;11758:2;11747:9;11743:18;11736:50;11809:33;11835:6;11827;11809:33;:::i;:::-;11795:47;;11890:9;11882:6;11878:22;11873:2;11862:9;11858:18;11851:50;11918:33;11944:6;11936;11918:33;:::i;:::-;11910:41;;;11987:6;11982:2;11971:9;11967:18;11960:34;11387:613;;;;;;;:::o;13076:127::-;13137:10;13132:3;13128:20;13125:1;13118:31;13168:4;13165:1;13158:15;13192:4;13189:1;13182:15

Swarm Source

ipfs://4c98ac4f477f06f69f4028fa9440dd9c691d20f120c69e574b4c9dd17f972192
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]

A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.