Programming Project - Phase 2

Haven’t review the contracts yet, but would be awesome to have a readme with some few instructions or description about the project.

Something like this: https://github.com/Ivan-on-Tech-Academy/chainlink_lottery_truffle

Would give it a more professional look to the repository :nerd_face:

Carlos Z

1 Like

Hey Carlos actually thanks very much for mentioning that. I actually did write a read me with instructions. I only realised after seeing your message just now that its on the wrong branch wouldnt have realised otherwise. My main branch is the chainLink oracle branch which is not the main branch i should probably reorder that. gonna include the read me in the chainlink branch now

Nice repo also is that from the chainlink course?

1 Like

Yes, basically is the last lesson of the course, the solution for the lottery contract :slight_smile:

Carlos Z

1 Like

Great I may take that course soon. Still so much to do lol

Hey @mcgrane5

I cannot find any major bug in your code, well done. Just use safemath as the vrf contracts compiles in Sol 0.6

Good job

1 Like

hey @filip pls help me check this my contract it keeps giving me paser error, saying : ParserError: Expected ‘(’ but got identifier
–> project:/contracts/LoanEngine.sol:118:18:
|
118 | function getIdentifier(uint256 index) public view returns (bytes32){

below is the code :
| `// SPDX-License-Identifier: MIT
pragma solidity 0.8.9;

import “State.sol”;
import “node_modules/@openzeppelin/contracts/acesss/ownable.sol”;
import “node_modules/@openzeppelin/contracts/interfaces/IERC20.sol”;

contract p2plending {

/*//Just Chainlink things
address private oracle = 0x2f90A6D021db21e1B2A077c5a37B3C7E75D15b7e;
bytes32 private jobId = “29fa9aa13bf1468788b7cc4a500a45b8”;
uint256 private fee = 0.1 * 10 ** 18; // 0.1 LINK
*/
enum Status { initial, lent, paid, destroyed }
Status status;
Status constant defaultStatus = Status.initial;

struct Approbation {
    bool approved;
    bytes data;
    bytes32 checksum;
}



struct loan {
    Status status;
    address lender;
    address borrower;
   // address IERC20; //collateral and loan token

    bytes32 chainlinkRequestId; 

    uint256 amount;
    uint256 interest;
    uint256 punitoryInterest;
    uint256 interestTimeStamp;
    uint256 paid;
    uint256 interestRate;
    uint256 interestRatePunitory;
    uint256 dueTime;
    uint256 DuesIn;  
    
     address ERC20Token; //collateral and loan token
     uint256 cancelableAt;
     uint256 lenderBalance;
     uint256 expirationRequest;

     mapping(address => bool) approbations;
} 

//Two mappings. One to get the loans for a user. And the other to get the the loans based off id
// mapping(uint256 => loan) public loanLookup;
// mapping(address => uint256[]) public loanIDs;
mapping(bytes32 => uint256) public identifierToIndex;
Loan[] private loans;

// mapping(bytes32 => bytes32) public merkleRoots;


 function configureNew(
// _erc20, // contract address of the  token used for payment
address _borrower,
address _IERC20, 
uint256 _amount, 
uint256 _interestRate, 
uint256 _interestRatePunitory, 
uint256 _duesIn, 
uint256 _cancealableAt,
uint256 _expirationRequest

// string memory _metadata
)
public
returns(uint256)
{
require(!deprecated);
require(_cancealableAt <= duesIn);
// require(address( oracle));
require(_borrower != address(0));
require(_amount != 0);
require(_interstRatePunitory != 0);
require(_interestRate != 0);
require(_expirationRequest > block.timestamp);

    Loan memory loan = loan(  
     Status.initial,
     address(0), //lender
     msg.sender, // borrower
     _IERC20, //collateral and loan token

     0x0,

     _amount,
     0,
     0,
     0,
     0,
     _interestRate,
     _interestRatePunitory,
     0,
     _DuesIn,  

      _cancelableAt,
      0,
      _expirationRequest
    );  

    uint256 index = loans.push(loan) -1;
    emit configureNew(index, _borrower);

    bytes32 identifier = getIdentifier(index);
    require(identifierToIndex[identifier] == 0);
    identifierToIndex[identifier] = index;
     return index; 

    function getIdentifier(uint256 index) public view returns (bytes32){
         Loan memory loan = loans[index];
         return buildIdentifier(loan.borrower, loan.IERC20, loan.amount, loan.interestRate, loan.interestRatePunitory, loan.duesIn, loan.cancelableAt, loan.expirationRequest
         
         );
   }
     
    function buildIdentifier(address borrower, address IERC20, uint256 amount, uint256 interestRate,  uint256 interestRatePunitory, uint256 duesIn, uint256 cancelableAt, uint256 expirationRequest) public view returns(bytes32) {
     return keccak256(
         abi.encode(
             this,
             borrower,
             IERC20,
             amount,
             interestRate
             interestRatePunitory
             duesIn,
             cancelableAt,
             expirationRequest

         )
     );
 }

function isApproved(uint256 index) public view returns(bool) {
Loan storage loan = loans[index];
return loan.approbations[loan.borrower];
//require(loan.issued == issued: false);

}

function approveLoan(uint256 index) public view returns (bool) {
Loan storage loan = loan[index];
require(loan.status == Status.initial);
loan.approbations[msg.sender] = true;
emit ApprovedBy(index, msg.sender);
return true;
}

function approveLoanIdentifier(bytes32 identifier) public returns (bool) {
uint256 index = identifierToIndex[identifier];
require(index != 0);
return approveLoan(index);
}

function lend(uint256 index) public returns (bool) {
Loan storage loan =loans[index];

   require(loan.status == Status.initial);
   require(isApproved(index));
   require(block.timestamp <= loan.expirationRequest);
   

   loan.lender = msg.sender;
   loan.dueTime = safeAdd(block.timestamp, loan.duesIn);
   loan.interestTimeStamp = block.timestamp;
   loan.issued = issued:true;

   emit Transfer(loan.lender, index);
   ativeLoans += 1;
   lendersBalance[loan.lender] += 1;

   
    if (loan.cancelableAt > 0)
        internalAddInterest(loan, safeAdd(block.timestamp, loan.cancelableAt));

    // Transfer the money to the borrower 
    uint256 transferValue = isApproved(uint256 index);
     //convertRate(loan.oracle, loan.currency, oracleData, loan.amount);
    require(IERC20.transferFrom(msg.sender, loan.borrower, transferValue));
     
      emit Lent(index, loan.lender);
   
   return true;

}

 // destroy a loan request if not needed anymore.

function destroy(uint index) public returns (bool) {
    Loan storage loan = loans[index];
    require(loan.status != Status.destroyed);
    require(msg.sender == loan.lender || (msg.sender == loan.borrower && loan.status == issued:false));
    emit DestroyedBy(index, msg.sender);

    // ERC721, remove loan from circulation
    if (loan.status != issued:false) {
        lendersBalance[loan.lender] -= 1;
        activeLoans -= 1;
        emit Transfer(loan.lender, index);
    }

    loan.status = Status.destroyed;
    return true;
}
 


 /**
    @notice Returns the pending amount to complete de payment of the loan, keep in mind that this number increases
    every second.
    @dev This method also computes the interest and updates the loan
    @param index Index of the loan
    @return Aprox pending payment amount
*/
function getPendingAmount(uint index) public returns (uint256) {
    addInterest(index);
    return getRawPendingAmount(index);
}   

/**
    @notice Returns the pending amount up to the last time of the interest update. This is not the real pending amount
    @dev This method is exact only if "addInterest(loan)" was before and in the same block.
    @param index Index of the loan
    @return The past pending amount
*/
function getRawPendingAmount(uint index) public view returns (uint256) {
    Loan memory loan = loans[index];
    return safeSubtract(safeAdd(safeAdd(loan.amount, loan.interest), loan.punitoryInterest), loan.paid);
}

/**
    @notice Calculates the interest of a given amount, interest rate and delta time.
    @param timeDelta Elapsed time
    @param interestRate Interest rate expressed as the denominator of 10 000 000.
    @param amount Amount to apply interest
    @return realDelta The real timeDelta applied
    @return interest The interest gained in the realDelta time
*/
function calculateInterest(uint256 timeDelta, uint256 interestRate, uint256 amount) internal pure returns (uint256 realDelta, uint256 interest) {
    if (amount == 0) {
        interest = 0;
        realDelta = timeDelta;
    } else {
        interest = safeMult(safeMult(10000, amount), timeDelta) / interestRate;
        realDelta = safeMult(interest, interestRate) / (amount * 10000);
    }
}

/**
    @notice Computes loan interest
    Computes the punitory and non-punitory interest of a given loan and only applies the change.
    @param loan Loan to compute interest
    @param timestamp Target absolute unix time to calculate interest.
*/
function internalAddInterest(Loan storage loan, uint256 timestamp) internal {
    if (timestamp > loan.interestTimestamp) {
        uint256 newInterest = loan.interest;
        uint256 newPunitoryInterest = loan.punitoryInterest;

        uint256 newTimestamp;
        uint256 realDelta;
        uint256 calculatedInterest;

        uint256 deltaTime;
        uint256 pending;

        uint256 endNonPunitory = min(timestamp, loan.dueTime);
        if (endNonPunitory > loan.interestTimestamp) {
            deltaTime = endNonPunitory - loan.interestTimestamp;

            if (loan.paid < loan.amount) {
                pending = loan.amount - loan.paid;
            } else {
                pending = 0;
            }

             
            (realDelta, calculatedInterest) = calculateInterest(deltaTime, loan.interestRate, pending);
            newInterest = safeAdd(calculatedInterest, newInterest);
            newTimestamp = loan.interestTimestamp + realDelta;
        }

        if (timestamp > loan.dueTime) {
            uint256 startPunitory = max(loan.dueTime, loan.interestTimestamp);
            deltaTime = timestamp - startPunitory;

            uint256 debt = safeAdd(loan.amount, newInterest);
            pending = min(debt, safeSubtract(safeAdd(debt, newPunitoryInterest), loan.paid));

            (realDelta, calculatedInterest) = calculateInterest(deltaTime, loan.interestRatePunitory, pending);
            newPunitoryInterest = safeAdd(newPunitoryInterest, calculatedInterest);
            newTimestamp = startPunitory + realDelta;
        }

        if (newInterest != loan.interest || newPunitoryInterest != loan.punitoryInterest) {
            loan.interestTimestamp = newTimestamp;
            loan.interest = newInterest;
            loan.punitoryInterest = newPunitoryInterest;
        }
    }
}

/**
@notice Updates the loan accumulated interests up to the current Unix time.
@param index Index of the loan
@return true If the interest was updated
*/
function addInterest(uint index) public returns (bool) {
Loan storage loan = loans[index];
require(loan.status == Status.lent);
internalAddInterest(loan, block.timestamp);
}

 /*=========borrower pay up loan=========*/

  function pay(uint index, uint256 _amount, address _from) public returns (bool) {
    Loan storage loan = loans[index];

    require(loan.status == issued:true);
    addInterest(index);
    uint256 toPay = min(getPendingAmount(index), _amount);
    emit PartialPayment(index, msg.sender, _from, toPay);

    loan.paid = safeAdd(loan.paid, toPay);

    if (getRawPendingAmount(index) == 0) {
        emit TotalPayment(index);
        loan.status = Status.paid;

        // ERC721, remove loan from circulation
        lendersBalance[loan.lender] -= 1;
        activeLoans -= 1;
        emit Transfer(loan.lender address(0), index);
    }

    uint256 transferValue = convertRate( loan.ERC20Token, toPay);
    require(transferValue > 0 || toPay < _amount);

    lockTokens(address(IERC20), transferValue);
    require(IERC20.transferFrom(msg.sender, address(this), transferValue));
    loan.lenderBalance = safeAdd(transferValue, loan.lenderBalance);

    return true;
}


}`

pls fam help me check what could be wrong here and why i m getting error…thanks fam.

1 Like

yo g you need to post the code properly its hard to read. Re-edit the post and ill have a look. the error messag etells you evrything here it seems you have a syntax error you have are missing a bracket on line 118