lohoz/Smart-Contract-MultiTask-Dataset huggingface dataset:
// Solidity 0.8.7
/**
 * @dev Allow anyone to buy presale tokens for the right price.
 * @param  _purchaseAmount the amount of tokens to buy
 * @param  _hash the bytes for the message hash
 * @param _signature the signature of the message   
 */
function buy(uint256 _purchaseAmount, bytes32 _hash, bytes memory _signature) public payable {
    require(_purchaseAmount > 0, "You Should Buy at least 1.");
    require(_purchaseAmount + PURCHASED[msg.sender] <= MAX_PURCHASE, "Maximum amount exceded per wallet");
    require(SUPPLY + _purchaseAmount <= MAX_SUPPLY, "400 maximum.");
    require(msg.value >= PRICE * _purchaseAmount, "Insufficient value.");
    require(_checkHash(_hash, _signature, SIGNER), "Address is not on Presale List");
    PURCHASED[msg.sender] += _purchaseAmount;
    for (uint i = 0; i < _purchaseAmount; i++) {
      OWNERS.push(msg.sender);
    }
    SUPPLY += _purchaseAmount;
  }
// Solidity 0.8.7
/**
 * @dev Divides the correct amount of tokens for every address by 100 presale tokens.
 */
function withdraw() public payable onlyAdmin {
    require(SUPPLY >= 100, "The minimum supply to withdraw is 100.");
    uint paymentStage = uint ((SUPPLY - LAST_SUPPLY)/ 100);
    uint256 QDamount = (QDpayment * paymentStage);
    uint256 ARTamount = (ARTpayment * paymentStage);
    (bool qd, ) = payable(QDaddress).call{value: QDamount}("");
    require(qd);
    (bool art, ) = payable(ARTaddress).call{value: ARTamount}("");
    require(art);
    (bool project, ) = payable(projectAddress).call{value: (PRICE * paymentStage * 100) - (ARTamount + QDamount)}("");
    require(project);
    LAST_SUPPLY = paymentStage * 100;
  }
// Solidity 0.6.12
// Stake funds into the pool
function stake(uint256 amount) public virtual {
        // Calculate tax and after-tax amount
        uint256 taxRate = calculateTax();
        uint256 taxedAmount = amount.mul(taxRate).div(100);
        uint256 stakedAmount = amount.sub(taxedAmount);

        // Increment sender's balances and total supply
        _balances[msg.sender] = _balances[msg.sender].add(stakedAmount);
        _totalSupply = _totalSupply.add(stakedAmount);
        // Increment dev fund by tax
        devFund = devFund.add(taxedAmount);

        // Transfer funds
        stakingToken.safeTransferFrom(msg.sender, address(this), amount);
    }
// Solidity 0.6.12
// Distributes the dev fund to the developer addresses, callable by anyone
function distributeDevFund() public virtual {
        // Reset dev fund to 0 before distributing any funds
        uint256 totalDistributionAmount = devFund;
        devFund = 0;
        // Distribute dev fund according to percentages
        for (uint256 i = 0; i < devCount; i++) {
            uint256 devPercentage = devAllocations[devIDs[i]];
            uint256 allocation = totalDistributionAmount.mul(devPercentage).div(
                100
            );
            if (allocation > 0) {
                stakingToken.safeTransfer(devIDs[i], allocation);
            }
        }
    }
// Solidity 0.6.12
// Return the tax amount according to current block time
function calculateTax() public view returns (uint256) {
        // Pre-pool start time = 3% tax
        if (block.timestamp < startTime) {
            return 3;
            // 0-60 minutes after pool start time = 5% tax
        } else if (
            block.timestamp.sub(startTime) >= 0 minutes &&
            block.timestamp.sub(startTime) <= 60 minutes
        ) {
            return 5;
            // 60-90 minutes after pool start time = 3% tax
        } else if (
            block.timestamp.sub(startTime) > 60 minutes &&
            block.timestamp.sub(startTime) <= 90 minutes
        ) {
            return 3;
            // 90+ minutes after pool start time = 1% tax
        } else if (block.timestamp.sub(startTime) > 90 minutes) {
            return 1;
        }
    }
// Solidity 0.6.12
// Staking function which updates the user balances in the parent contract
function stake(uint256 amount) public override {
        updateReward(msg.sender);
        require(amount > 0, "Cannot stake 0");
        super.stake(amount);

        // Users that have bought multipliers will have an extra balance added to their stake according to the boost multiplier.
        if (boostLevel[msg.sender] > 0) {
            uint256 prevBalancesAccounting = _balancesAccounting[msg.sender];
            // Calculate and set user's new accounting balance
            uint256 accTotalMultiplier = getTotalMultiplier(msg.sender);
            uint256 newBalancesAccounting = _balances[msg.sender]
                .mul(accTotalMultiplier)
                .div(1e18)
                .sub(_balances[msg.sender]);
            _balancesAccounting[msg.sender] = newBalancesAccounting;
            // Adjust total accounting supply accordingly
            uint256 diffBalancesAccounting = newBalancesAccounting.sub(
                prevBalancesAccounting
            );
            _totalSupplyAccounting = _totalSupplyAccounting.add(
                diffBalancesAccounting
            );
        }

        emit Staked(msg.sender, amount);
    }
// Solidity 0.6.12
// Returns the multiplier for user.
function getTotalMultiplier(address account) public view returns (uint256) {
        uint256 boostMultiplier = 0;
        if (boostLevel[account] == 1) {
            boostMultiplier = FivePercentBonus;
        } else if (boostLevel[account] == 2) {
            boostMultiplier = TwentyPercentBonus;
        } else if (boostLevel[account] == 3) {
            boostMultiplier = FourtyPercentBonus;
        } else if (boostLevel[account] == 4) {
            boostMultiplier = HundredPercentBonus;
        }
        return boostMultiplier.add(1 * 10**18);
    }
// Solidity 0.6.12
// Distributes the dev fund for accounts
function distributeDevFund() public override {
        uint256 totalMulitplierDistributionAmount = multiplierTokenDevFund;
        multiplierTokenDevFund = 0;
        // Distribute multiplier dev fund according to percentages
        for (uint256 i = 0; i < devCount; i++) {
            uint256 devPercentage = devAllocations[devIDs[i]];
            uint256 allocation = totalMulitplierDistributionAmount
                .mul(devPercentage)
                .div(100);
            if (allocation > 0) {
                multiplierToken.safeTransfer(devIDs[i], allocation);
            }
        }
        // Distribute the staking token rewards
        super.distributeDevFund();
    }
// Solidity 0.4.25
/// @notice Used to burn tokens and decrease total supply
/// @param _amount The amount of TEMPLATE-TOKENToken tokens in wei to burn
function tokenBurner(uint256 _amount) public
    onlyOwner
    returns (bool burned)
    {
        require(_amount > 0);
        require(totalSupply.sub(_amount) > 0);
        require(balances[msg.sender] > _amount);
        require(balances[msg.sender].sub(_amount) > 0);
        totalSupply = totalSupply.sub(_amount);
        balances[msg.sender] = balances[msg.sender].sub(_amount);
        emit Transfer(msg.sender, 0, _amount);
        return true;
    }
// Solidity 0.4.25
/// @notice Reusable code to do sanity check of transfer variables
function transferCheck(address _sender, address _receiver, uint256 _amount)
    private
    constant
    returns (bool success)
    {
        require(!tokenIsFrozen);
        require(_amount > 0);
        require(_receiver != address(0));
        require(balances[_sender].sub(_amount) >= 0);
        require(balances[_receiver].add(_amount) > 0);
        require(balances[_receiver].add(_amount) > balances[_receiver]);
        return true;
    }
// Solidity 0.6.12
/**
 * @dev Deposit Vault's type collateral to activeProvider
 * call Controller checkrates
 * @param _collateralAmount: to be deposited
 * Emits a {Deposit} event.
 */
function deposit(uint256 _collateralAmount) public payable override {
    require(msg.value == _collateralAmount && _collateralAmount != 0, Errors.VL_AMOUNT_ERROR);

    // Alpha Whitelist Routine
    require(
      IAlphaWhiteList(_fujiAdmin.getaWhiteList()).whiteListRoutine(
        msg.sender,
        vAssets.collateralID,
        _collateralAmount,
        fujiERC1155
      ),
      Errors.SP_ALPHA_WHITELIST
    );

    // Delegate Call Deposit to current provider
    _deposit(_collateralAmount, address(activeProvider));

    // Collateral Management
    IFujiERC1155(fujiERC1155).mint(msg.sender, vAssets.collateralID, _collateralAmount, "");

    emit Deposit(msg.sender, vAssets.collateralAsset, _collateralAmount);
  }
// Solidity 0.6.12
/**
 * @dev Withdraws Vault's type collateral from activeProvider
 * call Controller checkrates
 * @param _withdrawAmount: amount of collateral to withdraw
 * otherwise pass -1 to withdraw maximum amount possible of collateral (including safety factors)
 * Emits a {Withdraw} event.
 */
function withdraw(int256 _withdrawAmount) public override nonReentrant {
    // If call from Normal User do typical, otherwise Fliquidator
    if (msg.sender != _fujiAdmin.getFliquidator()) {
      updateF1155Balances();

      // Get User Collateral in this Vault
      uint256 providedCollateral =
        IFujiERC1155(fujiERC1155).balanceOf(msg.sender, vAssets.collateralID);

      // Check User has collateral
      require(providedCollateral > 0, Errors.VL_INVALID_COLLATERAL);

      // Get Required Collateral with Factors to maintain debt position healthy
      uint256 neededCollateral =
        getNeededCollateralFor(
          IFujiERC1155(fujiERC1155).balanceOf(msg.sender, vAssets.borrowID),
          true
        );

      uint256 amountToWithdraw =
        _withdrawAmount < 0 ? providedCollateral.sub(neededCollateral) : uint256(_withdrawAmount);

      // Check Withdrawal amount, and that it will not fall undercollaterized.
      require(
        amountToWithdraw != 0 && providedCollateral.sub(amountToWithdraw) >= neededCollateral,
        Errors.VL_INVALID_WITHDRAW_AMOUNT
      );

      // Collateral Management before Withdraw Operation
      IFujiERC1155(fujiERC1155).burn(msg.sender, vAssets.collateralID, amountToWithdraw);

      // Delegate Call Withdraw to current provider
      _withdraw(amountToWithdraw, address(activeProvider));

      // Transer Assets to User
      IERC20(vAssets.collateralAsset).uniTransfer(msg.sender, amountToWithdraw);

      emit Withdraw(msg.sender, vAssets.collateralAsset, amountToWithdraw);
    } else {
      // Logic used when called by Fliquidator
      _withdraw(uint256(_withdrawAmount), address(activeProvider));
      IERC20(vAssets.collateralAsset).uniTransfer(msg.sender, uint256(_withdrawAmount));
    }
  }
// Solidity 0.6.12
/**
 * @dev Borrows Vault's type underlying amount from activeProvider
 * @param _borrowAmount: token amount of underlying to borrow
 * Emits a {Borrow} event.
 */
function borrow(uint256 _borrowAmount) public override nonReentrant {
    updateF1155Balances();

    uint256 providedCollateral =
      IFujiERC1155(fujiERC1155).balanceOf(msg.sender, vAssets.collateralID);

    // Get Required Collateral with Factors to maintain debt position healthy
    uint256 neededCollateral =
      getNeededCollateralFor(
        _borrowAmount.add(IFujiERC1155(fujiERC1155).balanceOf(msg.sender, vAssets.borrowID)),
        true
      );

    // Check Provided Collateral is not Zero, and greater than needed to maintain healthy position
    require(
      _borrowAmount != 0 && providedCollateral > neededCollateral,
      Errors.VL_INVALID_BORROW_AMOUNT
    );

    // Debt Management
    IFujiERC1155(fujiERC1155).mint(msg.sender, vAssets.borrowID, _borrowAmount, "");

    // Delegate Call Borrow to current provider
    _borrow(_borrowAmount, address(activeProvider));

    // Transer Assets to User
    IERC20(vAssets.borrowAsset).uniTransfer(msg.sender, _borrowAmount);

    emit Borrow(msg.sender, vAssets.borrowAsset, _borrowAmount);
  }
// Solidity 0.6.12
/**
 * @dev Paybacks Vault's type underlying to activeProvider
 * @param _repayAmount: token amount of underlying to repay, or pass -1 to repay full ammount
 * Emits a {Repay} event.
 */
function payback(int256 _repayAmount) public payable override {
    // If call from Normal User do typical, otherwise Fliquidator
    if (msg.sender != _fujiAdmin.getFliquidator()) {
      updateF1155Balances();

      uint256 userDebtBalance = IFujiERC1155(fujiERC1155).balanceOf(msg.sender, vAssets.borrowID);

      // Check User Debt is greater than Zero and amount is not Zero
      require(_repayAmount != 0 && userDebtBalance > 0, Errors.VL_NO_DEBT_TO_PAYBACK);

      // TODO: Get => corresponding amount of BaseProtocol Debt and FujiDebt

      // If passed argument amount is negative do MAX
      uint256 amountToPayback = _repayAmount < 0 ? userDebtBalance : uint256(_repayAmount);

      // Check User Allowance
      require(
        IERC20(vAssets.borrowAsset).allowance(msg.sender, address(this)) >= amountToPayback,
        Errors.VL_MISSING_ERC20_ALLOWANCE
      );

      // Transfer Asset from User to Vault
      IERC20(vAssets.borrowAsset).transferFrom(msg.sender, address(this), amountToPayback);

      // Delegate Call Payback to current provider
      _payback(amountToPayback, address(activeProvider));

      //TODO: Transfer corresponding Debt Amount to Fuji Treasury

      // Debt Management
      IFujiERC1155(fujiERC1155).burn(msg.sender, vAssets.borrowID, amountToPayback);

      emit Payback(msg.sender, vAssets.borrowAsset, userDebtBalance);
    } else {
      // Logic used when called by Fliquidator
      _payback(uint256(_repayAmount), address(activeProvider));
    }
  }
// Solidity 0.6.12
/**
 * @dev Changes Vault debt and collateral to newProvider, called by Flasher
 * @param _newProvider new provider's address
 * @param _flashLoanAmount amount of flashloan underlying to repay Flashloan
 * Emits a {Switch} event.
 */
function executeSwitch(
    address _newProvider,
    uint256 _flashLoanAmount,
    uint256 fee
  ) external override onlyFlash whenNotPaused {
    // Compute Ratio of transfer before payback
    uint256 ratio =
      _flashLoanAmount.mul(1e18).div(
        IProvider(activeProvider).getBorrowBalance(vAssets.borrowAsset)
      );

    // Payback current provider
    _payback(_flashLoanAmount, activeProvider);

    // Withdraw collateral proportional ratio from current provider
    uint256 collateraltoMove =
      IProvider(activeProvider).getDepositBalance(vAssets.collateralAsset).mul(ratio).div(1e18);

    _withdraw(collateraltoMove, activeProvider);

    // Deposit to the new provider
    _deposit(collateraltoMove, _newProvider);

    // Borrow from the new provider, borrowBalance + premium
    _borrow(_flashLoanAmount.add(fee), _newProvider);

    // return borrowed amount to Flasher
    IERC20(vAssets.borrowAsset).uniTransfer(msg.sender, _flashLoanAmount.add(fee));

    emit Switch(address(this), activeProvider, _newProvider, _flashLoanAmount, collateraltoMove);
  }
// Solidity 0.6.12
/**
 * @dev Set Factors "a" and "b" for a Struct Factor
 * For safetyF;  Sets Safety Factor of Vault, should be > 1, a/b
 * For collatF; Sets Collateral Factor of Vault, should be > 1, a/b
 * @param _newFactorA: Nominator
 * @param _newFactorB: Denominator
 * @param _isSafety: safetyF or collatF
 */
function setFactor(
    uint64 _newFactorA,
    uint64 _newFactorB,
    bool _isSafety
  ) external isAuthorized {
    if (_isSafety) {
      safetyF.a = _newFactorA;
      safetyF.b = _newFactorB;
    } else {
      collatF.a = _newFactorA;
      collatF.b = _newFactorB;
    }
  }
// Solidity 0.6.12
/**
 * @dev External Function to call updateState in F1155
 */
function updateF1155Balances() public override {
    uint256 borrowBals;
    uint256 depositBals;

    // take into account all balances across providers
    uint256 length = providers.length;
    for (uint256 i = 0; i < length; i++) {
      borrowBals = borrowBals.add(IProvider(providers[i]).getBorrowBalance(vAssets.borrowAsset));
    }
    for (uint256 i = 0; i < length; i++) {
      depositBals = depositBals.add(
        IProvider(providers[i]).getDepositBalance(vAssets.collateralAsset)
      );
    }

    IFujiERC1155(fujiERC1155).updateState(vAssets.borrowID, borrowBals);
    IFujiERC1155(fujiERC1155).updateState(vAssets.collateralID, depositBals);
  }
// Solidity 0.6.12
/**
 * @dev Returns an amount to be paid as bonus for liquidation
 * @param _amount: Vault underlying type intended to be liquidated
 * @param _flash: Flash or classic type of liquidation, bonus differs
 */
function getLiquidationBonusFor(uint256 _amount, bool _flash)
    external
    view
    override
    returns (uint256)
  {
    if (_flash) {
      // Bonus Factors for Flash Liquidation
      (uint64 a, uint64 b) = _fujiAdmin.getBonusFlashL();
      return _amount.mul(a).div(b);
    } else {
      //Bonus Factors for Normal Liquidation
      (uint64 a, uint64 b) = _fujiAdmin.getBonusLiq();
      return _amount.mul(a).div(b);
    }
  }
// Solidity 0.6.12
/**
 * @dev Returns the amount of collateral needed, including or not safety factors
 * @param _amount: Vault underlying type intended to be borrowed
 * @param _withFactors: Inidicate if computation should include safety_Factors
 */
function getNeededCollateralFor(uint256 _amount, bool _withFactors)
    public
    view
    override
    returns (uint256)
  {
    // Get price of DAI in ETH
    (, int256 latestPrice, , , ) = oracle.latestRoundData();
    uint256 minimumReq = (_amount.mul(1e12).mul(uint256(latestPrice))).div(_BASE);

    if (_withFactors) {
      return minimumReq.mul(collatF.a).mul(safetyF.a).div(collatF.b).div(safetyF.b);
    } else {
      return minimumReq;
    }
  }
// Solidity 0.5.15
// The nft value & risk group is to be updated by authenticated oracles
function update(bytes32 nftID_, uint value, uint risk_) public auth {
        // the risk group has to exist
        require(thresholdRatio[risk_] != 0, "threshold for risk group not defined");

        // switch of collateral risk group results in new: ceiling, threshold and interest rate for existing loan
        // change to new rate interestRate immediately in pile if loan debt exists
        uint loan = shelf.nftlookup(nftID_);
        if (pile.pie(loan) != 0) {
            pile.changeRate(loan, risk_);
        }
        risk[nftID_] = risk_;
        nftValues[nftID_] = value;
    }
// Solidity 0.5.15
// function checks if the borrow amount does not exceed the max allowed borrow amount (=ceiling)
function borrow(uint loan, uint amount) external auth returns (uint) {
        // increase borrowed amount -> note: max allowed borrow amount does not include accrued interest
        borrowed[loan] = safeAdd(borrowed[loan], amount);

        require(currentCeiling(loan) >= borrowed[loan], "borrow-amount-too-high");
        return amount;
    }
// Solidity 0.5.15
// borrowEvent is called by the shelf in the borrow method
function borrowEvent(uint loan) public auth {
        uint risk_ = risk[nftID(loan)];

        // when issued every loan has per default interest rate of risk group 0.
        // correct interest rate has to be set on first borrow event
        if(pile.loanRates(loan) != risk_) {
            // set loan interest rate to the one of the correct risk group
            pile.setRate(loan, risk_);
        }
    }
// Solidity 0.5.15
/// maturityDate is a unix timestamp
function file(bytes32 name, bytes32 nftID_, uint maturityDate_) public auth {
        // maturity date only can be changed when there is no debt on the collateral -> futureValue == 0
        if (name == "maturityDate") {
            require((futureValue[nftID_] == 0), "can-not-change-maturityDate-outstanding-debt");
            maturityDate[nftID_] = uniqueDayTimestamp(maturityDate_);
        } else { revert("unknown config parameter");}
    }
// Solidity 0.5.15
// On borrow: the discounted future value of the asset is computed based on the loan amount and addeed to the bucket with the according maturity Date
function _borrow(uint loan, uint amount) internal returns(uint navIncrease) {
        // ceiling check uses existing loan debt
        require(ceiling(loan) >= safeAdd(borrowed[loan], amount), "borrow-amount-too-high");

        bytes32 nftID_ = nftID(loan);
        uint maturityDate_ = maturityDate[nftID_];
        // maturity date has to be a value in the future
        require(maturityDate_ > block.timestamp, "maturity-date-is-not-in-the-future");

        // calculate amount including fixed fee if applicatable
        (, , , , uint fixedRate) = pile.rates(pile.loanRates(loan));
        uint amountIncludingFixed =  safeAdd(amount, rmul(amount, fixedRate));
        // calculate future value FV
        uint fv = calcFutureValue(loan, amountIncludingFixed, maturityDate_, recoveryRatePD[risk[nftID_]].value);
        futureValue[nftID_] = safeAdd(futureValue[nftID_], fv);

        // add future value to the bucket of assets with the same maturity date
        if (buckets[maturityDate_].value == 0) {
            addBucket(maturityDate_, fv);
        } else {
            buckets[maturityDate_].value = safeAdd(buckets[maturityDate_].value, fv);
        }

        // increase borrowed amount for future ceiling computations
        borrowed[loan] = safeAdd(borrowed[loan], amount);

        // return increase NAV amount
        return calcDiscount(fv, uniqueDayTimestamp(block.timestamp), maturityDate_);
    }
// Solidity 0.5.15
// calculate the future value based on the amount, maturityDate interestRate and recoveryRate
function calcFutureValue(uint loan, uint amount, uint maturityDate_, uint recoveryRatePD_) public returns(uint) {
        // retrieve interest rate from the pile
        (, ,uint loanInterestRate, ,) = pile.rates(pile.loanRates(loan));
        return rmul(rmul(rpow(loanInterestRate, safeSub(maturityDate_, uniqueDayTimestamp(now)), ONE), amount), recoveryRatePD_);
    }
// Solidity 0.5.15
/// update the nft value and change the risk group
function update(bytes32 nftID_, uint value, uint risk_) public auth {
        nftValues[nftID_] = value;

        // no change in risk group
        if (risk_ == risk[nftID_]) {
            return;
        }

        // nfts can only be added to risk groups that are part of the score card
        require(thresholdRatio[risk_] != 0, "risk group not defined in contract");
        risk[nftID_] = risk_;

        // no currencyAmount borrowed yet
        if (futureValue[nftID_] == 0) {
            return;
        }

        uint loan = shelf.nftlookup(nftID_);
        uint maturityDate_ = maturityDate[nftID_];

        // Changing the risk group of an nft, might lead to a new interest rate for the dependant loan.
        // New interest rate leads to a future value.
        // recalculation required
        buckets[maturityDate_].value = safeSub(buckets[maturityDate_].value, futureValue[nftID_]);

        futureValue[nftID_] = calcFutureValue(loan, pile.debt(loan), maturityDate[nftID_], recoveryRatePD[risk[nftID_]].value);
        buckets[maturityDate_].value = safeAdd(buckets[maturityDate_].value, futureValue[nftID_]);
    }
// Solidity 0.5.15
// In case of successful repayment the approximatedNAV is decreased by the repaid amount
function repay(uint loan, uint amount) external auth returns (uint navDecrease) {
        navDecrease = _repay(loan, amount);
        if (navDecrease > approximatedNAV) {
            approximatedNAV = 0;
        }

        if(navDecrease < approximatedNAV) {
            approximatedNAV = safeSub(approximatedNAV, navDecrease);
            return navDecrease;
        }

        approximatedNAV = 0;
        return navDecrease;
    }