---
# System prepended metadata

title: Nextlend doc
tags: [AIS]

---

---
tags: AIS
---

# Nextlend doc

```solidity
contract cToken {
    
    // To construct cToken which contains lending logic
    // @param name - name of cToken
    // @param symbol - symbol of cToken
    // @param decimals - decimals of cToken
    // @param underlying - underlying token address
    // @param initialExchangeRateMantissa - initial value of mantiss(TODO: describe more)
    constructor(string memory name, string memory symbol, uint8 decimals, address underlying, uint256 initialExchangeRateMantissa);
    
    // To connect another CToken Together
    // @param address - address of another cToken that need to be added to market
    // @return success status which always be true
    function addToMarket(address CTokenAddress) external returns(bool);
    
    // To disconnect another CToken from market
    // @param address - address of another cToken that need to be removed from market
    // @return success status which always be true
    function removeFromMarket(address CTokenAddress) external returns(bool);
    
    // To get market list
    // @return market list
    function readMarket() external view returns(address [] memory)
    
    // Set token for incentive reward
    // @param address - token address to be used as incentive
    // @return success status
    function setCompAddr(address newCompAddr) external returns(bool)

    // Mint some token to contract
    // @param mintAmount - amount of token to mint which have to be smaller or equal to aproval
    // @return - sucess status or exceptions
    function mint(uint256 mintAmount) external returns (bool)
    
    // Redeem some amount of token
    // @param redeemTokens - amount to redeem
    // @return - success status
    function redeem(uint256 redeemTokens) external returns (bool){
        
        require(checkApproveCToken(msg.sender,redeemTokens));
        uint256 underlyingToken = redeemTokens.div(getExchangeRate());
        require(checkUnderlyingToken(underlyingToken));
        require(checkAmountCToken(msg.sender,redeemTokens));
        require(
            getAllLiquidity(msg.sender).add((balances[msg.sender].sub(redeemTokens)).mul(getPrice()))*80/100 >= getAllBorrow(msg.sender)
        );
        
        tokenContract.transfer(msg.sender,underlyingToken);
        
        calculateComp_redeem(balances[msg.sender]);

        balances[msg.sender] = balances[msg.sender].sub(redeemTokens);
        totalSupply_ = totalSupply_.sub(redeemTokens);
        
        
        return true;
    }
    
    function redeemUnderlying(uint256 redeemTokens) external returns (bool){
        
        require(checkApprove(msg.sender,redeemTokens)); 
        uint256 cTokenAmount = redeemTokens.mul(getExchangeRate());
        require(checkUnderlyingToken(redeemTokens));
        require(checkAmountCToken(msg.sender,cTokenAmount));
        
        tokenContract.transfer(msg.sender,redeemTokens);

        calculateComp_redeem(balances[msg.sender]);

        balances[msg.sender] = balances[msg.sender].sub(cTokenAmount);
        totalSupply_ = totalSupply_.sub(cTokenAmount);
        
        
        return true;
       
    }
    
    
    
    function calculateComp_mint(uint256 mintAmount) internal returns(bool){
        uint256 CompAmount = calculateComp(startBlock[msg.sender],mintAmount);
        Compbalances[msg.sender] = Compbalances[msg.sender].add(CompAmount);
        uint currentblock = block.number;
        startBlock[msg.sender] = currentblock;
        
        return true;
        
        
    }
    
    function calculateComp_redeem(uint256 redeemAmount) internal returns(bool){
        CompContract.transfer(msg.sender,(calculateComp(startBlock[msg.sender],redeemAmount)).div(1e18));
        Compbalances[msg.sender] = Compbalances[msg.sender].sub(calculateComp(startBlock[msg.sender],redeemAmount));
        startBlock[msg.sender] = block.number;
        
        return true;
        
    }

    // To claim reward without withdrawing
    function ClaimComp() external returns (bool){
        if (balances[msg.sender]!=0){
            calculateComp_redeem(balances[msg.sender]);
         }
         else{
             if (borrowBalance[msg.sender]!=0){
                 calculateComp_repay(borrowBalance[msg.sender]);
                 }
             
         }
        
        return true;
    }

    // To get claimable reward
    function getAvailableComp(address account) external view returns(uint256){
        if (balances[account]!=0){
            return (calculateComp(startBlock[account],balances[account])).div(1e18);
           
        }
        else{
            if (borrowBalance[account]!=0){
                return (calculateComp(borrowStartBlock[account],borrowBalance[account].mul(50))).div(1e18);
            }
            else{
                return 0;
            }
        }
      
    }
    

    function setCToken(address CTokenAddress) external{
        pairCToken_ = CTokenAddress;
        CTokenContract = cTokenInterface(CTokenAddress);
    }
    
    // Borrow money form CToken
    function borrow(uint256 borrowAmount) external returns (bool){
        
        require(balances[msg.sender]==0);
        require(
            
           
            getAllLiquidity(msg.sender)*80/100 >= getAllBorrow(msg.sender).add((borrowBalance[msg.sender].add(borrowAmount)).mul(getPrice()*50))
            
            ); 
            
        tokenContract.transfer(msg.sender,borrowAmount);
        borrowBalance[msg.sender] = borrowBalance[msg.sender].add(borrowAmount);
        calculateComp_borrow(borrowAmount);
        return true;
    }

    // Repay money to CToken
    function repayBorrow(uint256 repayAmount) external returns (bool){
        require(AllowRepayBorrow(msg.sender,repayAmount));
        
        tokenContract.transferFrom(msg.sender,address(this),repayAmount);
        calculateComp_repay(repayAmount);
        borrowBalance[msg.sender] = borrowBalance[msg.sender].sub(repayAmount);
        
        return true;
    }
    
    function calculateComp_borrow(uint256 borrowAmount) internal returns(bool){
        
        uint256 CompAmount = calculateComp(borrowStartBlock[msg.sender],borrowAmount.mul(50));
        borrowCompbalances[msg.sender] = borrowCompbalances[msg.sender].add(CompAmount);
        uint currentblock = block.number;
        borrowStartBlock[msg.sender] = currentblock;
        
        return true;
    }
    
     function calculateComp_repay(uint256 repayAmount) internal returns(bool){
         
        
        CompContract.transfer(msg.sender,(calculateComp(borrowStartBlock[msg.sender],repayAmount.mul(50))).div(1e18));
        borrowCompbalances[msg.sender] = borrowCompbalances[msg.sender].sub(calculateComp(borrowStartBlock[msg.sender],repayAmount.mul(50)));
        borrowStartBlock[msg.sender] = block.number;
        
        return true;
        
    }
    function getAllLiquidity(address account) internal view returns(uint256){
        cTokenInterface ctokenContract;
        uint256 TotalLiquidity;
        
       
        for (uint i = 0;i < MarketList.length;i++){
            
            ctokenContract = cTokenInterface(MarketList[i]);
            TotalLiquidity = TotalLiquidity.add(ctokenContract.liquidityOf(account));
            
           }
    
        return TotalLiquidity;
    }


    function getAllBorrow(address account) internal view returns(uint256){
        cTokenInterface ctokenContract;
        uint256 TotalBorrow;
        
        for (uint i = 0;i < MarketList.length;i++){
            
            ctokenContract = cTokenInterface(MarketList[i]);
            TotalBorrow = TotalBorrow.add(ctokenContract.borrowOf(account));
            
           }
           return TotalBorrow;
    }
    
    
    function AllowRepayBorrow(address account, uint256 repayAmount) internal view returns(bool){
        if (repayAmount > borrowBalance[account]){
            return false;
        }
        else{
            return true;
        }
    }

    
    
    // check & set OraclePriceFeed
    function setOraclePrice(address OracleAddress) external returns(address){
        require(msg.sender == admin_);
        OraclePriceFeed_ = OracleAddress;
    }
    
    function checkOraclePriceFeed() internal view returns(bool){
        if (OraclePriceFeed_ == address(0)){
            return false;
        }
        else{
            return true;
        }
    }
    
    // Set fixed price for CToken
    function setPrice(uint index) external {
        require(msg.sender == admin_);
        //WBTC
        if (index == 1){
            price_ = 48000 * 1e9 / 50   ;    
        }
        //WETH
        else if (index == 2){
            price_ = 3800 * 1e9 / 50;
        }
        //NXC
        else if (index == 3){
            price_ = 3 * 1e9 / 50;
        }
        //NXN
        else if (index == 4){
            price_ = 0.03 * 1e9 / 50;
        }
        //USDT
        else{
            price_ = 1 * 1e9 / 50;
        }
    }

    function getPrice() public override view returns(uint256){
        // This is price for CToken.
        
        if (!checkOraclePriceFeed()){
            return price_;
        }
        else{
            oraclePricefeedInterface oraclePriceContract = oraclePricefeedInterface(OraclePriceFeed_);
            return oraclePriceContract.getPrice();
        }
    }
    
    function admin() external view returns (address){
        return admin_;
    }
    
    // Set Comp distribution speed
    function setCompSpeed(uint256 CompSpeed) external{
        require(msg.sender == admin_);
        CompSpeed_ = CompSpeed;
    }
    function getCompSpeed() external view returns(uint256){
        return CompSpeed_;
    }
    function check(address account) external view returns(uint256){
        return calculateComp(startBlock[account],balances[account]).div(1e18);
    }

    function getAmountNXC(uint256 blocks,uint256 amount) external view returns(uint256){
        return amount.mul(getPrice()).mul(CompSpeed_).mul(blocks).div(1e9);
    }

    function getBlock() external view returns(uint256){
        return block.number;
    }
    
    function calculateComp(uint initialblock,uint256 tokenAmount) internal view returns(uint256){
        
        uint256 currentblock = block.number;
        uint256 lengthPeriod = currentblock.sub(initialblock);
        uint256 rate = (tokenAmount.mul(getPrice())).mul(CompSpeed_);
        uint256 CompAmount = lengthPeriod.mul(rate);
        
        return CompAmount;
        
    }
    
   
    
    event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
    event Transfer(address indexed from, address indexed to, uint tokens);


    mapping(address => uint256) balances;
    mapping(address => mapping (address => uint256)) allowed;
    mapping(address => uint256) Compbalances;
    mapping(address => uint) startBlock;
    
    mapping(address => uint) borrowStartBlock;
    mapping(address => uint256) borrowCompbalances;
    
    mapping(address => uint256) liquidity;
    mapping(address => uint256) borrowBalance;
   
    
    

    function borrowOf(address borrower) public override view returns (uint256){
        return (borrowBalance[borrower].mul(getPrice()*50));
        
        
    }

    function liquidityOf(address account) public override view returns (uint256){
        return (balances[account].mul(getPrice()));
    }
    
    
    function totalSupply() public override view returns (uint256) {
        return totalSupply_;
    }

    function balanceOf(address tokenOwner) public override view returns (uint256) {
        return balances[tokenOwner];
    }

    function transfer(address receiver, uint256 numTokens) public override returns (bool) {
        require(numTokens <= balances[msg.sender]);
        balances[msg.sender] = balances[msg.sender].sub(numTokens);
        balances[receiver] = balances[receiver].add(numTokens);
        emit Transfer(msg.sender, receiver, numTokens);
        return true;
    }

    function approve(address delegate, uint256 numTokens) public override returns (bool) {
        allowed[msg.sender][delegate] = numTokens;
        emit Approval(msg.sender, delegate, numTokens);
        return true;
    }

    function allowance(address owner, address delegate) public override view returns (uint) {
        return allowed[owner][delegate];
    }

    function transferFrom(address owner, address buyer, uint256 numTokens) public override returns (bool) {
        require(numTokens <= balances[owner]);
        require(numTokens <= allowed[owner][msg.sender]);

        balances[owner] = balances[owner].sub(numTokens);
        allowed[owner][msg.sender] = allowed[owner][msg.sender].sub(numTokens);
        balances[buyer] = balances[buyer].add(numTokens);
        emit Transfer(owner, buyer, numTokens);
        return true;
    }
    
}


```