Address Details
contract

0x3B545121ac63eed59A638d7B82c5dF457Ba57541

Contract Name
SpiralsStaking
Creator
0xe1c46d–097af5 at 0xaf0e32–bca1d6
Balance
0 CELO ( )
Locked CELO Balance
0.10 CELO
Voting CELO Balance
0.10 CELO
Pending Unlocked Gold
0.00 CELO
Tokens
Fetching tokens...
Transactions
1 Transactions
Transfers
2 Transfers
Gas Used
271,858
Last Balance Update
12379407
This contract has been verified via Sourcify. View contract in Sourcify repository
Contract name:
SpiralsStaking




Optimization enabled
true
Compiler version
v0.8.10+commit.fc410830




Optimization runs
200
EVM Version
london




Verified at
2022-10-05T14:28:49.404318Z

src/SpiralsStaking.sol

// SPDX-License-Identifier: Apache-2.0
// https://docs.soliditylang.org/en/v0.8.10/style-guide.html
pragma solidity ^0.8.10;

import "@openzeppelin/contracts/utils/math/SafeMath.sol";
import "./IAccounts.sol";
import "./ILockedGold.sol";
import "./IElection.sol";
import "./IRegistry.sol";
import "./IValidators.sol";

contract SpiralsStaking {
    using SafeMath for uint256;

    address public validatorGroup;
    address public owner;
    uint256 public totalStaked;
    uint256 public lastVoteCastEpoch;
    IRegistry constant c_celoRegistry =
        IRegistry(0x000000000000000000000000000000000000ce10);

    event VotesCast(
        address indexed _address,
        address indexed _validatorGroup,
        uint256 indexed amount
    );
    event VotesActivated(
        address indexed _validatorGroup,
        uint256 indexed amount
    );
    event Unstake(
        address indexed _address,
        address indexed _validatorGroup,
        uint256 indexed amount
    );

    constructor(address _validatorGroup) {
        validatorGroup = _validatorGroup;
        owner = msg.sender;
        require(getAccounts().createAccount(), "CREATE_ACCOUNT");
    }

    /// @dev Modifier for checking whether function caller is `_owner`.
    modifier onlyOwner() {
        require(msg.sender == owner, "Only owner can call this function!");
        _;
    }

    /*
     * STAKING
     */

    /// @notice Main function for staking with Spirals protocol
    /// @dev
    function stake() external payable {
        require(msg.value != 0, "NO_VALUE_STAKED");
        lock(msg.value);
        vote(msg.value);
        lastVoteCastEpoch = getElection().getEpochNumber();
        // all pending -> active for this group
        emit VotesCast(msg.sender, validatorGroup, msg.value);
    }

    /// @dev Helper function for locking CELO
    function lock(uint256 _value) public {
        getLockedGold().lock{value: _value}();
    }

    function lockDirect() public payable {
        getLockedGold().lock{value: 0.1 ether}();
    }

    function voteSignerToAccount() public returns (address account) {
        address account = getAccounts().voteSignerToAccount(address(this));
        return account;
    }

    function getLocked() public view returns (uint256) {
        return getLockedGold().getAccountTotalLockedGold(address(this));
    }

    /// @dev Helper function for casting votes with a given validator group
    function vote(uint256 _value) public {
        (address lesser, address greater) = getLesserGreater();

        require(
            !(lesser == address(0) && greater == address(0)),
            "NO_LESSER_GREATER"
        ); // Can't both be null address
        require(
            getElection().vote(validatorGroup, _value, lesser, greater),
            "VOTE_FAILED"
        );
    }

    function voteDirect() public {
        require(
            getElection().vote(
                0x5edfCe0bad47e24E30625c275457F5b4Bb619241,
                0.1 ether,
                0x87614eD7AF361a563C6a3624CcadD52e165f67C2,
                0x0000000000000000000000000000000000000000
            ),
            "VOTE2_FAILED"
        );
    }

    /// @dev Helper function for
    function getLesserGreater() public view returns (address, address) {
        (address[] memory validatorGroups, ) = getElection()
            .getTotalVotesForEligibleValidatorGroups(); // sorted by votes desc

        address lesser = address(0);
        address greater = address(0);

        for (uint256 i = 0; i < validatorGroups.length; i++) {
            if (validatorGroup == validatorGroups[i]) {
                if (i > 0) {
                    greater = validatorGroups[i - 1];
                }
                if (i < validatorGroups.length - 1) {
                    lesser = validatorGroups[i + 1];
                }
                break;
            }
        }
        return (lesser, greater);
    }

    /// @dev Activates pending votes (if ready) with a given validator group.
    function activate() external {
        IElection c_election = getElection();
        require(
            c_election.hasActivatablePendingVotes(
                address(this),
                validatorGroup
            ),
            "NOT_READY_TO_ACTIVATE"
        );
        uint256 pendingVotes = getElection().getPendingVotesForGroupByAccount(
            validatorGroup,
            address(this)
        );
        require(c_election.activate(validatorGroup), "ACTIVATE_FAILED");

        // all pending -> active for this group
        emit VotesActivated(validatorGroup, pendingVotes);
    }

    /*
     * UNSTAKING
     */

    // function unstake() public {}

    // function revoke() public {}

    // function unlock() public {}

    // function withdraw() public {}

    /*
     * OTHER
     */

    /// @notice For updating with validator group we stake with. Performs
    /// some simple checks to make sure address given is an eligible
    /// validator group (limited to 1 for now).
    function setValidatorGroup(address _newValidatorGroup) external onlyOwner {
        require(
            getValidators().isValidatorGroup(_newValidatorGroup),
            "NOT_VALIDATOR_GROUP"
        );
        require(
            getElection().getGroupEligibility(_newValidatorGroup),
            "NOT_ELIGIBLE_VG"
        );
        validatorGroup = _newValidatorGroup;
    }

    /// @notice Get active votes (staked + rewards) for this smart contract.
    function getRewards() public view returns (uint256) {
        uint256 activeVotes = getActiveVotes();
        require(totalStaked >= activeVotes, "NEGATIVE_REWARDS");
        return totalStaked - getActiveVotes();
    }

    /// @notice Get active votes (staked + rewards) for this smart contract.
    function getActiveVotes() public view returns (uint256) {
        return
            getElection().getActiveVotesForGroupByAccount(
                validatorGroup,
                address(this)
            );
    }

    /*
     * CELO SMART CONTRACT HELPERS
     */

    /// @dev Returns a Accounts.sol interface for interacting with the smart contract.
    function getAccounts() internal view returns (IAccounts) {
        address accountsAddr = c_celoRegistry.getAddressForStringOrDie(
            "Accounts"
        );
        return IAccounts(accountsAddr);
    }

    /// @dev Returns an Election.sol interface for interacting with the smart contract.
    function getElection() internal view returns (IElection) {
        address electionAddr = c_celoRegistry.getAddressForStringOrDie(
            "Election"
        );
        return IElection(electionAddr);
    }

    /// @dev Returns a LockedGold.sol interface for interacting with the smart contract.
    function getLockedGold() internal view returns (ILockedGold) {
        address lockedGoldAddr = c_celoRegistry.getAddressForStringOrDie(
            "LockedGold"
        );
        return ILockedGold(lockedGoldAddr);
    }

    /// @dev Returns a Validators.sol interface for interacting with the smart contract.
    function getValidators() internal view returns (IValidators) {
        address validatorsAddr = c_celoRegistry.getAddressForStringOrDie(
            "Validators"
        );
        return IValidators(validatorsAddr);
    }
}
        

/_openzeppelin/contracts/utils/math/SafeMath.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (utils/math/SafeMath.sol)

pragma solidity ^0.8.0;

// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.

/**
 * @dev Wrappers over Solidity's arithmetic operations.
 *
 * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler
 * now has built in overflow checking.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b > a) return (false, 0);
            return (true, a - b);
        }
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
            // benefit is lost if 'b' is also tested.
            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
            if (a == 0) return (true, 0);
            uint256 c = a * b;
            if (c / a != b) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a / b);
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a % b);
        }
    }

    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        return a + b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return a - b;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        return a * b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator.
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b <= a, errorMessage);
            return a - b;
        }
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a / b;
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a % b;
        }
    }
}
          

/src/IAccounts.sol

// SPDX-License-Identifier: Apache-2.0
// https://github.com/celo-org/celo-monorepo/tree/master/packages/protocol/contracts/governance/interfaces/ILockedGold.sol
pragma solidity >=0.5.13;

interface IAccounts {
    function isAccount(address) external view returns (bool);

    function voteSignerToAccount(address) external view returns (address);

    function validatorSignerToAccount(address) external view returns (address);

    function attestationSignerToAccount(address)
        external
        view
        returns (address);

    function signerToAccount(address) external view returns (address);

    function getAttestationSigner(address) external view returns (address);

    function getValidatorSigner(address) external view returns (address);

    function getVoteSigner(address) external view returns (address);

    function hasAuthorizedVoteSigner(address) external view returns (bool);

    function hasAuthorizedValidatorSigner(address) external view returns (bool);

    function hasAuthorizedAttestationSigner(address)
        external
        view
        returns (bool);

    function setAccountDataEncryptionKey(bytes calldata) external;

    function setMetadataURL(string calldata) external;

    function setName(string calldata) external;

    function setWalletAddress(
        address,
        uint8,
        bytes32,
        bytes32
    ) external;

    function setAccount(
        string calldata,
        bytes calldata,
        address,
        uint8,
        bytes32,
        bytes32
    ) external;

    function getDataEncryptionKey(address) external view returns (bytes memory);

    function getWalletAddress(address) external view returns (address);

    function getMetadataURL(address) external view returns (string memory);

    function batchGetMetadataURL(address[] calldata)
        external
        view
        returns (uint256[] memory, bytes memory);

    function getName(address) external view returns (string memory);

    function authorizeVoteSigner(
        address,
        uint8,
        bytes32,
        bytes32
    ) external;

    function authorizeValidatorSigner(
        address,
        uint8,
        bytes32,
        bytes32
    ) external;

    function authorizeValidatorSignerWithPublicKey(
        address,
        uint8,
        bytes32,
        bytes32,
        bytes calldata
    ) external;

    function authorizeValidatorSignerWithKeys(
        address,
        uint8,
        bytes32,
        bytes32,
        bytes calldata,
        bytes calldata,
        bytes calldata
    ) external;

    function authorizeAttestationSigner(
        address,
        uint8,
        bytes32,
        bytes32
    ) external;

    function createAccount() external returns (bool);

    function setPaymentDelegation(address, uint256) external;

    function getPaymentDelegation(address)
        external
        view
        returns (address, uint256);
}
          

/src/IElection.sol

// SPDX-License-Identifier: Apache-2.0
// https://github.com/celo-org/celo-monorepo/tree/master/packages/protocol/contracts/governance/interfaces/IElection.sol
pragma solidity >=0.5.13;

interface IElection {
    function electValidatorSigners() external view returns (address[] memory);

    function electNValidatorSigners(uint256, uint256)
        external
        view
        returns (address[] memory);

    function vote(
        address,
        uint256,
        address,
        address
    ) external returns (bool);

    function activate(address) external returns (bool);

    function revokeActive(
        address,
        uint256,
        address,
        address,
        uint256
    ) external returns (bool);

    function revokeAllActive(
        address,
        address,
        address,
        uint256
    ) external returns (bool);

    function revokePending(
        address,
        uint256,
        address,
        address,
        uint256
    ) external returns (bool);

    function markGroupIneligible(address) external;

    function markGroupEligible(
        address,
        address,
        address
    ) external;

    function forceDecrementVotes(
        address,
        uint256,
        address[] calldata,
        address[] calldata,
        uint256[] calldata
    ) external returns (uint256);

    // view functions
    function getEpochNumber() external view returns (uint256);

    function getElectableValidators() external view returns (uint256, uint256);

    function getElectabilityThreshold() external view returns (uint256);

    function getNumVotesReceivable(address) external view returns (uint256);

    function getTotalVotes() external view returns (uint256);

    function getActiveVotes() external view returns (uint256);

    function getTotalVotesByAccount(address) external view returns (uint256);

    function getPendingVotesForGroupByAccount(address, address)
        external
        view
        returns (uint256);

    function getActiveVotesForGroupByAccount(address, address)
        external
        view
        returns (uint256);

    function getTotalVotesForGroupByAccount(address, address)
        external
        view
        returns (uint256);

    function getActiveVoteUnitsForGroupByAccount(address, address)
        external
        view
        returns (uint256);

    function getTotalVotesForGroup(address) external view returns (uint256);

    function getActiveVotesForGroup(address) external view returns (uint256);

    function getPendingVotesForGroup(address) external view returns (uint256);

    function getGroupEligibility(address) external view returns (bool);

    function getGroupEpochRewards(
        address,
        uint256,
        uint256[] calldata
    ) external view returns (uint256);

    function getGroupsVotedForByAccount(address)
        external
        view
        returns (address[] memory);

    function getEligibleValidatorGroups()
        external
        view
        returns (address[] memory);

    function getTotalVotesForEligibleValidatorGroups()
        external
        view
        returns (address[] memory, uint256[] memory);

    function getCurrentValidatorSigners()
        external
        view
        returns (address[] memory);

    function canReceiveVotes(address, uint256) external view returns (bool);

    function hasActivatablePendingVotes(address, address)
        external
        view
        returns (bool);

    // only owner
    function setElectableValidators(uint256, uint256) external returns (bool);

    function setMaxNumGroupsVotedFor(uint256) external returns (bool);

    function setElectabilityThreshold(uint256) external returns (bool);

    // only VM
    function distributeEpochRewards(
        address,
        uint256,
        address,
        address
    ) external;

    event ElectableValidatorsSet(uint256 min, uint256 max);
    event MaxNumGroupsVotedForSet(uint256 maxNumGroupsVotedFor);
    event ElectabilityThresholdSet(uint256 electabilityThreshold);
    event ValidatorGroupMarkedEligible(address indexed group);
    event ValidatorGroupMarkedIneligible(address indexed group);
    event ValidatorGroupVoteCast(
        address indexed account,
        address indexed group,
        uint256 value
    );
    event ValidatorGroupVoteActivated(
        address indexed account,
        address indexed group,
        uint256 value,
        uint256 units
    );
    event ValidatorGroupPendingVoteRevoked(
        address indexed account,
        address indexed group,
        uint256 value
    );
    event ValidatorGroupActiveVoteRevoked(
        address indexed account,
        address indexed group,
        uint256 value,
        uint256 units
    );
    event EpochRewardsDistributedToVoters(address indexed group, uint256 value);
}
          

/src/ILockedGold.sol

// SPDX-License-Identifier: Apache-2.0
// https://github.com/celo-org/celo-monorepo/tree/master/packages/protocol/contracts/governance/interfaces/ILockedGold.sol
pragma solidity >=0.5.13;

interface ILockedGold {
    function incrementNonvotingAccountBalance(address, uint256) external;

    function decrementNonvotingAccountBalance(address, uint256) external;

    function getAccountTotalLockedGold(address) external view returns (uint256);

    function getAccountNonvotingLockedGold(address)
        external
        view
        returns (uint256);

    function getTotalLockedGold() external view returns (uint256);

    function getPendingWithdrawals(address)
        external
        view
        returns (uint256[] memory, uint256[] memory);

    function getTotalPendingWithdrawals(address)
        external
        view
        returns (uint256);

    function lock() external payable;

    function unlock(uint256) external;

    function relock(uint256, uint256) external;

    function withdraw(uint256) external;

    function slash(
        address account,
        uint256 penalty,
        address reporter,
        uint256 reward,
        address[] calldata lessers,
        address[] calldata greaters,
        uint256[] calldata indices
    ) external;

    function isSlasher(address) external view returns (bool);
}
          

/src/IRegistry.sol

// SPDX-License-Identifier: Apache-2.0
// https://docs.soliditylang.org/en/v0.8.10/style-guide.html
pragma solidity >=0.8.0;

interface IRegistry {
    function setAddressFor(string calldata, address) external;

    function getAddressForOrDie(bytes32) external view returns (address);

    function getAddressFor(bytes32) external view returns (address);

    function getAddressForStringOrDie(string calldata identifier)
        external
        view
        returns (address);

    function getAddressForString(string calldata identifier)
        external
        view
        returns (address);

    function isOneOf(bytes32[] calldata, address) external view returns (bool);
}
          

/src/IValidators.sol

pragma solidity >=0.8.0;

interface IValidators {
    function registerValidator(
        bytes calldata,
        bytes calldata,
        bytes calldata
    ) external returns (bool);

    function deregisterValidator(uint256) external returns (bool);

    function affiliate(address) external returns (bool);

    function deaffiliate() external returns (bool);

    function updateBlsPublicKey(bytes calldata, bytes calldata)
        external
        returns (bool);

    function registerValidatorGroup(uint256) external returns (bool);

    function deregisterValidatorGroup(uint256) external returns (bool);

    function addMember(address) external returns (bool);

    function addFirstMember(
        address,
        address,
        address
    ) external returns (bool);

    function removeMember(address) external returns (bool);

    function reorderMember(
        address,
        address,
        address
    ) external returns (bool);

    function updateCommission() external;

    function setNextCommissionUpdate(uint256) external;

    function resetSlashingMultiplier() external;

    // only owner
    function setCommissionUpdateDelay(uint256) external;

    function setMaxGroupSize(uint256) external returns (bool);

    function setMembershipHistoryLength(uint256) external returns (bool);

    function setValidatorScoreParameters(uint256, uint256)
        external
        returns (bool);

    function setGroupLockedGoldRequirements(uint256, uint256)
        external
        returns (bool);

    function setValidatorLockedGoldRequirements(uint256, uint256)
        external
        returns (bool);

    function setSlashingMultiplierResetPeriod(uint256) external;

    // view functions
    function getMaxGroupSize() external view returns (uint256);

    function getCommissionUpdateDelay() external view returns (uint256);

    function getValidatorScoreParameters()
        external
        view
        returns (uint256, uint256);

    function getMembershipHistory(address)
        external
        view
        returns (
            uint256[] memory,
            address[] memory,
            uint256,
            uint256
        );

    function calculateEpochScore(uint256) external view returns (uint256);

    function calculateGroupEpochScore(uint256[] calldata)
        external
        view
        returns (uint256);

    function getAccountLockedGoldRequirement(address)
        external
        view
        returns (uint256);

    function meetsAccountLockedGoldRequirements(address)
        external
        view
        returns (bool);

    function getValidatorBlsPublicKeyFromSigner(address)
        external
        view
        returns (bytes memory);

    function getValidator(address account)
        external
        view
        returns (
            bytes memory,
            bytes memory,
            address,
            uint256,
            address
        );

    function getValidatorGroup(address)
        external
        view
        returns (
            address[] memory,
            uint256,
            uint256,
            uint256,
            uint256[] memory,
            uint256,
            uint256
        );

    function getGroupNumMembers(address) external view returns (uint256);

    function getTopGroupValidators(address, uint256)
        external
        view
        returns (address[] memory);

    function getGroupsNumMembers(address[] calldata accounts)
        external
        view
        returns (uint256[] memory);

    function getNumRegisteredValidators() external view returns (uint256);

    function groupMembershipInEpoch(
        address,
        uint256,
        uint256
    ) external view returns (address);

    // only registered contract
    function updateEcdsaPublicKey(
        address,
        address,
        bytes calldata
    ) external returns (bool);

    function updatePublicKeys(
        address,
        address,
        bytes calldata,
        bytes calldata,
        bytes calldata
    ) external returns (bool);

    function getValidatorLockedGoldRequirements()
        external
        view
        returns (uint256, uint256);

    function getGroupLockedGoldRequirements()
        external
        view
        returns (uint256, uint256);

    function getRegisteredValidators() external view returns (address[] memory);

    function getRegisteredValidatorSigners()
        external
        view
        returns (address[] memory);

    function getRegisteredValidatorGroups()
        external
        view
        returns (address[] memory);

    function isValidatorGroup(address) external view returns (bool);

    function isValidator(address) external view returns (bool);

    function getValidatorGroupSlashingMultiplier(address)
        external
        view
        returns (uint256);

    function getMembershipInLastEpoch(address) external view returns (address);

    function getMembershipInLastEpochFromSigner(address)
        external
        view
        returns (address);

    // only VM
    function updateValidatorScoreFromSigner(address, uint256) external;

    function distributeEpochPaymentsFromSigner(address, uint256)
        external
        returns (uint256);

    // only slasher
    function forceDeaffiliateIfValidator(address) external;

    function halveSlashingMultiplier(address) external;
}
          

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_validatorGroup","internalType":"address"}]},{"type":"event","name":"Unstake","inputs":[{"type":"address","name":"_address","internalType":"address","indexed":true},{"type":"address","name":"_validatorGroup","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"VotesActivated","inputs":[{"type":"address","name":"_validatorGroup","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"VotesCast","inputs":[{"type":"address","name":"_address","internalType":"address","indexed":true},{"type":"address","name":"_validatorGroup","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"activate","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getActiveVotes","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"},{"type":"address","name":"","internalType":"address"}],"name":"getLesserGreater","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getLocked","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getRewards","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"lastVoteCastEpoch","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"lock","inputs":[{"type":"uint256","name":"_value","internalType":"uint256"}]},{"type":"function","stateMutability":"payable","outputs":[],"name":"lockDirect","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setValidatorGroup","inputs":[{"type":"address","name":"_newValidatorGroup","internalType":"address"}]},{"type":"function","stateMutability":"payable","outputs":[],"name":"stake","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalStaked","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"validatorGroup","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"vote","inputs":[{"type":"uint256","name":"_value","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"voteDirect","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"address","name":"account","internalType":"address"}],"name":"voteSignerToAccount","inputs":[]}]
              

Contract Creation Code

0x60806040523480156200001157600080fd5b50604051620013b0380380620013b083398101604081905262000034916200019e565b600080546001600160a01b0383166001600160a01b03199182161790915560018054909116331790556200006762000116565b6001600160a01b0316639dca362f6040518163ffffffff1660e01b81526004016020604051808303816000875af1158015620000a7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000cd9190620001d0565b6200010f5760405162461bcd60e51b815260206004820152600e60248201526d10d49150551157d050d0d3d5539560921b604482015260640160405180910390fd5b50620001f4565b60405163224cb2fd60e21b81526020600482015260086024820152674163636f756e747360c01b6044820152600090819061ce1090638932cbf490606401602060405180830381865afa15801562000172573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200019891906200019e565b92915050565b600060208284031215620001b157600080fd5b81516001600160a01b0381168114620001c957600080fd5b9392505050565b600060208284031215620001e357600080fd5b81518015158114620001c957600080fd5b6111ac80620002046000396000f3fe6080604052600436106100f35760003560e01c8063417c393d1161008a5780638da5cb5b116100595780638da5cb5b1461024a57806393f922ca1461026a578063dd4670641461027f578063ec4e3a311461029f57600080fd5b8063417c393d146101c6578063680104c5146101fe5780636b4c3c611461021e578063817b1cd21461023457600080fd5b806322a7a41c116100c657806322a7a41c1461016c5780632d49ffcd146101a15780632e4dec8c146101b65780633a4b66f1146101be57600080fd5b80630121b93f146100f85780630572b0cc1461011a5780630f15f4c0146101425780631f60424314610157575b600080fd5b34801561010457600080fd5b50610118610113366004610eb8565b6102b4565b005b34801561012657600080fd5b5061012f6103f5565b6040519081526020015b60405180910390f35b34801561014e57600080fd5b50610118610462565b34801561016357600080fd5b5061012f61068f565b34801561017857600080fd5b50610181610712565b604080516001600160a01b03938416815292909116602083015201610139565b3480156101ad57600080fd5b5061012f610854565b61011861088c565b6101186108f1565b3480156101d257600080fd5b506000546101e6906001600160a01b031681565b6040516001600160a01b039091168152602001610139565b34801561020a57600080fd5b50610118610219366004610ee9565b6109eb565b34801561022a57600080fd5b5061012f60035481565b34801561024057600080fd5b5061012f60025481565b34801561025657600080fd5b506001546101e6906001600160a01b031681565b34801561027657600080fd5b506101e6610bda565b34801561028b57600080fd5b5061011861029a366004610eb8565b610c56565b3480156102ab57600080fd5b50610118610cb4565b6000806102bf610712565b90925090506001600160a01b0382161580156102e257506001600160a01b038116155b156103285760405162461bcd60e51b81526020600482015260116024820152702727afa622a9a9a2a92fa3a922a0aa22a960791b60448201526064015b60405180910390fd5b610330610da8565b600054604051632c06ba3d60e11b81526001600160a01b039182166004820152602481018690528482166044820152838216606482015291169063580d747a906084016020604051808303816000875af1158015610392573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103b69190610f0d565b6103f05760405162461bcd60e51b815260206004820152600b60248201526a1593d51157d1905253115160aa1b604482015260640161031f565b505050565b60008061040061068f565b90508060025410156104475760405162461bcd60e51b815260206004820152601060248201526f4e454741544956455f5245574152445360801b604482015260640161031f565b61044f61068f565b60025461045c9190610f45565b91505090565b600061046c610da8565b60005460405163098fb3dd60e21b81523060048201526001600160a01b03918216602482015291925082169063263ecf7490604401602060405180830381865afa1580156104be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104e29190610f0d565b6105265760405162461bcd60e51b81526020600482015260156024820152744e4f545f52454144595f544f5f414354495641544560581b604482015260640161031f565b6000610530610da8565b600054604051639b95975f60e01b81526001600160a01b039182166004820152306024820152911690639b95975f90604401602060405180830381865afa15801561057f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105a39190610f5c565b600054604051630716a76760e21b81526001600160a01b039182166004820152919250831690631c5a9d9c906024016020604051808303816000875af11580156105f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106159190610f0d565b6106535760405162461bcd60e51b815260206004820152600f60248201526e1050d5125590551157d19052531151608a1b604482015260640161031f565b6000805460405183926001600160a01b03909216917ffdb3176a1ebea0dc05bd03e3910d445075e04e92e0b93908f75b4d64a18effaa91a35050565b6000610699610da8565b6000546040516334f890a960e21b81526001600160a01b03918216600482015230602482015291169063d3e242a4906044015b602060405180830381865afa1580156106e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070d9190610f5c565b905090565b600080600061071f610da8565b6001600160a01b0316637046c96b6040518163ffffffff1660e01b8152600401600060405180830381865afa15801561075c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610784919081019061104b565b50905060008060005b8351811015610849578381815181106107a8576107a8611110565b60209081029190910101516000546001600160a01b03908116911614156108375780156107f657836107db600183610f45565b815181106107eb576107eb611110565b602002602001015191505b600184516108049190610f45565b8110156108325783610817826001611126565b8151811061082757610827611110565b602002602001015192505b610849565b806108418161113e565b91505061078d565b509094909350915050565b600061085e610deb565b6040516330ec70f560e01b81523060048201526001600160a01b0391909116906330ec70f5906024016106cc565b610894610deb565b6001600160a01b031663f83d08ba67016345785d8a00006040518263ffffffff1660e01b81526004016000604051808303818588803b1580156108d657600080fd5b505af11580156108ea573d6000803e3d6000fd5b5050505050565b346109305760405162461bcd60e51b815260206004820152600f60248201526e1393d7d59053155157d4d51052d151608a1b604482015260640161031f565b61093934610c56565b610942346102b4565b61094a610da8565b6001600160a01b0316639a7b3be76040518163ffffffff1660e01b8152600401602060405180830381865afa158015610987573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109ab9190610f5c565b6003556000805460405134926001600160a01b039092169133917fc903789bc217ae62d94ab93c15368f82a58d0e1c9d1724fce2b4cd9a6a24f6009190a4565b6001546001600160a01b03163314610a505760405162461bcd60e51b815260206004820152602260248201527f4f6e6c79206f776e65722063616e2063616c6c20746869732066756e6374696f6044820152616e2160f01b606482015260840161031f565b610a58610e30565b6040516329789d2760e11b81526001600160a01b03838116600483015291909116906352f13a4e90602401602060405180830381865afa158015610aa0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ac49190610f0d565b610b065760405162461bcd60e51b815260206004820152601360248201527204e4f545f56414c494441544f525f47524f555606c1b604482015260640161031f565b610b0e610da8565b604051638c66677560e01b81526001600160a01b0383811660048301529190911690638c66677590602401602060405180830381865afa158015610b56573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7a9190610f0d565b610bb85760405162461bcd60e51b815260206004820152600f60248201526e4e4f545f454c494749424c455f564760881b604482015260640161031f565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b600080610be5610e75565b604051631990b56560e21b81523060048201526001600160a01b039190911690636642d594906024015b602060405180830381865afa158015610c2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c509190611159565b92915050565b610c5e610deb565b6001600160a01b031663f83d08ba826040518263ffffffff1660e01b81526004016000604051808303818588803b158015610c9857600080fd5b505af1158015610cac573d6000803e3d6000fd5b505050505050565b610cbc610da8565b604051632c06ba3d60e11b8152735edfce0bad47e24e30625c275457f5b4bb619241600482015267016345785d8a000060248201527387614ed7af361a563c6a3624ccadd52e165f67c26044820152600060648201526001600160a01b03919091169063580d747a906084016020604051808303816000875af1158015610d47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d6b9190610f0d565b610da65760405162461bcd60e51b815260206004820152600c60248201526b1593d5114c97d1905253115160a21b604482015260640161031f565b565b60405163224cb2fd60e21b815260206004820152600860248201526722b632b1ba34b7b760c11b6044820152600090819061ce1090638932cbf490606401610c0f565b60405163224cb2fd60e21b815260206004820152600a602482015269131bd8dad95911dbdb1960b21b6044820152600090819061ce1090638932cbf490606401610c0f565b60405163224cb2fd60e21b815260206004820152600a60248201526956616c696461746f727360b01b6044820152600090819061ce1090638932cbf490606401610c0f565b60405163224cb2fd60e21b81526020600482015260086024820152674163636f756e747360c01b6044820152600090819061ce1090638932cbf490606401610c0f565b600060208284031215610eca57600080fd5b5035919050565b6001600160a01b0381168114610ee657600080fd5b50565b600060208284031215610efb57600080fd5b8135610f0681610ed1565b9392505050565b600060208284031215610f1f57600080fd5b81518015158114610f0657600080fd5b634e487b7160e01b600052601160045260246000fd5b600082821015610f5757610f57610f2f565b500390565b600060208284031215610f6e57600080fd5b5051919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715610fb457610fb4610f75565b604052919050565b600067ffffffffffffffff821115610fd657610fd6610f75565b5060051b60200190565b600082601f830112610ff157600080fd5b8151602061100661100183610fbc565b610f8b565b82815260059290921b8401810191818101908684111561102557600080fd5b8286015b848110156110405780518352918301918301611029565b509695505050505050565b6000806040838503121561105e57600080fd5b825167ffffffffffffffff8082111561107657600080fd5b818501915085601f83011261108a57600080fd5b8151602061109a61100183610fbc565b82815260059290921b840181019181810190898411156110b957600080fd5b948201945b838610156110e05785516110d181610ed1565b825294820194908201906110be565b918801519196509093505050808211156110f957600080fd5b5061110685828601610fe0565b9150509250929050565b634e487b7160e01b600052603260045260246000fd5b6000821982111561113957611139610f2f565b500190565b600060001982141561115257611152610f2f565b5060010190565b60006020828403121561116b57600080fd5b8151610f0681610ed156fea26469706673582212200c2a5892bb78792e16209e796d0a9026fed3d108af5473dbde1d02a7cfac906264736f6c634300080a00330000000000000000000000005edfce0bad47e24e30625c275457f5b4bb619241

Deployed ByteCode

0x6080604052600436106100f35760003560e01c8063417c393d1161008a5780638da5cb5b116100595780638da5cb5b1461024a57806393f922ca1461026a578063dd4670641461027f578063ec4e3a311461029f57600080fd5b8063417c393d146101c6578063680104c5146101fe5780636b4c3c611461021e578063817b1cd21461023457600080fd5b806322a7a41c116100c657806322a7a41c1461016c5780632d49ffcd146101a15780632e4dec8c146101b65780633a4b66f1146101be57600080fd5b80630121b93f146100f85780630572b0cc1461011a5780630f15f4c0146101425780631f60424314610157575b600080fd5b34801561010457600080fd5b50610118610113366004610eb8565b6102b4565b005b34801561012657600080fd5b5061012f6103f5565b6040519081526020015b60405180910390f35b34801561014e57600080fd5b50610118610462565b34801561016357600080fd5b5061012f61068f565b34801561017857600080fd5b50610181610712565b604080516001600160a01b03938416815292909116602083015201610139565b3480156101ad57600080fd5b5061012f610854565b61011861088c565b6101186108f1565b3480156101d257600080fd5b506000546101e6906001600160a01b031681565b6040516001600160a01b039091168152602001610139565b34801561020a57600080fd5b50610118610219366004610ee9565b6109eb565b34801561022a57600080fd5b5061012f60035481565b34801561024057600080fd5b5061012f60025481565b34801561025657600080fd5b506001546101e6906001600160a01b031681565b34801561027657600080fd5b506101e6610bda565b34801561028b57600080fd5b5061011861029a366004610eb8565b610c56565b3480156102ab57600080fd5b50610118610cb4565b6000806102bf610712565b90925090506001600160a01b0382161580156102e257506001600160a01b038116155b156103285760405162461bcd60e51b81526020600482015260116024820152702727afa622a9a9a2a92fa3a922a0aa22a960791b60448201526064015b60405180910390fd5b610330610da8565b600054604051632c06ba3d60e11b81526001600160a01b039182166004820152602481018690528482166044820152838216606482015291169063580d747a906084016020604051808303816000875af1158015610392573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103b69190610f0d565b6103f05760405162461bcd60e51b815260206004820152600b60248201526a1593d51157d1905253115160aa1b604482015260640161031f565b505050565b60008061040061068f565b90508060025410156104475760405162461bcd60e51b815260206004820152601060248201526f4e454741544956455f5245574152445360801b604482015260640161031f565b61044f61068f565b60025461045c9190610f45565b91505090565b600061046c610da8565b60005460405163098fb3dd60e21b81523060048201526001600160a01b03918216602482015291925082169063263ecf7490604401602060405180830381865afa1580156104be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104e29190610f0d565b6105265760405162461bcd60e51b81526020600482015260156024820152744e4f545f52454144595f544f5f414354495641544560581b604482015260640161031f565b6000610530610da8565b600054604051639b95975f60e01b81526001600160a01b039182166004820152306024820152911690639b95975f90604401602060405180830381865afa15801561057f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105a39190610f5c565b600054604051630716a76760e21b81526001600160a01b039182166004820152919250831690631c5a9d9c906024016020604051808303816000875af11580156105f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106159190610f0d565b6106535760405162461bcd60e51b815260206004820152600f60248201526e1050d5125590551157d19052531151608a1b604482015260640161031f565b6000805460405183926001600160a01b03909216917ffdb3176a1ebea0dc05bd03e3910d445075e04e92e0b93908f75b4d64a18effaa91a35050565b6000610699610da8565b6000546040516334f890a960e21b81526001600160a01b03918216600482015230602482015291169063d3e242a4906044015b602060405180830381865afa1580156106e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070d9190610f5c565b905090565b600080600061071f610da8565b6001600160a01b0316637046c96b6040518163ffffffff1660e01b8152600401600060405180830381865afa15801561075c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610784919081019061104b565b50905060008060005b8351811015610849578381815181106107a8576107a8611110565b60209081029190910101516000546001600160a01b03908116911614156108375780156107f657836107db600183610f45565b815181106107eb576107eb611110565b602002602001015191505b600184516108049190610f45565b8110156108325783610817826001611126565b8151811061082757610827611110565b602002602001015192505b610849565b806108418161113e565b91505061078d565b509094909350915050565b600061085e610deb565b6040516330ec70f560e01b81523060048201526001600160a01b0391909116906330ec70f5906024016106cc565b610894610deb565b6001600160a01b031663f83d08ba67016345785d8a00006040518263ffffffff1660e01b81526004016000604051808303818588803b1580156108d657600080fd5b505af11580156108ea573d6000803e3d6000fd5b5050505050565b346109305760405162461bcd60e51b815260206004820152600f60248201526e1393d7d59053155157d4d51052d151608a1b604482015260640161031f565b61093934610c56565b610942346102b4565b61094a610da8565b6001600160a01b0316639a7b3be76040518163ffffffff1660e01b8152600401602060405180830381865afa158015610987573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109ab9190610f5c565b6003556000805460405134926001600160a01b039092169133917fc903789bc217ae62d94ab93c15368f82a58d0e1c9d1724fce2b4cd9a6a24f6009190a4565b6001546001600160a01b03163314610a505760405162461bcd60e51b815260206004820152602260248201527f4f6e6c79206f776e65722063616e2063616c6c20746869732066756e6374696f6044820152616e2160f01b606482015260840161031f565b610a58610e30565b6040516329789d2760e11b81526001600160a01b03838116600483015291909116906352f13a4e90602401602060405180830381865afa158015610aa0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ac49190610f0d565b610b065760405162461bcd60e51b815260206004820152601360248201527204e4f545f56414c494441544f525f47524f555606c1b604482015260640161031f565b610b0e610da8565b604051638c66677560e01b81526001600160a01b0383811660048301529190911690638c66677590602401602060405180830381865afa158015610b56573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7a9190610f0d565b610bb85760405162461bcd60e51b815260206004820152600f60248201526e4e4f545f454c494749424c455f564760881b604482015260640161031f565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b600080610be5610e75565b604051631990b56560e21b81523060048201526001600160a01b039190911690636642d594906024015b602060405180830381865afa158015610c2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c509190611159565b92915050565b610c5e610deb565b6001600160a01b031663f83d08ba826040518263ffffffff1660e01b81526004016000604051808303818588803b158015610c9857600080fd5b505af1158015610cac573d6000803e3d6000fd5b505050505050565b610cbc610da8565b604051632c06ba3d60e11b8152735edfce0bad47e24e30625c275457f5b4bb619241600482015267016345785d8a000060248201527387614ed7af361a563c6a3624ccadd52e165f67c26044820152600060648201526001600160a01b03919091169063580d747a906084016020604051808303816000875af1158015610d47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d6b9190610f0d565b610da65760405162461bcd60e51b815260206004820152600c60248201526b1593d5114c97d1905253115160a21b604482015260640161031f565b565b60405163224cb2fd60e21b815260206004820152600860248201526722b632b1ba34b7b760c11b6044820152600090819061ce1090638932cbf490606401610c0f565b60405163224cb2fd60e21b815260206004820152600a602482015269131bd8dad95911dbdb1960b21b6044820152600090819061ce1090638932cbf490606401610c0f565b60405163224cb2fd60e21b815260206004820152600a60248201526956616c696461746f727360b01b6044820152600090819061ce1090638932cbf490606401610c0f565b60405163224cb2fd60e21b81526020600482015260086024820152674163636f756e747360c01b6044820152600090819061ce1090638932cbf490606401610c0f565b600060208284031215610eca57600080fd5b5035919050565b6001600160a01b0381168114610ee657600080fd5b50565b600060208284031215610efb57600080fd5b8135610f0681610ed1565b9392505050565b600060208284031215610f1f57600080fd5b81518015158114610f0657600080fd5b634e487b7160e01b600052601160045260246000fd5b600082821015610f5757610f57610f2f565b500390565b600060208284031215610f6e57600080fd5b5051919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715610fb457610fb4610f75565b604052919050565b600067ffffffffffffffff821115610fd657610fd6610f75565b5060051b60200190565b600082601f830112610ff157600080fd5b8151602061100661100183610fbc565b610f8b565b82815260059290921b8401810191818101908684111561102557600080fd5b8286015b848110156110405780518352918301918301611029565b509695505050505050565b6000806040838503121561105e57600080fd5b825167ffffffffffffffff8082111561107657600080fd5b818501915085601f83011261108a57600080fd5b8151602061109a61100183610fbc565b82815260059290921b840181019181810190898411156110b957600080fd5b948201945b838610156110e05785516110d181610ed1565b825294820194908201906110be565b918801519196509093505050808211156110f957600080fd5b5061110685828601610fe0565b9150509250929050565b634e487b7160e01b600052603260045260246000fd5b6000821982111561113957611139610f2f565b500190565b600060001982141561115257611152610f2f565b5060010190565b60006020828403121561116b57600080fd5b8151610f0681610ed156fea26469706673582212200c2a5892bb78792e16209e796d0a9026fed3d108af5473dbde1d02a7cfac906264736f6c634300080a0033