ETH Price: $2,551.77 (+0.71%)

Contract

0xae4773f542b8128549B153DFa799C1571f7c2F50
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
0x60806040148356532022-05-24 12:01:09828 days ago1653393669IN
 Create: StkBMIStaking
0 ETH0.0387820230

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
StkBMIStaking

Compiler Version
v0.7.4+commit.3f05b770

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 14 : StkBMIStaking.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.7.4;
pragma experimental ABIEncoderV2;

import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/math/Math.sol";

import "./interfaces/IContractsRegistry.sol";
import "./interfaces/IClaimVoting.sol";

import "./interfaces/IStkBMIStaking.sol";

import "./abstract/AbstractDependant.sol";

contract StkBMIStaking is IStkBMIStaking, OwnableUpgradeable, AbstractDependant {
    using SafeMath for uint256;
    using Math for uint256;

    IERC20 public stkBMIToken;
    IClaimVoting public claimVoting;
    address public reinsurancePoolAddress;

    mapping(address => uint256) internal _stakedStkBMI;
    uint256 internal _totalStakedStkBMI;

    address public bmiStakingAddress;

    bool public enableBMIStakingAccess;

    event UserSlashed(address user, uint256 amount);
    event Locked(address user, uint256 amount);
    event Unlocked(address user, uint256 amount);

    modifier onlyClaimVoting() {
        require(_msgSender() == address(claimVoting), "StkBMIStaking: Not a ClaimVoting contract");
        _;
    }

    function __StkBMIStaking_init() external initializer {
        __Ownable_init();

        enableBMIStakingAccess = true;
    }

    function setDependencies(IContractsRegistry _contractsRegistry)
        external
        override
        onlyInjectorOrZero
    {
        stkBMIToken = IERC20(_contractsRegistry.getSTKBMIContract());
        claimVoting = IClaimVoting(_contractsRegistry.getClaimVotingContract());
        reinsurancePoolAddress = _contractsRegistry.getReinsurancePoolContract();
        if (enableBMIStakingAccess) {
            bmiStakingAddress = _contractsRegistry.getBMIStakingContract();
        }
    }

    function setEnableBMIStakingAccess(bool _enableBMIStakingAccess) external onlyOwner {
        enableBMIStakingAccess = _enableBMIStakingAccess;
    }

    function stakedStkBMI(address user) external view override returns (uint256) {
        require(
            _msgSender() == user ||
                _msgSender() == address(claimVoting) ||
                (enableBMIStakingAccess && _msgSender() == bmiStakingAddress),
            "StkBMIStaking : not allowed"
        );
        return _stakedStkBMI[user];
    }

    function totalStakedStkBMI() external view override onlyClaimVoting returns (uint256) {
        return _totalStakedStkBMI;
    }

    /// @dev a temporary function for migration stkBMI from vBMI to this contract
    function lockStkBMIFor(address user, uint256 amount) external override {
        // vbmi
        require(_msgSender() == 0x9DD9e2B26F75d42437582FCB354d567556343dAe);

        _totalStakedStkBMI = _totalStakedStkBMI.add(amount);
        _stakedStkBMI[user] = _stakedStkBMI[user].add(amount);

        emit Locked(user, amount);
    }

    function lockStkBMI(uint256 amount) external override {
        require(amount > 0, "StkBMIStaking: can't lock 0 tokens");

        _totalStakedStkBMI = _totalStakedStkBMI.add(amount);
        _stakedStkBMI[msg.sender] = _stakedStkBMI[msg.sender].add(amount);
        stkBMIToken.transferFrom(msg.sender, address(this), amount);

        emit Locked(msg.sender, amount);
    }

    function unlockStkBMI(uint256 amount) external override {
        require(
            claimVoting.canUnstake(_msgSender()),
            "StkBMIStaking: Can't withdraw, there are pending votes"
        );
        require(_stakedStkBMI[_msgSender()] >= amount, "StkBMIStaking: No staked amount");

        _totalStakedStkBMI = _totalStakedStkBMI.sub(amount);
        _stakedStkBMI[_msgSender()] = _stakedStkBMI[_msgSender()].sub(amount);
        stkBMIToken.transfer(_msgSender(), amount);

        emit Unlocked(_msgSender(), amount);
    }

    function slashUserTokens(address user, uint256 amount) external override onlyClaimVoting {
        amount = Math.min(_stakedStkBMI[user], amount);
        _totalStakedStkBMI = _totalStakedStkBMI.sub(amount);
        _stakedStkBMI[user] = _stakedStkBMI[user].sub(amount);
        stkBMIToken.transfer(reinsurancePoolAddress, amount);

        emit UserSlashed(user, amount);
    }
}

File 2 of 14 : IStkBMIStaking.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.7.4;

interface IStkBMIStaking {
    function stakedStkBMI(address user) external view returns (uint256);

    function totalStakedStkBMI() external view returns (uint256);

    function lockStkBMIFor(address user, uint256 amount) external;

    function lockStkBMI(uint256 amount) external;

    function unlockStkBMI(uint256 amount) external;

    function slashUserTokens(address user, uint256 amount) external;
}

File 3 of 14 : IPolicyBookFabric.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.7.4;

interface IPolicyBookFabric {
    enum ContractType {CONTRACT, STABLECOIN, SERVICE, EXCHANGE, VARIOUS}

    /// @notice Create new Policy Book contract, access: ANY
    /// @param _contract is Contract to create policy book for
    /// @param _contractType is Contract to create policy book for
    /// @param _description is bmiXCover token desription for this policy book
    /// @param _projectSymbol replaces x in bmiXCover token symbol
    /// @param _initialDeposit is an amount user deposits on creation (addLiquidity())
    /// @return _policyBook is address of created contract
    function create(
        address _contract,
        ContractType _contractType,
        string calldata _description,
        string calldata _projectSymbol,
        uint256 _initialDeposit,
        address _shieldMiningToken
    ) external returns (address);

    function createLeveragePools(
        address _insuranceContract,
        ContractType _contractType,
        string calldata _description,
        string calldata _projectSymbol
    ) external returns (address);
}

File 4 of 14 : IContractsRegistry.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.7.4;
pragma experimental ABIEncoderV2;

interface IContractsRegistry {
    function getAMMRouterContract() external view returns (address);

    function getAMMBMIToETHPairContract() external view returns (address);

    function getAMMBMIToUSDTPairContract() external view returns (address);

    function getSushiSwapMasterChefV2Contract() external view returns (address);

    function getWrappedTokenContract() external view returns (address);

    function getUSDTContract() external view returns (address);

    function getBMIContract() external view returns (address);

    function getPriceFeedContract() external view returns (address);

    function getPolicyBookRegistryContract() external view returns (address);

    function getPolicyBookFabricContract() external view returns (address);

    function getBMICoverStakingContract() external view returns (address);

    function getBMICoverStakingViewContract() external view returns (address);

    function getBMITreasury() external view returns (address);

    function getRewardsGeneratorContract() external view returns (address);

    function getBMIUtilityNFTContract() external view returns (address);

    function getNFTStakingContract() external view returns (address);

    function getLiquidityBridgeContract() external view returns (address);

    function getClaimingRegistryContract() external view returns (address);

    function getPolicyRegistryContract() external view returns (address);

    function getLiquidityRegistryContract() external view returns (address);

    function getClaimVotingContract() external view returns (address);

    function getReinsurancePoolContract() external view returns (address);

    function getLeveragePortfolioViewContract() external view returns (address);

    function getCapitalPoolContract() external view returns (address);

    function getPolicyBookAdminContract() external view returns (address);

    function getPolicyQuoteContract() external view returns (address);

    function getBMIStakingContract() external view returns (address);

    function getSTKBMIContract() external view returns (address);

    function getStkBMIStakingContract() external view returns (address);

    function getVBMIContract() external view returns (address);

    function getLiquidityMiningStakingETHContract() external view returns (address);

    function getLiquidityMiningStakingUSDTContract() external view returns (address);

    function getReputationSystemContract() external view returns (address);

    function getDefiProtocol1Contract() external view returns (address);

    function getAaveLendPoolAddressProvdierContract() external view returns (address);

    function getAaveATokenContract() external view returns (address);

    function getDefiProtocol2Contract() external view returns (address);

    function getCompoundCTokenContract() external view returns (address);

    function getCompoundComptrollerContract() external view returns (address);

    function getDefiProtocol3Contract() external view returns (address);

    function getYearnVaultContract() external view returns (address);

    function getYieldGeneratorContract() external view returns (address);

    function getShieldMiningContract() external view returns (address);
}

File 5 of 14 : IClaimingRegistry.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.7.4;
pragma experimental ABIEncoderV2;

import "./IPolicyBookFabric.sol";

interface IClaimingRegistry {
    enum ClaimStatus {
        CAN_CLAIM,
        UNCLAIMABLE,
        PENDING,
        AWAITING_CALCULATION,
        REJECTED_CAN_APPEAL,
        REJECTED,
        ACCEPTED,
        EXPIRED
    }

    struct ClaimInfo {
        address claimer;
        address policyBookAddress;
        string evidenceURI;
        uint256 dateSubmitted;
        uint256 dateEnded;
        bool appeal;
        ClaimStatus status;
        uint256 claimAmount;
        uint256 claimRefund;
    }

    struct ClaimWithdrawalInfo {
        uint256 readyToWithdrawDate;
        bool committed;
    }

    struct RewardWithdrawalInfo {
        uint256 rewardAmount;
        uint256 readyToWithdrawDate;
    }

    enum WithdrawalStatus {NONE, PENDING, READY, EXPIRED}

    function claimWithdrawalInfo(uint256 index)
        external
        view
        returns (uint256 readyToWithdrawDate, bool committed);

    function rewardWithdrawalInfo(address voter)
        external
        view
        returns (uint256 rewardAmount, uint256 readyToWithdrawDate);

    /// @notice returns anonymous voting duration
    function anonymousVotingDuration(uint256 index) external view returns (uint256);

    /// @notice returns the whole voting duration
    function votingDuration(uint256 index) external view returns (uint256);

    /// @notice returns the whole voting duration + view verdict duration
    function validityDuration(uint256 index) external view returns (uint256);

    /// @notice returns how many time should pass before anyone could calculate a claim result
    function anyoneCanCalculateClaimResultAfter(uint256 index) external view returns (uint256);

    /// @notice check if a user can buy new policy of specified PolicyBook and end the active one if there is
    function canBuyNewPolicy(address buyer, address policyBookAddress) external;

    /// @notice returns withdrawal status of requested claim
    function getClaimWithdrawalStatus(uint256 index) external view returns (WithdrawalStatus);

    /// @notice returns withdrawal status of requested reward
    function getRewardWithdrawalStatus(address voter) external view returns (WithdrawalStatus);

    /// @notice returns true if there is ongoing claiming procedure
    function hasProcedureOngoing(address poolAddress) external view returns (bool);

    /// @notice submits new PolicyBook claim for the user
    function submitClaim(
        address user,
        address policyBookAddress,
        string calldata evidenceURI,
        uint256 cover,
        bool appeal
    ) external returns (uint256);

    /// @notice returns true if the claim with this index exists
    function claimExists(uint256 index) external view returns (bool);

    /// @notice returns claim submition time
    function claimSubmittedTime(uint256 index) external view returns (uint256);

    /// @notice returns claim end time or zero in case it is pending
    function claimEndTime(uint256 index) external view returns (uint256);

    /// @notice returns true if the claim is anonymously votable
    function isClaimAnonymouslyVotable(uint256 index) external view returns (bool);

    /// @notice returns true if the claim is exposably votable
    function isClaimExposablyVotable(uint256 index) external view returns (bool);

    /// @notice returns true if claim is anonymously votable or exposably votable
    function isClaimVotable(uint256 index) external view returns (bool);

    /// @notice returns true if a claim can be calculated by anyone
    function canClaimBeCalculatedByAnyone(uint256 index) external view returns (bool);

    /// @notice returns true if this claim is pending or awaiting
    function isClaimPending(uint256 index) external view returns (bool);

    /// @notice returns how many claims the holder has
    function countPolicyClaimerClaims(address user) external view returns (uint256);

    /// @notice returns how many pending claims are there
    function countPendingClaims() external view returns (uint256);

    /// @notice returns how many claims are there
    function countClaims() external view returns (uint256);

    /// @notice returns a claim index of it's claimer and an ordinal number
    function claimOfOwnerIndexAt(address claimer, uint256 orderIndex)
        external
        view
        returns (uint256);

    /// @notice returns pending claim index by its ordinal index
    function pendingClaimIndexAt(uint256 orderIndex) external view returns (uint256);

    /// @notice returns claim index by its ordinal index
    function claimIndexAt(uint256 orderIndex) external view returns (uint256);

    /// @notice returns current active claim index by policybook and claimer
    function claimIndex(address claimer, address policyBookAddress)
        external
        view
        returns (uint256);

    /// @notice returns true if the claim is appealed
    function isClaimAppeal(uint256 index) external view returns (bool);

    /// @notice returns current status of a claim
    function policyStatus(address claimer, address policyBookAddress)
        external
        view
        returns (ClaimStatus);

    /// @notice returns current status of a claim
    function claimStatus(uint256 index) external view returns (ClaimStatus);

    /// @notice returns the claim owner (claimer)
    function claimOwner(uint256 index) external view returns (address);

    /// @notice returns the claim PolicyBook
    function claimPolicyBook(uint256 index) external view returns (address);

    /// @notice returns claim info by its index
    function claimInfo(uint256 index) external view returns (ClaimInfo memory _claimInfo);

    function getAllPendingClaimsAmount() external view returns (uint256 _totalClaimsAmount);

    function getAllPendingRewardsAmount() external view returns (uint256 _totalRewardsAmount);

    function getClaimableAmounts(uint256[] memory _claimIndexes) external view returns (uint256);

    /// @notice marks the user's claim as Accepted
    function acceptClaim(uint256 index, uint256 amount) external;

    /// @notice marks the user's claim as Rejected
    function rejectClaim(uint256 index) external;

    /// @notice marks the user's claim as Expired
    function expireClaim(uint256 index) external;

    /// @notice Update Image Uri in case it contains material that is ilegal
    ///         or offensive.
    /// @dev Only the owner of the PolicyBookAdmin can erase/update evidenceUri.
    /// @param claim_Index Claim Index that is going to be updated
    /// @param _newEvidenceURI New evidence uri. It can be blank.
    function updateImageUriOfClaim(uint256 claim_Index, string calldata _newEvidenceURI) external;

    function requestClaimWithdrawal(uint256 index) external;

    function requestRewardWithdrawal(address voter, uint256 rewardAmount) external;
}

File 6 of 14 : IClaimVoting.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.7.4;
pragma experimental ABIEncoderV2;

import "@openzeppelin/contracts/utils/EnumerableSet.sol";

import "./IClaimingRegistry.sol";

interface IClaimVoting {
    enum VoteStatus {
        ANONYMOUS_PENDING,
        AWAITING_EXPOSURE,
        EXPIRED,
        EXPOSED_PENDING,
        MINORITY,
        MAJORITY,
        RECEIVED
    }

    struct VotingResult {
        uint256 withdrawalAmount;
        uint256 lockedBMIAmount;
        uint256 reinsuranceTokensAmount;
        uint256 votedAverageWithdrawalAmount;
        uint256 votedYesStakedStkBMIAmountWithReputation;
        uint256 votedNoStakedStkBMIAmountWithReputation;
        uint256 allVotedStakedStkBMIAmount;
        uint256 votedYesPercentage;
        EnumerableSet.UintSet voteIndexes;
    }

    struct VotingInst {
        uint256 claimIndex;
        bytes32 finalHash;
        string encryptedVote;
        address voter;
        uint256 voterReputation;
        uint256 suggestedAmount;
        uint256 stakedStkBMIAmount;
        bool accept;
        VoteStatus status;
    }

    struct MyClaimInfo {
        uint256 index;
        address policyBookAddress;
        string evidenceURI;
        bool appeal;
        uint256 claimAmount;
        IClaimingRegistry.ClaimStatus finalVerdict;
        uint256 finalClaimAmount;
        uint256 bmiCalculationReward;
    }

    struct PublicClaimInfo {
        uint256 claimIndex;
        address claimer;
        address policyBookAddress;
        string evidenceURI;
        bool appeal;
        uint256 claimAmount;
        uint256 time;
    }

    struct AllClaimInfo {
        PublicClaimInfo publicClaimInfo;
        IClaimingRegistry.ClaimStatus finalVerdict;
        uint256 finalClaimAmount;
        uint256 bmiCalculationReward;
    }

    struct MyVoteInfo {
        AllClaimInfo allClaimInfo;
        string encryptedVote;
        uint256 suggestedAmount;
        VoteStatus status;
        uint256 time;
    }

    struct VotesUpdatesInfo {
        uint256 bmiReward;
        uint256 stblReward;
        int256 reputationChange;
        int256 stakeChange;
    }

    function voteResults(uint256 voteIndex)
        external
        view
        returns (
            uint256 bmiReward,
            uint256 stblReward,
            int256 reputationChange,
            int256 stakeChange
        );

    /// @notice starts the voting process
    function initializeVoting(
        address claimer,
        string calldata evidenceURI,
        uint256 coverTokens,
        bool appeal
    ) external;

    /// @notice returns true if the user has no PENDING votes
    function canUnstake(address user) external view returns (bool);

    /// @notice returns true if the user has no awaiting reception votes
    function canVote(address user) external view returns (bool);

    /// @notice returns number of vote on a claim
    function countVoteOnClaim(uint256 claimIndex) external view returns (uint256);

    /// @notice returns amount of bmi locked for FE
    function lockedBMIAmount(uint256 claimIndex) external view returns (uint256);

    /// @notice returns how many votes the user has
    function countVotes(address user) external view returns (uint256);

    function voteIndexByClaimIndexAt(uint256 claimIndex, uint256 orderIndex)
        external
        view
        returns (uint256);

    /// @notice returns status of the vote
    function voteStatus(uint256 index) external view returns (VoteStatus);

    /// @notice returns a list of claims that are votable for msg.sender
    function whatCanIVoteFor(uint256 offset, uint256 limit)
        external
        returns (uint256 _claimsCount, PublicClaimInfo[] memory _votablesInfo);

    /// @notice returns info list of ALL claims
    function allClaims(uint256 offset, uint256 limit)
        external
        view
        returns (AllClaimInfo[] memory _allClaimsInfo);

    /// @notice returns info list of claims of msg.sender
    function myClaims(uint256 offset, uint256 limit)
        external
        view
        returns (MyClaimInfo[] memory _myClaimsInfo);

    /// @notice returns info list of claims that are voted by msg.sender
    function myVotes(uint256 offset, uint256 limit)
        external
        view
        returns (MyVoteInfo[] memory _myVotesInfo);

    function myNotReceivesVotes(address user)
        external
        view
        returns (uint256[] memory claimIndexes, VotesUpdatesInfo[] memory voteRewardInfo);

    /// @notice anonymously votes (result used later in exposeVote())
    /// @notice the claims have to be PENDING, the voter can vote only once for a specific claim
    /// @param claimIndexes are the indexes of the claims the voter is voting on
    ///     (each one is unique for each claim and appeal)
    /// @param finalHashes are the hashes produced by the encryption algorithm.
    ///     They will be verified onchain in expose function
    /// @param encryptedVotes are the AES encrypted values that represent the actual vote
    function anonymouslyVoteBatch(
        uint256[] calldata claimIndexes,
        bytes32[] calldata finalHashes,
        string[] calldata encryptedVotes
    ) external;

    /// @notice exposes votes of anonymous votings
    /// @notice the vote has to be voted anonymously prior
    /// @param claimIndexes are the indexes of the claims to expose votes for
    /// @param suggestedClaimAmounts are the actual vote values.
    ///     They must match the decrypted values in anonymouslyVoteBatch function
    /// @param hashedSignaturesOfClaims are the validation data needed to construct proper finalHashes
    function exposeVoteBatch(
        uint256[] calldata claimIndexes,
        uint256[] calldata suggestedClaimAmounts,
        bytes32[] calldata hashedSignaturesOfClaims
    ) external;

    /// @notice calculates results of votes on a claim
    function calculateResult(uint256 claimIndex) external;

    /// @notice distribute rewards and slash penalties
    function receiveResult() external;

    function transferLockedBMI(uint256 claimIndex, address claimer) external;
}

File 7 of 14 : AbstractDependant.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.7.4;

import "../interfaces/IContractsRegistry.sol";

abstract contract AbstractDependant {
    /// @dev keccak256(AbstractDependant.setInjector(address)) - 1
    bytes32 private constant _INJECTOR_SLOT =
        0xd6b8f2e074594ceb05d47c27386969754b6ad0c15e5eb8f691399cd0be980e76;

    modifier onlyInjectorOrZero() {
        address _injector = injector();

        require(_injector == address(0) || _injector == msg.sender, "Dependant: Not an injector");
        _;
    }

    function setInjector(address _injector) external onlyInjectorOrZero {
        bytes32 slot = _INJECTOR_SLOT;

        assembly {
            sstore(slot, _injector)
        }
    }

    /// @dev has to apply onlyInjectorOrZero() modifier
    function setDependencies(IContractsRegistry) external virtual;

    function injector() public view returns (address _injector) {
        bytes32 slot = _INJECTOR_SLOT;

        assembly {
            _injector := sload(slot)
        }
    }
}

File 8 of 14 : EnumerableSet.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.0;

/**
 * @dev Library for managing
 * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
 * types.
 *
 * Sets have the following properties:
 *
 * - Elements are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Elements are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```
 * contract Example {
 *     // Add the library methods
 *     using EnumerableSet for EnumerableSet.AddressSet;
 *
 *     // Declare a set state variable
 *     EnumerableSet.AddressSet private mySet;
 * }
 * ```
 *
 * As of v3.0.0, only sets of type `address` (`AddressSet`) and `uint256`
 * (`UintSet`) are supported.
 */
library EnumerableSet {
    // To implement this library for multiple types with as little code
    // repetition as possible, we write it in terms of a generic Set type with
    // bytes32 values.
    // The Set implementation uses private functions, and user-facing
    // implementations (such as AddressSet) are just wrappers around the
    // underlying Set.
    // This means that we can only create new EnumerableSets for types that fit
    // in bytes32.

    struct Set {
        // Storage of set values
        bytes32[] _values;

        // Position of the value in the `values` array, plus 1 because index 0
        // means a value is not in the set.
        mapping (bytes32 => uint256) _indexes;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function _add(Set storage set, bytes32 value) private returns (bool) {
        if (!_contains(set, value)) {
            set._values.push(value);
            // The value is stored at length-1, but we add 1 to all indexes
            // and use 0 as a sentinel value
            set._indexes[value] = set._values.length;
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function _remove(Set storage set, bytes32 value) private returns (bool) {
        // We read and store the value's index to prevent multiple reads from the same storage slot
        uint256 valueIndex = set._indexes[value];

        if (valueIndex != 0) { // Equivalent to contains(set, value)
            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
            // the array, and then remove the last element (sometimes called as 'swap and pop').
            // This modifies the order of the array, as noted in {at}.

            uint256 toDeleteIndex = valueIndex - 1;
            uint256 lastIndex = set._values.length - 1;

            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs
            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.

            bytes32 lastvalue = set._values[lastIndex];

            // Move the last value to the index where the value to delete is
            set._values[toDeleteIndex] = lastvalue;
            // Update the index for the moved value
            set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based

            // Delete the slot where the moved value was stored
            set._values.pop();

            // Delete the index for the deleted slot
            delete set._indexes[value];

            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function _contains(Set storage set, bytes32 value) private view returns (bool) {
        return set._indexes[value] != 0;
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function _length(Set storage set) private view returns (uint256) {
        return set._values.length;
    }

   /**
    * @dev Returns the value stored at position `index` in the set. O(1).
    *
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function _at(Set storage set, uint256 index) private view returns (bytes32) {
        require(set._values.length > index, "EnumerableSet: index out of bounds");
        return set._values[index];
    }

    // AddressSet

    struct AddressSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(AddressSet storage set, address value) internal returns (bool) {
        return _add(set._inner, bytes32(uint256(value)));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(AddressSet storage set, address value) internal returns (bool) {
        return _remove(set._inner, bytes32(uint256(value)));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(AddressSet storage set, address value) internal view returns (bool) {
        return _contains(set._inner, bytes32(uint256(value)));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(AddressSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

   /**
    * @dev Returns the value stored at position `index` in the set. O(1).
    *
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function at(AddressSet storage set, uint256 index) internal view returns (address) {
        return address(uint256(_at(set._inner, index)));
    }


    // UintSet

    struct UintSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(UintSet storage set, uint256 value) internal returns (bool) {
        return _add(set._inner, bytes32(value));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(UintSet storage set, uint256 value) internal returns (bool) {
        return _remove(set._inner, bytes32(value));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(UintSet storage set, uint256 value) internal view returns (bool) {
        return _contains(set._inner, bytes32(value));
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function length(UintSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

   /**
    * @dev Returns the value stored at position `index` in the set. O(1).
    *
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function at(UintSet storage set, uint256 index) internal view returns (uint256) {
        return uint256(_at(set._inner, index));
    }
}

File 9 of 14 : IERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

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

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

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

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

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

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

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

File 10 of 14 : SafeMath.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.0;

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @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) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    /**
     * @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 sub(a, b, "SafeMath: subtraction overflow");
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;

        return c;
    }

    /**
     * @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) {
        // 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 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts 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) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts 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) {
        require(b > 0, errorMessage);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts 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 mod(a, b, "SafeMath: modulo by zero");
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts with custom message 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, string memory errorMessage) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }
}

File 11 of 14 : Math.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.0;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a >= b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow, so we distribute
        return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2);
    }
}

File 12 of 14 : Initializable.sol
// SPDX-License-Identifier: MIT

// solhint-disable-next-line compiler-version
pragma solidity >=0.4.24 <0.8.0;


/**
 * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
 * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an
 * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
 * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
 * 
 * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
 * possible by providing the encoded function call as the `_data` argument to {UpgradeableProxy-constructor}.
 * 
 * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
 * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
 */
abstract contract Initializable {

    /**
     * @dev Indicates that the contract has been initialized.
     */
    bool private _initialized;

    /**
     * @dev Indicates that the contract is in the process of being initialized.
     */
    bool private _initializing;

    /**
     * @dev Modifier to protect an initializer function from being invoked twice.
     */
    modifier initializer() {
        require(_initializing || _isConstructor() || !_initialized, "Initializable: contract is already initialized");

        bool isTopLevelCall = !_initializing;
        if (isTopLevelCall) {
            _initializing = true;
            _initialized = true;
        }

        _;

        if (isTopLevelCall) {
            _initializing = false;
        }
    }

    /// @dev Returns true if and only if the function is running in the constructor
    function _isConstructor() private view returns (bool) {
        // extcodesize checks the size of the code stored in an address, and
        // address returns the current address. Since the code is still not
        // deployed when running a constructor, any checks on its code size will
        // yield zero, making it an effective way to detect if a contract is
        // under construction or not.
        address self = address(this);
        uint256 cs;
        // solhint-disable-next-line no-inline-assembly
        assembly { cs := extcodesize(self) }
        return cs == 0;
    }
}

File 13 of 14 : OwnableUpgradeable.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "../GSN/ContextUpgradeable.sol";
import "../proxy/Initializable.sol";
/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    function __Ownable_init() internal initializer {
        __Context_init_unchained();
        __Ownable_init_unchained();
    }

    function __Ownable_init_unchained() internal initializer {
        address msgSender = _msgSender();
        _owner = msgSender;
        emit OwnershipTransferred(address(0), msgSender);
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(_owner == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        emit OwnershipTransferred(_owner, address(0));
        _owner = address(0);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        emit OwnershipTransferred(_owner, newOwner);
        _owner = newOwner;
    }
    uint256[49] private __gap;
}

File 14 of 14 : ContextUpgradeable.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;
import "../proxy/Initializable.sol";

/*
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with GSN meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract ContextUpgradeable is Initializable {
    function __Context_init() internal initializer {
        __Context_init_unchained();
    }

    function __Context_init_unchained() internal initializer {
    }
    function _msgSender() internal view virtual returns (address payable) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes memory) {
        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
        return msg.data;
    }
    uint256[50] private __gap;
}

Settings
{
  "remappings": [],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "evmVersion": "istanbul",
  "libraries": {},
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  }
}

Contract Security Audit

Contract ABI

[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Locked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Unlocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"UserSlashed","type":"event"},{"inputs":[],"name":"__StkBMIStaking_init","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"bmiStakingAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimVoting","outputs":[{"internalType":"contract IClaimVoting","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"enableBMIStakingAccess","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"injector","outputs":[{"internalType":"address","name":"_injector","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"lockStkBMI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"lockStkBMIFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"reinsurancePoolAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IContractsRegistry","name":"_contractsRegistry","type":"address"}],"name":"setDependencies","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_enableBMIStakingAccess","type":"bool"}],"name":"setEnableBMIStakingAccess","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_injector","type":"address"}],"name":"setInjector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"slashUserTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"stakedStkBMI","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stkBMIToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalStakedStkBMI","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"unlockStkBMI","outputs":[],"stateMutability":"nonpayable","type":"function"}]

608060405234801561001057600080fd5b5061166c806100206000396000f3fe608060405234801561001057600080fd5b50600436106101215760003560e01c8063a803a315116100ad578063df1e0a0211610071578063df1e0a02146101ff578063e3ea38c914610212578063edaf2c6a14610225578063f01d174f1461022d578063f2fde38b1461024057610121565b8063a803a315146101b6578063a8baf9df146101c9578063b014bb9f146101d1578063b84161a0146101d9578063bb3cf6e6146101ec57610121565b806376d7f6ba116100f457806376d7f6ba1461016b5780638389cb18146101805780638cb941cc146101935780638da5cb5b146101a65780639fb3fd79146101ae57610121565b806337b06dbc146101265780634617161014610144578063715018a61461014c578063730edf8e14610156575b600080fd5b61012e610253565b60405161013b919061140b565b60405180910390f35b61012e610262565b610154610287565b005b61015e61033b565b60405161013b91906115b6565b610173610388565b60405161013b919061145c565b61015461018e366004611358565b610398565b6101546101a1366004611358565b61067a565b61012e61071a565b610154610729565b6101546101c43660046113f3565b6107e6565b61012e610a03565b61012e610a12565b61015e6101e7366004611358565b610a21565b6101546101fa366004611390565b610ad5565b61015461020d3660046113f3565b610b9b565b610154610220366004611390565b610caf565b61012e610e12565b61015461023b3660046113bb565b610e21565b61015461024e366004611358565b610ea9565b6065546001600160a01b031681565b7fd6b8f2e074594ceb05d47c27386969754b6ad0c15e5eb8f691399cd0be980e765490565b61028f610fb4565b6033546001600160a01b039081169116146102f1576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6033546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603380546001600160a01b0319169055565b6066546000906001600160a01b0316610352610fb4565b6001600160a01b0316146103815760405162461bcd60e51b815260040161037890611467565b60405180910390fd5b5060695490565b606a54600160a01b900460ff1681565b60006103a2610262565b90506001600160a01b03811615806103c257506001600160a01b03811633145b610413576040805162461bcd60e51b815260206004820152601a60248201527f446570656e64616e743a204e6f7420616e20696e6a6563746f72000000000000604482015290519081900360640190fd5b816001600160a01b03166353c6d6f16040518163ffffffff1660e01b815260040160206040518083038186803b15801561044c57600080fd5b505afa158015610460573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104849190611374565b606560006101000a8154816001600160a01b0302191690836001600160a01b03160217905550816001600160a01b031663ae0a0f866040518163ffffffff1660e01b815260040160206040518083038186803b1580156104e357600080fd5b505afa1580156104f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061051b9190611374565b606660006101000a8154816001600160a01b0302191690836001600160a01b03160217905550816001600160a01b03166334dd10546040518163ffffffff1660e01b815260040160206040518083038186803b15801561057a57600080fd5b505afa15801561058e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105b29190611374565b606780546001600160a01b0319166001600160a01b0392909216919091179055606a54600160a01b900460ff161561067657816001600160a01b0316632463efd66040518163ffffffff1660e01b815260040160206040518083038186803b15801561061d57600080fd5b505afa158015610631573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106559190611374565b606a80546001600160a01b0319166001600160a01b03929092169190911790555b5050565b6000610684610262565b90506001600160a01b03811615806106a457506001600160a01b03811633145b6106f5576040805162461bcd60e51b815260206004820152601a60248201527f446570656e64616e743a204e6f7420616e20696e6a6563746f72000000000000604482015290519081900360640190fd5b507fd6b8f2e074594ceb05d47c27386969754b6ad0c15e5eb8f691399cd0be980e7655565b6033546001600160a01b031690565b600054610100900460ff16806107425750610742610fb8565b80610750575060005460ff16155b61078b5760405162461bcd60e51b815260040180806020018281038252602e815260200180611609602e913960400191505060405180910390fd5b600054610100900460ff161580156107b6576000805460ff1961ff0019909116610100171660011790555b6107be610fbe565b606a805460ff60a01b1916600160a01b17905580156107e3576000805461ff00191690555b50565b6066546001600160a01b03166385f4498b6107ff610fb4565b6040518263ffffffff1660e01b815260040161081b919061140b565b60206040518083038186803b15801561083357600080fd5b505afa158015610847573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061086b91906113d7565b6108875760405162461bcd60e51b8152600401610378906114f2565b8060686000610894610fb4565b6001600160a01b03166001600160a01b031681526020019081526020016000205410156108d35760405162461bcd60e51b81526004016103789061157f565b6069546108e0908261106f565b60695561091381606860006108f3610fb4565b6001600160a01b031681526020810191909152604001600020549061106f565b6068600061091f610fb4565b6001600160a01b0390811682526020820192909252604001600020919091556065541663a9059cbb61094f610fb4565b836040518363ffffffff1660e01b815260040161096d929190611443565b602060405180830381600087803b15801561098757600080fd5b505af115801561099b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109bf91906113d7565b507f0f0bc5b519ddefdd8e5f9e6423433aa2b869738de2ae34d58ebc796fc749fa0d6109e9610fb4565b826040516109f8929190611443565b60405180910390a150565b606a546001600160a01b031681565b6066546001600160a01b031681565b6000816001600160a01b0316610a35610fb4565b6001600160a01b03161480610a6457506066546001600160a01b0316610a59610fb4565b6001600160a01b0316145b80610a9d5750606a54600160a01b900460ff168015610a9d5750606a546001600160a01b0316610a92610fb4565b6001600160a01b0316145b610ab95760405162461bcd60e51b815260040161037890611548565b506001600160a01b031660009081526068602052604090205490565b610add610fb4565b6001600160a01b0316739dd9e2b26f75d42437582fcb354d567556343dae6001600160a01b031614610b0e57600080fd5b606954610b1b90826110b8565b6069556001600160a01b038216600090815260686020526040902054610b4190826110b8565b6001600160a01b0383166000908152606860205260409081902091909155517f9f1ec8c880f76798e7b793325d625e9b60e4082a553c98f42b6cda368dd6000890610b8f9084908490611443565b60405180910390a15050565b60008111610bbb5760405162461bcd60e51b8152600401610378906114b0565b606954610bc890826110b8565b60695533600090815260686020526040902054610be590826110b8565b33600081815260686020526040908190209290925560655491516323b872dd60e01b81526001600160a01b03909216916323b872dd91610c2b913090869060040161141f565b602060405180830381600087803b158015610c4557600080fd5b505af1158015610c59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c7d91906113d7565b507f9f1ec8c880f76798e7b793325d625e9b60e4082a553c98f42b6cda368dd6000833826040516109f8929190611443565b6066546001600160a01b0316610cc3610fb4565b6001600160a01b031614610ce95760405162461bcd60e51b815260040161037890611467565b6001600160a01b038216600090815260686020526040902054610d0c9082611112565b606954909150610d1c908261106f565b6069556001600160a01b038216600090815260686020526040902054610d42908261106f565b6001600160a01b038084166000908152606860205260409081902092909255606554606754925163a9059cbb60e01b81529082169263a9059cbb92610d8e929116908590600401611443565b602060405180830381600087803b158015610da857600080fd5b505af1158015610dbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610de091906113d7565b507f9ff4ae348b6f91c222997eceeebbeefe70027c0d92a032e1c9d5e4542536fcbf8282604051610b8f929190611443565b6067546001600160a01b031681565b610e29610fb4565b6033546001600160a01b03908116911614610e8b576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b606a8054911515600160a01b0260ff60a01b19909216919091179055565b610eb1610fb4565b6033546001600160a01b03908116911614610f13576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b038116610f585760405162461bcd60e51b81526004018080602001828103825260268152602001806115e36026913960400191505060405180910390fd5b6033546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603380546001600160a01b0319166001600160a01b0392909216919091179055565b3390565b303b1590565b600054610100900460ff1680610fd75750610fd7610fb8565b80610fe5575060005460ff16155b6110205760405162461bcd60e51b815260040180806020018281038252602e815260200180611609602e913960400191505060405180910390fd5b600054610100900460ff1615801561104b576000805460ff1961ff0019909116610100171660011790555b611053611128565b61105b6111c8565b80156107e3576000805461ff001916905550565b60006110b183836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506112c1565b9392505050565b6000828201838110156110b1576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600081831061112157816110b1565b5090919050565b600054610100900460ff16806111415750611141610fb8565b8061114f575060005460ff16155b61118a5760405162461bcd60e51b815260040180806020018281038252602e815260200180611609602e913960400191505060405180910390fd5b600054610100900460ff1615801561105b576000805460ff1961ff00199091166101001716600117905580156107e3576000805461ff001916905550565b600054610100900460ff16806111e157506111e1610fb8565b806111ef575060005460ff16155b61122a5760405162461bcd60e51b815260040180806020018281038252602e815260200180611609602e913960400191505060405180910390fd5b600054610100900460ff16158015611255576000805460ff1961ff0019909116610100171660011790555b600061125f610fb4565b603380546001600160a01b0319166001600160a01b038316908117909155604051919250906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a35080156107e3576000805461ff001916905550565b600081848411156113505760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156113155781810151838201526020016112fd565b50505050905090810190601f1680156113425780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600060208284031215611369578081fd5b81356110b1816115bf565b600060208284031215611385578081fd5b81516110b1816115bf565b600080604083850312156113a2578081fd5b82356113ad816115bf565b946020939093013593505050565b6000602082840312156113cc578081fd5b81356110b1816115d4565b6000602082840312156113e8578081fd5b81516110b1816115d4565b600060208284031215611404578081fd5b5035919050565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b60208082526029908201527f53746b424d495374616b696e673a204e6f74206120436c61696d566f74696e676040820152680818dbdb9d1c9858dd60ba1b606082015260800190565b60208082526022908201527f53746b424d495374616b696e673a2063616e2774206c6f636b203020746f6b656040820152616e7360f01b606082015260800190565b60208082526036908201527f53746b424d495374616b696e673a2043616e27742077697468647261772c207460408201527568657265206172652070656e64696e6720766f74657360501b606082015260800190565b6020808252601b908201527f53746b424d495374616b696e67203a206e6f7420616c6c6f7765640000000000604082015260600190565b6020808252601f908201527f53746b424d495374616b696e673a204e6f207374616b656420616d6f756e7400604082015260600190565b90815260200190565b6001600160a01b03811681146107e357600080fd5b80151581146107e357600080fdfe4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564a2646970667358221220c33948cc386337c1d7d95233ef6dff976a546908d49207c460214493b174ccb564736f6c63430007040033

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101215760003560e01c8063a803a315116100ad578063df1e0a0211610071578063df1e0a02146101ff578063e3ea38c914610212578063edaf2c6a14610225578063f01d174f1461022d578063f2fde38b1461024057610121565b8063a803a315146101b6578063a8baf9df146101c9578063b014bb9f146101d1578063b84161a0146101d9578063bb3cf6e6146101ec57610121565b806376d7f6ba116100f457806376d7f6ba1461016b5780638389cb18146101805780638cb941cc146101935780638da5cb5b146101a65780639fb3fd79146101ae57610121565b806337b06dbc146101265780634617161014610144578063715018a61461014c578063730edf8e14610156575b600080fd5b61012e610253565b60405161013b919061140b565b60405180910390f35b61012e610262565b610154610287565b005b61015e61033b565b60405161013b91906115b6565b610173610388565b60405161013b919061145c565b61015461018e366004611358565b610398565b6101546101a1366004611358565b61067a565b61012e61071a565b610154610729565b6101546101c43660046113f3565b6107e6565b61012e610a03565b61012e610a12565b61015e6101e7366004611358565b610a21565b6101546101fa366004611390565b610ad5565b61015461020d3660046113f3565b610b9b565b610154610220366004611390565b610caf565b61012e610e12565b61015461023b3660046113bb565b610e21565b61015461024e366004611358565b610ea9565b6065546001600160a01b031681565b7fd6b8f2e074594ceb05d47c27386969754b6ad0c15e5eb8f691399cd0be980e765490565b61028f610fb4565b6033546001600160a01b039081169116146102f1576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6033546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603380546001600160a01b0319169055565b6066546000906001600160a01b0316610352610fb4565b6001600160a01b0316146103815760405162461bcd60e51b815260040161037890611467565b60405180910390fd5b5060695490565b606a54600160a01b900460ff1681565b60006103a2610262565b90506001600160a01b03811615806103c257506001600160a01b03811633145b610413576040805162461bcd60e51b815260206004820152601a60248201527f446570656e64616e743a204e6f7420616e20696e6a6563746f72000000000000604482015290519081900360640190fd5b816001600160a01b03166353c6d6f16040518163ffffffff1660e01b815260040160206040518083038186803b15801561044c57600080fd5b505afa158015610460573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104849190611374565b606560006101000a8154816001600160a01b0302191690836001600160a01b03160217905550816001600160a01b031663ae0a0f866040518163ffffffff1660e01b815260040160206040518083038186803b1580156104e357600080fd5b505afa1580156104f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061051b9190611374565b606660006101000a8154816001600160a01b0302191690836001600160a01b03160217905550816001600160a01b03166334dd10546040518163ffffffff1660e01b815260040160206040518083038186803b15801561057a57600080fd5b505afa15801561058e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105b29190611374565b606780546001600160a01b0319166001600160a01b0392909216919091179055606a54600160a01b900460ff161561067657816001600160a01b0316632463efd66040518163ffffffff1660e01b815260040160206040518083038186803b15801561061d57600080fd5b505afa158015610631573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106559190611374565b606a80546001600160a01b0319166001600160a01b03929092169190911790555b5050565b6000610684610262565b90506001600160a01b03811615806106a457506001600160a01b03811633145b6106f5576040805162461bcd60e51b815260206004820152601a60248201527f446570656e64616e743a204e6f7420616e20696e6a6563746f72000000000000604482015290519081900360640190fd5b507fd6b8f2e074594ceb05d47c27386969754b6ad0c15e5eb8f691399cd0be980e7655565b6033546001600160a01b031690565b600054610100900460ff16806107425750610742610fb8565b80610750575060005460ff16155b61078b5760405162461bcd60e51b815260040180806020018281038252602e815260200180611609602e913960400191505060405180910390fd5b600054610100900460ff161580156107b6576000805460ff1961ff0019909116610100171660011790555b6107be610fbe565b606a805460ff60a01b1916600160a01b17905580156107e3576000805461ff00191690555b50565b6066546001600160a01b03166385f4498b6107ff610fb4565b6040518263ffffffff1660e01b815260040161081b919061140b565b60206040518083038186803b15801561083357600080fd5b505afa158015610847573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061086b91906113d7565b6108875760405162461bcd60e51b8152600401610378906114f2565b8060686000610894610fb4565b6001600160a01b03166001600160a01b031681526020019081526020016000205410156108d35760405162461bcd60e51b81526004016103789061157f565b6069546108e0908261106f565b60695561091381606860006108f3610fb4565b6001600160a01b031681526020810191909152604001600020549061106f565b6068600061091f610fb4565b6001600160a01b0390811682526020820192909252604001600020919091556065541663a9059cbb61094f610fb4565b836040518363ffffffff1660e01b815260040161096d929190611443565b602060405180830381600087803b15801561098757600080fd5b505af115801561099b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109bf91906113d7565b507f0f0bc5b519ddefdd8e5f9e6423433aa2b869738de2ae34d58ebc796fc749fa0d6109e9610fb4565b826040516109f8929190611443565b60405180910390a150565b606a546001600160a01b031681565b6066546001600160a01b031681565b6000816001600160a01b0316610a35610fb4565b6001600160a01b03161480610a6457506066546001600160a01b0316610a59610fb4565b6001600160a01b0316145b80610a9d5750606a54600160a01b900460ff168015610a9d5750606a546001600160a01b0316610a92610fb4565b6001600160a01b0316145b610ab95760405162461bcd60e51b815260040161037890611548565b506001600160a01b031660009081526068602052604090205490565b610add610fb4565b6001600160a01b0316739dd9e2b26f75d42437582fcb354d567556343dae6001600160a01b031614610b0e57600080fd5b606954610b1b90826110b8565b6069556001600160a01b038216600090815260686020526040902054610b4190826110b8565b6001600160a01b0383166000908152606860205260409081902091909155517f9f1ec8c880f76798e7b793325d625e9b60e4082a553c98f42b6cda368dd6000890610b8f9084908490611443565b60405180910390a15050565b60008111610bbb5760405162461bcd60e51b8152600401610378906114b0565b606954610bc890826110b8565b60695533600090815260686020526040902054610be590826110b8565b33600081815260686020526040908190209290925560655491516323b872dd60e01b81526001600160a01b03909216916323b872dd91610c2b913090869060040161141f565b602060405180830381600087803b158015610c4557600080fd5b505af1158015610c59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c7d91906113d7565b507f9f1ec8c880f76798e7b793325d625e9b60e4082a553c98f42b6cda368dd6000833826040516109f8929190611443565b6066546001600160a01b0316610cc3610fb4565b6001600160a01b031614610ce95760405162461bcd60e51b815260040161037890611467565b6001600160a01b038216600090815260686020526040902054610d0c9082611112565b606954909150610d1c908261106f565b6069556001600160a01b038216600090815260686020526040902054610d42908261106f565b6001600160a01b038084166000908152606860205260409081902092909255606554606754925163a9059cbb60e01b81529082169263a9059cbb92610d8e929116908590600401611443565b602060405180830381600087803b158015610da857600080fd5b505af1158015610dbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610de091906113d7565b507f9ff4ae348b6f91c222997eceeebbeefe70027c0d92a032e1c9d5e4542536fcbf8282604051610b8f929190611443565b6067546001600160a01b031681565b610e29610fb4565b6033546001600160a01b03908116911614610e8b576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b606a8054911515600160a01b0260ff60a01b19909216919091179055565b610eb1610fb4565b6033546001600160a01b03908116911614610f13576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b038116610f585760405162461bcd60e51b81526004018080602001828103825260268152602001806115e36026913960400191505060405180910390fd5b6033546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603380546001600160a01b0319166001600160a01b0392909216919091179055565b3390565b303b1590565b600054610100900460ff1680610fd75750610fd7610fb8565b80610fe5575060005460ff16155b6110205760405162461bcd60e51b815260040180806020018281038252602e815260200180611609602e913960400191505060405180910390fd5b600054610100900460ff1615801561104b576000805460ff1961ff0019909116610100171660011790555b611053611128565b61105b6111c8565b80156107e3576000805461ff001916905550565b60006110b183836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506112c1565b9392505050565b6000828201838110156110b1576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600081831061112157816110b1565b5090919050565b600054610100900460ff16806111415750611141610fb8565b8061114f575060005460ff16155b61118a5760405162461bcd60e51b815260040180806020018281038252602e815260200180611609602e913960400191505060405180910390fd5b600054610100900460ff1615801561105b576000805460ff1961ff00199091166101001716600117905580156107e3576000805461ff001916905550565b600054610100900460ff16806111e157506111e1610fb8565b806111ef575060005460ff16155b61122a5760405162461bcd60e51b815260040180806020018281038252602e815260200180611609602e913960400191505060405180910390fd5b600054610100900460ff16158015611255576000805460ff1961ff0019909116610100171660011790555b600061125f610fb4565b603380546001600160a01b0319166001600160a01b038316908117909155604051919250906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a35080156107e3576000805461ff001916905550565b600081848411156113505760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156113155781810151838201526020016112fd565b50505050905090810190601f1680156113425780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600060208284031215611369578081fd5b81356110b1816115bf565b600060208284031215611385578081fd5b81516110b1816115bf565b600080604083850312156113a2578081fd5b82356113ad816115bf565b946020939093013593505050565b6000602082840312156113cc578081fd5b81356110b1816115d4565b6000602082840312156113e8578081fd5b81516110b1816115d4565b600060208284031215611404578081fd5b5035919050565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b60208082526029908201527f53746b424d495374616b696e673a204e6f74206120436c61696d566f74696e676040820152680818dbdb9d1c9858dd60ba1b606082015260800190565b60208082526022908201527f53746b424d495374616b696e673a2063616e2774206c6f636b203020746f6b656040820152616e7360f01b606082015260800190565b60208082526036908201527f53746b424d495374616b696e673a2043616e27742077697468647261772c207460408201527568657265206172652070656e64696e6720766f74657360501b606082015260800190565b6020808252601b908201527f53746b424d495374616b696e67203a206e6f7420616c6c6f7765640000000000604082015260600190565b6020808252601f908201527f53746b424d495374616b696e673a204e6f207374616b656420616d6f756e7400604082015260600190565b90815260200190565b6001600160a01b03811681146107e357600080fd5b80151581146107e357600080fdfe4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a6564a2646970667358221220c33948cc386337c1d7d95233ef6dff976a546908d49207c460214493b174ccb564736f6c63430007040033

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.