Address Details
contract

0xf666D879e0480f0Dd9F64D3c31Abd9F89ffA85C9

Contract Name
SpiralsStaking
Creator
0xe1c46d–097af5 at 0x83e468–aa82d2
Balance
0 CELO ( )
Locked CELO Balance
0.16 CELO
Voting CELO Balance
0.16 CELO
Pending Unlocked Gold
0.00 CELO
Tokens
Fetching tokens...
Transactions
Fetching transactions...
Transfers
Fetching transfers...
Gas Used
Fetching gas used...
Last Balance Update
13967913
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-07-18T22:28:55.265843Z

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;
    IRegistry constant c_celoRegistry =
        IRegistry(0x000000000000000000000000000000000000ce10);

    mapping(address => uint256) stakeByAccount;

    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);

        stakeByAccount[msg.sender] = stakeByAccount[msg.sender].add(msg.value);
        totalStaked = totalStaked.add(msg.value);

        // all pending -> active for this group
        emit VotesCast(msg.sender, validatorGroup, msg.value);
    }

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

    /// @dev Helper function for casting votes with a given validator group
    function vote(uint256 _value) internal {
        (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"
        );
    }

    /// @dev Helper function for getting the 2 validator groups that
    /// our target validator group is sandwiched between.
    function getLesserGreater() internal 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 onlyOwner {
        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();
        (uint256 pendingVotes, ) = getPendingVotes();

        require(
            activeVotes.add(pendingVotes) >= totalStaked,
            "NEGATIVE_REWARDS"
        );

        return activeVotes.add(pendingVotes).sub(totalStaked);
    }

    /// @notice Get pending votes for this smart contract.
    function getPendingVotes() public view returns (uint256, bool) {
        return (
            getElection().getPendingVotesForGroupByAccount(
                validatorGroup,
                address(this)
            ),
            getElection().hasActivatablePendingVotes(
                validatorGroup,
                address(this)
            )
        );
    }

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

    /// @notice Returns the amount a certain address is currently staking
    /// with Spirals.
    function getStakeForAccount(address _address)
        public
        view
        returns (uint256)
    {
        return stakeByAccount[_address];
    }

    /*
     * 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":"uint256","name":"","internalType":"uint256"},{"type":"bool","name":"","internalType":"bool"}],"name":"getPendingVotes","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":"getStakeForAccount","inputs":[{"type":"address","name":"_address","internalType":"address"}]},{"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":[]}]
              

Contract Creation Code

0x60806040523480156200001157600080fd5b50604051620011e7380380620011e783398101604081905262000034916200019e565b600080546001600160a01b0383166001600160a01b03199182161790915560018054909116331790556200006762000116565b6001600160a01b0316639dca362f6040518163ffffffff1660e01b81526004016020604051808303816000875af1158015620000a7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000cd9190620001d0565b6200010f5760405162461bcd60e51b815260206004820152600e60248201526d10d49150551157d050d0d3d5539560921b604482015260640160405180910390fd5b50620001f4565b60405163224cb2fd60e21b81526020600482015260086024820152674163636f756e747360c01b6044820152600090819061ce1090638932cbf490606401602060405180830381865afa15801562000172573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200019891906200019e565b92915050565b600060208284031215620001b157600080fd5b81516001600160a01b0381168114620001c957600080fd5b9392505050565b600060208284031215620001e357600080fd5b81518015158114620001c957600080fd5b610fe380620002046000396000f3fe6080604052600436106100915760003560e01c8063417c393d11610059578063417c393d1461011c578063680104c514610154578063817b1cd2146101745780638da5cb5b1461018a578063c0c62018146101aa57600080fd5b80630572b0cc146100965780630f15f4c0146100be5780631f604243146100d55780631f8dfbd3146100ea5780633a4b66f114610114575b600080fd5b3480156100a257600080fd5b506100ab6101e0565b6040519081526020015b60405180910390f35b3480156100ca57600080fd5b506100d361026c565b005b3480156100e157600080fd5b506100ab6104c3565b3480156100f657600080fd5b506100ff610545565b604080519283529015156020830152016100b5565b6100d3610646565b34801561012857600080fd5b5060005461013c906001600160a01b031681565b6040516001600160a01b0390911681526020016100b5565b34801561016057600080fd5b506100d361016f366004610ce5565b61070e565b34801561018057600080fd5b506100ab60025481565b34801561019657600080fd5b5060015461013c906001600160a01b031681565b3480156101b657600080fd5b506100ab6101c5366004610ce5565b6001600160a01b031660009081526003602052604090205490565b6000806101eb6104c3565b905060006101f7610545565b5060025490915061020883836108c2565b101561024e5760405162461bcd60e51b815260206004820152601060248201526f4e454741544956455f5245574152445360801b60448201526064015b60405180910390fd5b6002546102659061025f84846108c2565b906108d5565b9250505090565b6001546001600160a01b031633146102965760405162461bcd60e51b815260040161024590610d02565b60006102a06108e1565b60005460405163098fb3dd60e21b81523060048201526001600160a01b03918216602482015291925082169063263ecf7490604401602060405180830381865afa1580156102f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103169190610d44565b61035a5760405162461bcd60e51b81526020600482015260156024820152744e4f545f52454144595f544f5f414354495641544560581b6044820152606401610245565b60006103646108e1565b600054604051639b95975f60e01b81526001600160a01b039182166004820152306024820152911690639b95975f90604401602060405180830381865afa1580156103b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103d79190610d66565b600054604051630716a76760e21b81526001600160a01b039182166004820152919250831690631c5a9d9c906024016020604051808303816000875af1158015610425573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104499190610d44565b6104875760405162461bcd60e51b815260206004820152600f60248201526e1050d5125590551157d19052531151608a1b6044820152606401610245565b6000805460405183926001600160a01b03909216917ffdb3176a1ebea0dc05bd03e3910d445075e04e92e0b93908f75b4d64a18effaa91a35050565b60006104cd6108e1565b6000546040516334f890a960e21b81526001600160a01b03918216600482015230602482015291169063d3e242a490604401602060405180830381865afa15801561051c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105409190610d66565b905090565b6000806105506108e1565b600054604051639b95975f60e01b81526001600160a01b039182166004820152306024820152911690639b95975f90604401602060405180830381865afa15801561059f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105c39190610d66565b6105cb6108e1565b60005460405163098fb3dd60e21b81526001600160a01b03918216600482015230602482015291169063263ecf7490604401602060405180830381865afa15801561061a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061063e9190610d44565b915091509091565b346106855760405162461bcd60e51b815260206004820152600f60248201526e1393d7d59053155157d4d51052d151608a1b6044820152606401610245565b61068e34610967565b610697346109c5565b336000908152600360205260409020546106b190346108c2565b336000908152600360205260409020556002546106ce90346108c2565b6002556000805460405134926001600160a01b039092169133917fc903789bc217ae62d94ab93c15368f82a58d0e1c9d1724fce2b4cd9a6a24f6009190a4565b6001546001600160a01b031633146107385760405162461bcd60e51b815260040161024590610d02565b610740610b01565b6040516329789d2760e11b81526001600160a01b03838116600483015291909116906352f13a4e90602401602060405180830381865afa158015610788573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ac9190610d44565b6107ee5760405162461bcd60e51b815260206004820152601360248201527204e4f545f56414c494441544f525f47524f555606c1b6044820152606401610245565b6107f66108e1565b604051638c66677560e01b81526001600160a01b0383811660048301529190911690638c66677590602401602060405180830381865afa15801561083e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108629190610d44565b6108a05760405162461bcd60e51b815260206004820152600f60248201526e4e4f545f454c494749424c455f564760881b6044820152606401610245565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b60006108ce8284610d95565b9392505050565b60006108ce8284610dad565b60405163224cb2fd60e21b815260206004820152600860248201526722b632b1ba34b7b760c11b6044820152600090819061ce1090638932cbf4906064015b602060405180830381865afa15801561093d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109619190610dc4565b92915050565b61096f610b46565b6001600160a01b031663f83d08ba826040518263ffffffff1660e01b81526004016000604051808303818588803b1580156109a957600080fd5b505af11580156109bd573d6000803e3d6000fd5b505050505050565b6000806109d0610b8b565b90925090506001600160a01b0382161580156109f357506001600160a01b038116155b15610a345760405162461bcd60e51b81526020600482015260116024820152702727afa622a9a9a2a92fa3a922a0aa22a960791b6044820152606401610245565b610a3c6108e1565b600054604051632c06ba3d60e11b81526001600160a01b039182166004820152602481018690528482166044820152838216606482015291169063580d747a906084016020604051808303816000875af1158015610a9e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ac29190610d44565b610afc5760405162461bcd60e51b815260206004820152600b60248201526a1593d51157d1905253115160aa1b6044820152606401610245565b505050565b60405163224cb2fd60e21b815260206004820152600a60248201526956616c696461746f727360b01b6044820152600090819061ce1090638932cbf490606401610920565b60405163224cb2fd60e21b815260206004820152600a602482015269131bd8dad95911dbdb1960b21b6044820152600090819061ce1090638932cbf490606401610920565b6000806000610b986108e1565b6001600160a01b0316637046c96b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610bd5573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610bfd9190810190610eb7565b50905060008060005b8351811015610cc257838181518110610c2157610c21610f7c565b60209081029190910101516000546001600160a01b0390811691161415610cb0578015610c6f5783610c54600183610dad565b81518110610c6457610c64610f7c565b602002602001015191505b60018451610c7d9190610dad565b811015610cab5783610c90826001610d95565b81518110610ca057610ca0610f7c565b602002602001015192505b610cc2565b80610cba81610f92565b915050610c06565b509094909350915050565b6001600160a01b0381168114610ce257600080fd5b50565b600060208284031215610cf757600080fd5b81356108ce81610ccd565b60208082526022908201527f4f6e6c79206f776e65722063616e2063616c6c20746869732066756e6374696f6040820152616e2160f01b606082015260800190565b600060208284031215610d5657600080fd5b815180151581146108ce57600080fd5b600060208284031215610d7857600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b60008219821115610da857610da8610d7f565b500190565b600082821015610dbf57610dbf610d7f565b500390565b600060208284031215610dd657600080fd5b81516108ce81610ccd565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715610e2057610e20610de1565b604052919050565b600067ffffffffffffffff821115610e4257610e42610de1565b5060051b60200190565b600082601f830112610e5d57600080fd5b81516020610e72610e6d83610e28565b610df7565b82815260059290921b84018101918181019086841115610e9157600080fd5b8286015b84811015610eac5780518352918301918301610e95565b509695505050505050565b60008060408385031215610eca57600080fd5b825167ffffffffffffffff80821115610ee257600080fd5b818501915085601f830112610ef657600080fd5b81516020610f06610e6d83610e28565b82815260059290921b84018101918181019089841115610f2557600080fd5b948201945b83861015610f4c578551610f3d81610ccd565b82529482019490820190610f2a565b91880151919650909350505080821115610f6557600080fd5b50610f7285828601610e4c565b9150509250929050565b634e487b7160e01b600052603260045260246000fd5b6000600019821415610fa657610fa6610d7f565b506001019056fea2646970667358221220d65163872280a1d2367f72846fdece6e94157181552595b456b19c996085ae5f64736f6c634300080a003300000000000000000000000070fc0b021dfdbb9a106d1ed8f35f59d3f23ecb7b

Deployed ByteCode

0x6080604052600436106100915760003560e01c8063417c393d11610059578063417c393d1461011c578063680104c514610154578063817b1cd2146101745780638da5cb5b1461018a578063c0c62018146101aa57600080fd5b80630572b0cc146100965780630f15f4c0146100be5780631f604243146100d55780631f8dfbd3146100ea5780633a4b66f114610114575b600080fd5b3480156100a257600080fd5b506100ab6101e0565b6040519081526020015b60405180910390f35b3480156100ca57600080fd5b506100d361026c565b005b3480156100e157600080fd5b506100ab6104c3565b3480156100f657600080fd5b506100ff610545565b604080519283529015156020830152016100b5565b6100d3610646565b34801561012857600080fd5b5060005461013c906001600160a01b031681565b6040516001600160a01b0390911681526020016100b5565b34801561016057600080fd5b506100d361016f366004610ce5565b61070e565b34801561018057600080fd5b506100ab60025481565b34801561019657600080fd5b5060015461013c906001600160a01b031681565b3480156101b657600080fd5b506100ab6101c5366004610ce5565b6001600160a01b031660009081526003602052604090205490565b6000806101eb6104c3565b905060006101f7610545565b5060025490915061020883836108c2565b101561024e5760405162461bcd60e51b815260206004820152601060248201526f4e454741544956455f5245574152445360801b60448201526064015b60405180910390fd5b6002546102659061025f84846108c2565b906108d5565b9250505090565b6001546001600160a01b031633146102965760405162461bcd60e51b815260040161024590610d02565b60006102a06108e1565b60005460405163098fb3dd60e21b81523060048201526001600160a01b03918216602482015291925082169063263ecf7490604401602060405180830381865afa1580156102f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103169190610d44565b61035a5760405162461bcd60e51b81526020600482015260156024820152744e4f545f52454144595f544f5f414354495641544560581b6044820152606401610245565b60006103646108e1565b600054604051639b95975f60e01b81526001600160a01b039182166004820152306024820152911690639b95975f90604401602060405180830381865afa1580156103b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103d79190610d66565b600054604051630716a76760e21b81526001600160a01b039182166004820152919250831690631c5a9d9c906024016020604051808303816000875af1158015610425573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104499190610d44565b6104875760405162461bcd60e51b815260206004820152600f60248201526e1050d5125590551157d19052531151608a1b6044820152606401610245565b6000805460405183926001600160a01b03909216917ffdb3176a1ebea0dc05bd03e3910d445075e04e92e0b93908f75b4d64a18effaa91a35050565b60006104cd6108e1565b6000546040516334f890a960e21b81526001600160a01b03918216600482015230602482015291169063d3e242a490604401602060405180830381865afa15801561051c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105409190610d66565b905090565b6000806105506108e1565b600054604051639b95975f60e01b81526001600160a01b039182166004820152306024820152911690639b95975f90604401602060405180830381865afa15801561059f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105c39190610d66565b6105cb6108e1565b60005460405163098fb3dd60e21b81526001600160a01b03918216600482015230602482015291169063263ecf7490604401602060405180830381865afa15801561061a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061063e9190610d44565b915091509091565b346106855760405162461bcd60e51b815260206004820152600f60248201526e1393d7d59053155157d4d51052d151608a1b6044820152606401610245565b61068e34610967565b610697346109c5565b336000908152600360205260409020546106b190346108c2565b336000908152600360205260409020556002546106ce90346108c2565b6002556000805460405134926001600160a01b039092169133917fc903789bc217ae62d94ab93c15368f82a58d0e1c9d1724fce2b4cd9a6a24f6009190a4565b6001546001600160a01b031633146107385760405162461bcd60e51b815260040161024590610d02565b610740610b01565b6040516329789d2760e11b81526001600160a01b03838116600483015291909116906352f13a4e90602401602060405180830381865afa158015610788573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ac9190610d44565b6107ee5760405162461bcd60e51b815260206004820152601360248201527204e4f545f56414c494441544f525f47524f555606c1b6044820152606401610245565b6107f66108e1565b604051638c66677560e01b81526001600160a01b0383811660048301529190911690638c66677590602401602060405180830381865afa15801561083e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108629190610d44565b6108a05760405162461bcd60e51b815260206004820152600f60248201526e4e4f545f454c494749424c455f564760881b6044820152606401610245565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b60006108ce8284610d95565b9392505050565b60006108ce8284610dad565b60405163224cb2fd60e21b815260206004820152600860248201526722b632b1ba34b7b760c11b6044820152600090819061ce1090638932cbf4906064015b602060405180830381865afa15801561093d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109619190610dc4565b92915050565b61096f610b46565b6001600160a01b031663f83d08ba826040518263ffffffff1660e01b81526004016000604051808303818588803b1580156109a957600080fd5b505af11580156109bd573d6000803e3d6000fd5b505050505050565b6000806109d0610b8b565b90925090506001600160a01b0382161580156109f357506001600160a01b038116155b15610a345760405162461bcd60e51b81526020600482015260116024820152702727afa622a9a9a2a92fa3a922a0aa22a960791b6044820152606401610245565b610a3c6108e1565b600054604051632c06ba3d60e11b81526001600160a01b039182166004820152602481018690528482166044820152838216606482015291169063580d747a906084016020604051808303816000875af1158015610a9e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ac29190610d44565b610afc5760405162461bcd60e51b815260206004820152600b60248201526a1593d51157d1905253115160aa1b6044820152606401610245565b505050565b60405163224cb2fd60e21b815260206004820152600a60248201526956616c696461746f727360b01b6044820152600090819061ce1090638932cbf490606401610920565b60405163224cb2fd60e21b815260206004820152600a602482015269131bd8dad95911dbdb1960b21b6044820152600090819061ce1090638932cbf490606401610920565b6000806000610b986108e1565b6001600160a01b0316637046c96b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610bd5573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610bfd9190810190610eb7565b50905060008060005b8351811015610cc257838181518110610c2157610c21610f7c565b60209081029190910101516000546001600160a01b0390811691161415610cb0578015610c6f5783610c54600183610dad565b81518110610c6457610c64610f7c565b602002602001015191505b60018451610c7d9190610dad565b811015610cab5783610c90826001610d95565b81518110610ca057610ca0610f7c565b602002602001015192505b610cc2565b80610cba81610f92565b915050610c06565b509094909350915050565b6001600160a01b0381168114610ce257600080fd5b50565b600060208284031215610cf757600080fd5b81356108ce81610ccd565b60208082526022908201527f4f6e6c79206f776e65722063616e2063616c6c20746869732066756e6374696f6040820152616e2160f01b606082015260800190565b600060208284031215610d5657600080fd5b815180151581146108ce57600080fd5b600060208284031215610d7857600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b60008219821115610da857610da8610d7f565b500190565b600082821015610dbf57610dbf610d7f565b500390565b600060208284031215610dd657600080fd5b81516108ce81610ccd565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715610e2057610e20610de1565b604052919050565b600067ffffffffffffffff821115610e4257610e42610de1565b5060051b60200190565b600082601f830112610e5d57600080fd5b81516020610e72610e6d83610e28565b610df7565b82815260059290921b84018101918181019086841115610e9157600080fd5b8286015b84811015610eac5780518352918301918301610e95565b509695505050505050565b60008060408385031215610eca57600080fd5b825167ffffffffffffffff80821115610ee257600080fd5b818501915085601f830112610ef657600080fd5b81516020610f06610e6d83610e28565b82815260059290921b84018101918181019089841115610f2557600080fd5b948201945b83861015610f4c578551610f3d81610ccd565b82529482019490820190610f2a565b91880151919650909350505080821115610f6557600080fd5b50610f7285828601610e4c565b9150509250929050565b634e487b7160e01b600052603260045260246000fd5b6000600019821415610fa657610fa6610d7f565b506001019056fea2646970667358221220d65163872280a1d2367f72846fdece6e94157181552595b456b19c996085ae5f64736f6c634300080a0033