lohoz/Smart-Contract-MultiTask-Dataset huggingface dataset:
// Solidity 0.7.5
/**
 * @dev returns the current delegated power of a user. The current power is the
 * power delegated at the time of the last snapshot
 * @param user the user
 **/
function getPowerCurrent(address user, DelegationType delegationType)
    external
    override
    view
    returns (uint256)
  {
    (
      mapping(address => mapping(uint256 => Snapshot)) storage snapshots,
      mapping(address => uint256) storage snapshotsCounts,

    ) = _getDelegationDataByType(delegationType);

    return _searchByBlockNumber(snapshots, snapshotsCounts, user, block.number);
  }
// Solidity 0.7.5
/**
 * @dev returns the delegated power of a user at a certain block
 * @param user the user
 **/
function getPowerAtBlock(
    address user,
    uint256 blockNumber,
    DelegationType delegationType
  ) external override view returns (uint256) {
    (
      mapping(address => mapping(uint256 => Snapshot)) storage snapshots,
      mapping(address => uint256) storage snapshotsCounts,

    ) = _getDelegationDataByType(delegationType);

    return _searchByBlockNumber(snapshots, snapshotsCounts, user, blockNumber);
  }
// Solidity 0.7.5
/**
 * @dev delegates the specific power to a delegatee
 * @param delegatee the user which delegated power has changed
 * @param delegationType the type of delegation (VOTING_POWER, PROPOSITION_POWER)
 **/
function _delegateByType(
    address delegator,
    address delegatee,
    DelegationType delegationType
  ) internal {
    require(delegatee != address(0), 'INVALID_DELEGATEE');

    (, , mapping(address => address) storage delegates) = _getDelegationDataByType(delegationType);

    uint256 delegatorBalance = balanceOf(delegator);

    address previousDelegatee = _getDelegatee(delegator, delegates);

    delegates[delegator] = delegatee;

    _moveDelegatesByType(previousDelegatee, delegatee, delegatorBalance, delegationType);
    emit DelegateChanged(delegator, delegatee, delegationType);
  }
// Solidity 0.7.5
/**
 * @dev moves delegated power from one user to another
 * @param from the user from which delegated power is moved
 * @param to the user that will receive the delegated power
 * @param amount the amount of delegated power to be moved
 * @param delegationType the type of delegation (VOTING_POWER, PROPOSITION_POWER)
 **/
function _moveDelegatesByType(
    address from,
    address to,
    uint256 amount,
    DelegationType delegationType
  ) internal {
    if (from == to) {
      return;
    }

    (
      mapping(address => mapping(uint256 => Snapshot)) storage snapshots,
      mapping(address => uint256) storage snapshotsCounts,

    ) = _getDelegationDataByType(delegationType);

    if (from != address(0)) {
      uint256 previous = 0;
      uint256 fromSnapshotsCount = snapshotsCounts[from];

      if (fromSnapshotsCount != 0) {
        previous = snapshots[from][fromSnapshotsCount - 1].value;
      } else {
        previous = balanceOf(from);
      }

      _writeSnapshot(
        snapshots,
        snapshotsCounts,
        from,
        uint128(previous),
        uint128(previous.sub(amount))
      );

      emit DelegatedPowerChanged(from, previous.sub(amount), delegationType);
    }
    if (to != address(0)) {
      uint256 previous = 0;
      uint256 toSnapshotsCount = snapshotsCounts[to];
      if (toSnapshotsCount != 0) {
        previous = snapshots[to][toSnapshotsCount - 1].value;
      } else {
        previous = balanceOf(to);
      }

      _writeSnapshot(
        snapshots,
        snapshotsCounts,
        to,
        uint128(previous),
        uint128(previous.add(amount))
      );

      emit DelegatedPowerChanged(to, previous.add(amount), delegationType);
    }
  }
// Solidity 0.7.5
/**
 * @dev searches a snapshot by block number. Uses binary search.
 * @param snapshots the snapshots mapping
 * @param snapshotsCounts the number of snapshots
 * @param user the user for which the snapshot is being searched
 * @param blockNumber the block number being searched
 **/
function _searchByBlockNumber(
    mapping(address => mapping(uint256 => Snapshot)) storage snapshots,
    mapping(address => uint256) storage snapshotsCounts,
    address user,
    uint256 blockNumber
  ) internal view returns (uint256) {
    require(blockNumber <= block.number, 'INVALID_BLOCK_NUMBER');

    uint256 snapshotsCount = snapshotsCounts[user];

    if (snapshotsCount == 0) {
      return balanceOf(user);
    }

    // First check most recent balance
    if (snapshots[user][snapshotsCount - 1].blockNumber <= blockNumber) {
      return snapshots[user][snapshotsCount - 1].value;
    }

    // Next check implicit zero balance
    if (snapshots[user][0].blockNumber > blockNumber) {
      return 0;
    }

    uint256 lower = 0;
    uint256 upper = snapshotsCount - 1;
    while (upper > lower) {
      uint256 center = upper - (upper - lower) / 2; // ceil, avoiding overflow
      Snapshot memory snapshot = snapshots[user][center];
      if (snapshot.blockNumber == blockNumber) {
        return snapshot.value;
      } else if (snapshot.blockNumber < blockNumber) {
        lower = center;
      } else {
        upper = center - 1;
      }
    }
    return snapshots[user][lower].value;
  }
// Solidity 0.7.5
/**
 * @dev Writes a snapshot for an owner of tokens
 * @param owner The owner of the tokens
 * @param oldValue The value before the operation that is gonna be executed after the snapshot
 * @param newValue The value after the operation
 */
function _writeSnapshot(
    mapping(address => mapping(uint256 => Snapshot)) storage snapshots,
    mapping(address => uint256) storage snapshotsCounts,
    address owner,
    uint128 oldValue,
    uint128 newValue
  ) internal {
    uint128 currentBlock = uint128(block.number);

    uint256 ownerSnapshotsCount = snapshotsCounts[owner];
    mapping(uint256 => Snapshot) storage snapshotsOwner = snapshots[owner];

    // Doing multiple operations in the same block
    if (
      ownerSnapshotsCount != 0 &&
      snapshotsOwner[ownerSnapshotsCount - 1].blockNumber == currentBlock
    ) {
      snapshotsOwner[ownerSnapshotsCount - 1].value = newValue;
    } else {
      snapshotsOwner[ownerSnapshotsCount] = Snapshot(currentBlock, newValue);
      snapshotsCounts[owner] = ownerSnapshotsCount + 1;
    }
  }
// Solidity 0.7.5
/**
 * @dev Redeems staked tokens, and stop earning rewards
 * @param to Address to redeem to
 * @param amount Amount to redeem
 **/
function redeem(address to, uint256 amount) external override {
    require(amount != 0, 'INVALID_ZERO_AMOUNT');
    //solium-disable-next-line
    uint256 cooldownStartTimestamp = stakersCooldowns[msg.sender];
    require(
      block.timestamp > cooldownStartTimestamp.add(COOLDOWN_SECONDS),
      'INSUFFICIENT_COOLDOWN'
    );
    require(
      block.timestamp.sub(cooldownStartTimestamp.add(COOLDOWN_SECONDS)) <= UNSTAKE_WINDOW,
      'UNSTAKE_WINDOW_FINISHED'
    );
    uint256 balanceOfMessageSender = balanceOf(msg.sender);

    uint256 amountToRedeem = (amount > balanceOfMessageSender) ? balanceOfMessageSender : amount;

    _updateCurrentUnclaimedRewards(msg.sender, balanceOfMessageSender, true);

    _burn(msg.sender, amountToRedeem);

    if (balanceOfMessageSender.sub(amountToRedeem) == 0) {
      stakersCooldowns[msg.sender] = 0;
    }

    IERC20(STAKED_TOKEN).safeTransfer(to, amountToRedeem);

    emit Redeem(msg.sender, to, amountToRedeem);
  }
// Solidity 0.7.5
/**
 * @dev Claims an `amount` of `REWARD_TOKEN` to the address `to`
 * @param to Address to stake for
 * @param amount Amount to stake
 **/
function claimRewards(address to, uint256 amount) external override {
    uint256 newTotalRewards =
      _updateCurrentUnclaimedRewards(msg.sender, balanceOf(msg.sender), false);
    uint256 amountToClaim = (amount == type(uint256).max) ? newTotalRewards : amount;

    stakerRewardsToClaim[msg.sender] = newTotalRewards.sub(amountToClaim, 'INVALID_AMOUNT');

    REWARD_TOKEN.safeTransferFrom(REWARDS_VAULT, to, amountToClaim);

    emit RewardsClaimed(msg.sender, to, amountToClaim);
  }
// Solidity 0.7.5
/**
 * @dev Internal ERC20 _transfer of the tokenized staked tokens
 * @param from Address to transfer from
 * @param to Address to transfer to
 * @param amount Amount to transfer
 **/
function _transfer(
    address from,
    address to,
    uint256 amount
  ) internal override {
    uint256 balanceOfFrom = balanceOf(from);
    // Sender
    _updateCurrentUnclaimedRewards(from, balanceOfFrom, true);

    // Recipient
    if (from != to) {
      uint256 balanceOfTo = balanceOf(to);
      _updateCurrentUnclaimedRewards(to, balanceOfTo, true);

      uint256 previousSenderCooldown = stakersCooldowns[from];
      stakersCooldowns[to] = getNextCooldownTimestamp(
        previousSenderCooldown,
        amount,
        to,
        balanceOfTo
      );
      // if cooldown was set and whole balance of sender was transferred - clear cooldown
      if (balanceOfFrom == amount && previousSenderCooldown != 0) {
        stakersCooldowns[from] = 0;
      }
    }

    super._transfer(from, to, amount);
  }
// Solidity 0.7.5
/**
 * @dev Updates the user state related with his accrued rewards
 * @param user Address of the user
 * @param userBalance The current balance of the user
 * @param updateStorage Boolean flag used to update or not the stakerRewardsToClaim of the user
 * @return The unclaimed rewards that were added to the total accrued
 **/
function _updateCurrentUnclaimedRewards(
    address user,
    uint256 userBalance,
    bool updateStorage
  ) internal returns (uint256) {
    uint256 accruedRewards =
      _updateUserAssetInternal(user, address(this), userBalance, totalSupply());
    uint256 unclaimedRewards = stakerRewardsToClaim[user].add(accruedRewards);

    if (accruedRewards != 0) {
      if (updateStorage) {
        stakerRewardsToClaim[user] = unclaimedRewards;
      }
      emit RewardsAccrued(user, accruedRewards);
    }

    return unclaimedRewards;
  }
// Solidity 0.7.5
/**
 * @dev Calculates the how is gonna be a new cooldown timestamp depending on the sender/receiver situation
 *  - If the timestamp of the sender is "better" or the timestamp of the recipient is 0, we take the one of the recipient
 *  - Weighted average of from/to cooldown timestamps if:
 *    # The sender doesn't have the cooldown activated (timestamp 0).
 *    # The sender timestamp is expired
 *    # The sender has a "worse" timestamp
 *  - If the receiver's cooldown timestamp expired (too old), the next is 0
 * @param fromCooldownTimestamp Cooldown timestamp of the sender
 * @param amountToReceive Amount
 * @param toAddress Address of the recipient
 * @param toBalance Current balance of the receiver
 * @return The new cooldown timestamp
 **/
function getNextCooldownTimestamp(
    uint256 fromCooldownTimestamp,
    uint256 amountToReceive,
    address toAddress,
    uint256 toBalance
  ) public returns (uint256) {
    uint256 toCooldownTimestamp = stakersCooldowns[toAddress];
    if (toCooldownTimestamp == 0) {
      return 0;
    }

    uint256 minimalValidCooldownTimestamp =
      block.timestamp.sub(COOLDOWN_SECONDS).sub(UNSTAKE_WINDOW);

    if (minimalValidCooldownTimestamp > toCooldownTimestamp) {
      toCooldownTimestamp = 0;
    } else {
      uint256 fromCooldownTimestamp =
        (minimalValidCooldownTimestamp > fromCooldownTimestamp)
          ? block.timestamp
          : fromCooldownTimestamp;

      if (fromCooldownTimestamp < toCooldownTimestamp) {
        return toCooldownTimestamp;
      } else {
        toCooldownTimestamp = (
          amountToReceive.mul(fromCooldownTimestamp).add(toBalance.mul(toCooldownTimestamp))
        )
          .div(amountToReceive.add(toBalance));
      }
    }
    stakersCooldowns[toAddress] = toCooldownTimestamp;

    return toCooldownTimestamp;
  }
// Solidity 0.7.5
/**
 * @dev Writes a snapshot before any operation involving transfer of value: _transfer, _mint and _burn
 * - On _transfer, it writes snapshots for both "from" and "to"
 * - On _mint, only for _to
 * - On _burn, only for _from
 * @param from the from address
 * @param to the to address
 * @param amount the amount to transfer
 */
function _beforeTokenTransfer(
    address from,
    address to,
    uint256 amount
  ) internal override {
    address votingFromDelegatee = _votingDelegates[from];
    address votingToDelegatee = _votingDelegates[to];

    if (votingFromDelegatee == address(0)) {
      votingFromDelegatee = from;
    }
    if (votingToDelegatee == address(0)) {
      votingToDelegatee = to;
    }

    _moveDelegatesByType(
      votingFromDelegatee,
      votingToDelegatee,
      amount,
      DelegationType.VOTING_POWER
    );

    address propPowerFromDelegatee = _propositionPowerDelegates[from];
    address propPowerToDelegatee = _propositionPowerDelegates[to];

    if (propPowerFromDelegatee == address(0)) {
      propPowerFromDelegatee = from;
    }
    if (propPowerToDelegatee == address(0)) {
      propPowerToDelegatee = to;
    }

    _moveDelegatesByType(
      propPowerFromDelegatee,
      propPowerToDelegatee,
      amount,
      DelegationType.PROPOSITION_POWER
    );

    // caching the aave governance address to avoid multiple state loads
    ITransferHook aaveGovernance = _aaveGovernance;
    if (aaveGovernance != ITransferHook(0)) {
      aaveGovernance.onTransfer(from, to, amount);
    }
  }
// Solidity 0.4.25
// Transfer the balance from token owner account to receiver account
function transfer(address to, uint tokens) public returns (bool success) {
        require(to != 0x0); // Prevent transfer to 0x0 address. Use burn() instead
        require(!transactionLock);  // Check for transaction lock
        require(!frozenAccount[to]);// Check if recipient is frozen
        balances[msg.sender] = balances[msg.sender].sub(tokens);
        balances[to] = balances[to].add(tokens);
        emit Transfer(msg.sender, to, tokens);
        return true;
    }
// Solidity 0.4.25
// Transfer token from spender account to receiver account
function transferFrom(address from, address to, uint tokens) public returns (bool success) {
        require(to != 0x0); // Prevent transfer to 0x0 address. Use burn() instead
        require(!transactionLock);         // Check for transaction lock
        require(!frozenAccount[from]);     // Check if sender is frozen
        require(!frozenAccount[to]);       // Check if recipient is frozen
        balances[from] = balances[from].sub(tokens);
        allowed[from][msg.sender] = allowed[from][msg.sender].sub(tokens);
        balances[to] = balances[to].add(tokens);
        emit Transfer(from, to, tokens);
        return true;
    }
// Solidity 0.6.12
/**
 * @dev stakeNft allows a user to submit their NFT to the contract and begin getting returns.
 * @param _nftIds The ID of the NFT being staked.
 **/
function batchStakeNft(uint256[] memory _nftIds)
      public
      // doKeep
    {
        // Loop through all submitted NFT IDs and stake them.
        for (uint256 i = 0; i < _nftIds.length; i++) {
            _stake(_nftIds[i], msg.sender);
        }
    }
// Solidity 0.6.12
/**
 * @dev Internal function for staking--this allows us to skip updating stake multiple times during a batch stake.
 * @param _nftId The ID of the NFT being staked. == coverId
 * @param _user The user who is staking the NFT.
 **/
function _stake(uint256 _nftId, address _user)
      internal
    {
        (/*coverId*/,  uint8 coverStatus, uint256 sumAssured, uint16 coverPeriod, uint256 validUntil, address scAddress, 
         bytes4 coverCurrency, /*premiumNXM*/, uint256 coverPrice, /*claimId*/) = IarNFT( getModule("ARNFT") ).getToken(_nftId);
        
        _checkNftValid(validUntil, scAddress, coverCurrency, coverStatus);
        
        // coverPrice must be determined by dividing by length.
        uint256 secondPrice = coverPrice / (uint256(coverPeriod) * 1 days);

        // Update PlanManager to use the correct price for the protocol.
        // Find price per amount here to update plan manager correctly.
        uint256 pricePerEth = secondPrice / sumAssured;
        
        IPlanManager(getModule("PLAN")).changePrice(scAddress, pricePerEth);
        
        IarNFT(getModule("ARNFT")).transferFrom(_user, getModule("CLAIM"), _nftId);

        ExpireTracker.push(uint96(_nftId), uint64(validUntil));
        // Save owner of NFT.
        nftOwners[_nftId] = _user;

        uint256 weiSumAssured = sumAssured * (10 ** 18);
        _addCovers(_user, _nftId, weiSumAssured, secondPrice, scAddress);
        
        // Add to utilization farming.
        if (ufOn) IUtilizationFarm(getModule("UFS")).stake(_user, secondPrice);
        
        emit StakedNFT(_user, scAddress, _nftId, weiSumAssured, secondPrice, coverPeriod, block.timestamp);
    }
// Solidity 0.6.12
/**
 * @dev Internal main removal functionality.
 **/
function _removeNft(uint256 _nftId)
      internal
    {
        (/*coverId*/, /*status*/, uint256 sumAssured, uint16 coverPeriod, /*uint256 validuntil*/, address scAddress, 
         /*coverCurrency*/, /*premiumNXM*/, uint256 coverPrice, /*claimId*/) = IarNFT(getModule("ARNFT")).getToken(_nftId);
        address user = nftOwners[_nftId];
        require(user != address(0), "NFT does not belong to this contract.");

        ExpireTracker.pop(uint96(_nftId));

        uint256 weiSumAssured = sumAssured * (10 ** 18);
        uint256 secondPrice = coverPrice / (uint256(coverPeriod) * 1 days);
        _subtractCovers(user, _nftId, weiSumAssured, secondPrice, scAddress);
        
        // Exit from utilization farming.
        if (ufOn) IUtilizationFarm(getModule("UFS")).withdraw(user, secondPrice);

        emit RemovedNFT(user, scAddress, _nftId, weiSumAssured, secondPrice, coverPeriod, block.timestamp);
    }
// Solidity 0.6.12
/**
 * @dev Need a force remove--at least temporarily--where owner can remove data relating to an NFT.
 *      This necessity came about when updating the contracts and some users started withdrawal when _removeNFT
 *      was in the second step of withdrawal, then executed the second step of withdrawal after _removeNFT had
 *      been moved to the first step of withdrawal.
 **/
function forceRemoveNft(address[] calldata _users, uint256[] calldata _nftIds)
      external
      onlyOwner
    {
        require(_users.length == _nftIds.length, "Array lengths must match.");
        for (uint256 i = 0; i < _users.length; i++) {
            uint256 nftId = _nftIds[i];
            address user = _users[i];
            (/*coverId*/, /*status*/, uint256 sumAssured, uint16 coverPeriod, /*uint256 validuntil*/, address scAddress, 
            /*coverCurrency*/, /*premiumNXM*/, uint256 coverPrice, /*claimId*/) = IarNFT(getModule("ARNFT")).getToken(nftId);
            //address user = nftOwners[_nftId];
            // require(user != address(0), "NFT does not belong to this contract.");
            require(nftOwners[nftId] == address(0) && ExpireTracker.infos[uint96(nftId)].next > 0, "NFT may not be force removed.");

            ExpireTracker.pop(uint96(nftId));

            uint256 weiSumAssured = sumAssured * (10 ** 18);
            uint256 secondPrice = coverPrice / (uint256(coverPeriod) * 1 days);
            _subtractCovers(user, nftId, weiSumAssured, secondPrice, scAddress);
            
            // Exit from utilization farming.
            if (ufOn) IUtilizationFarm(getModule("UFS")).withdraw(user, secondPrice);

            emit RemovedNFT(user, scAddress, nftId, weiSumAssured, secondPrice, coverPeriod, block.timestamp);
        }
    }
// Solidity 0.6.12
/**
 * @dev Some NFT expiries used a different bucket step upon update and must be reset. 
 **/
function forceResetExpires(uint256[] calldata _nftIds)
      external
      onlyOwner
    {
        uint64[] memory validUntils = new uint64[](_nftIds.length);
        for (uint256 i = 0; i < _nftIds.length; i++) {
            (/*coverId*/, /*status*/, /*uint256 sumAssured*/, /*uint16 coverPeriod*/, uint256 validUntil, /*address scAddress*/, 
            /*coverCurrency*/, /*premiumNXM*/, /*uint256 coverPrice*/, /*claimId*/) = IarNFT(getModule("ARNFT")).getToken(_nftIds[i]);
            require(nftOwners[_nftIds[i]] != address(0), "this nft does not belong here");
            ExpireTracker.pop(uint96(_nftIds[i]), 86400);
            ExpireTracker.pop(uint96(_nftIds[i]), 86400*3);
            validUntils[i] = uint64(validUntil);
        }
        for (uint256 i = 0; i < _nftIds.length; i++) {
            ExpireTracker.push(uint96(_nftIds[i]),uint64(validUntils[i]));
        }
    }
// Solidity 0.6.12
/**
 * @dev Subtract from the cover amount for the user and contract overall.
 * @param _user The user who is having the token removed.
 * @param _nftId ID of the NFT being used--must check if it has been submitted.
 * @param _coverAmount The amount of cover being removed.
 * @param _coverPrice Price that the user was paying per second.
 * @param _protocol The protocol that this NFT protected.
 **/
function _subtractCovers(address _user, uint256 _nftId, uint256 _coverAmount, uint256 _coverPrice, address _protocol)
      internal
    {
        if (coverMigrated[_nftId]) {
            IRewardManagerV2(getModule("REWARDV2")).withdraw(_user, _protocol, _coverPrice, _nftId);
        } else {
            IRewardManager(getModule("REWARD")).withdraw(_user, _coverPrice, _nftId);
        }

        if (!submitted[_nftId]) totalStakedAmount[_protocol] = totalStakedAmount[_protocol].sub(_coverAmount);
    }
// Solidity 0.6.12
/**
 * @dev Migrate reward to V2
 * @param _nftIds Nft ids
 **/
function migrateCovers(uint256[] calldata _nftIds)
      external
    {
        for (uint256 i = 0; i < _nftIds.length; i += 1) {
            address user = nftOwners[_nftIds[i]];
            require(user != address(0), "NFT not staked.");
            require(coverMigrated[_nftIds[i]] == false, "Already migrated.");
            coverMigrated[_nftIds[i]] = true;
            (/*coverId*/, /*status*/, /*sumAssured*/, uint16 coverPeriod, /*uint256 validuntil*/, address scAddress, 
            /*coverCurrency*/, /*premiumNXM*/, uint256 coverPrice, /*claimId*/) = IarNFT(getModule("ARNFT")).getToken(_nftIds[i]);

            uint256 secondPrice = coverPrice / (uint256(coverPeriod) * 1 days);

            IRewardManager(getModule("REWARD")).withdraw(user, secondPrice, _nftIds[i]);
            IRewardManagerV2(getModule("REWARDV2")).deposit(user, scAddress, secondPrice, _nftIds[i]);
        }
    }
// Solidity 0.6.12
/**
 * @dev Check that the NFT should be allowed to be added. We check expiry and claimInProgress.
 * @param _validUntil The expiration time of this NFT.
 * @param _scAddress The smart contract protocol that the NFt is protecting.
 * @param _coverCurrency The currency that this NFT is protected in (must be ETH_SIG).
 * @param _coverStatus status of cover, only accepts Active
 **/
function _checkNftValid(uint256 _validUntil, address _scAddress, bytes4 _coverCurrency, uint8 _coverStatus)
      internal
      view
    {
        require(_validUntil > now + 20 days, "NFT is expired or within 20 days of expiry.");
        require(_coverStatus == 0, "arNFT claim is already in progress.");
        require(allowedProtocol[_scAddress], "Protocol is not allowed to be staked.");
        require(_coverCurrency == ETH_SIG, "Only Ether arNFTs may be staked.");
    }