--- 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; } } ```