X2Y2 contract
LoanStatus.sol
// SPDX-License-Identifier: BUSL-1.1
 
pragma solidity 0.8.4;
 
import "./Xy3Nft.sol";
import "./interfaces/ILoanStatus.sol";
import "./interfaces/IConfig.sol";
 
/**
 * @title  LoanStatus
 * @author XY3
 */
contract LoanStatus is ILoanStatus {
 
    event UpdateStatus(
        uint32 indexed loanId,
        uint64 indexed xy3NftId,
        StatusType newStatus
    );
 
    uint32 public totalNumLoans = 10000;
    mapping(uint32 => LoanState) private loanStatus;
 
    /**
     * @dev XY3 mint a NFT to the lender as a ticket for collateral
     * @param _lender Lender address
     * @param _borrower Borrower address
     */
    function createLoan(address _lender, address _borrower) internal returns (uint32) {
        // skip 0, loanIds start from 1
        totalNumLoans += 1;
 
        uint64 xy3NftId = uint64(
            uint256(keccak256(abi.encodePacked(address(this), totalNumLoans)))
        );
 
        LoanState memory newLoan = LoanState({
            status: StatusType.NEW,
            xy3NftId: xy3NftId
        });
 
        (Xy3Nft borrowerNote, Xy3Nft lenderNote) = getNotes();
        // Mint an ERC721 to the lender as the ticket for the collateral
        lenderNote.mint(
            _lender,
            xy3NftId,
            abi.encode(totalNumLoans)
        );
 
        // Mint an ERC721 to the borrower as the ticket for the collateral
        borrowerNote.mint(
            _borrower,
            xy3NftId,
            abi.encode(totalNumLoans)
        );
 
        loanStatus[totalNumLoans] = newLoan;
        emit UpdateStatus(totalNumLoans, xy3NftId, StatusType.NEW);
 
        return totalNumLoans;
    }
 
    /**
     * @dev XY3 close the loan when load paid
     * Update the loan status to be RESOLVED and burns Xy3Nft token.
     * @param _loanId - Id of loan
     */
    function resolveLoan(uint32 _loanId) internal {
        LoanState storage loan = loanStatus[_loanId];
        require(loan.status == StatusType.NEW, "Loan is not a new one");
 
        loan.status = StatusType.RESOLVED;
        (Xy3Nft borrowerNote, Xy3Nft lenderNote) = getNotes();
        lenderNote.burn(loan.xy3NftId);
        borrowerNote.burn(loan.xy3NftId);
 
        emit UpdateStatus(_loanId, loan.xy3NftId, StatusType.RESOLVED);
        delete loanStatus[_loanId];
    }
 
    /**
     * @dev Get loan state for a given id.
     * @param _loanId The given load Id.
     */
    function getLoanState(uint32 _loanId)
        public
        view
        override
        returns (LoanState memory)
    {
        return loanStatus[_loanId];
    }
 
    function getNotes() private view returns(Xy3Nft borrowerNote, Xy3Nft lenderNote) {
        IAddressProvider addressProvider = IConfig(address(this)).getAddressProvider();
        borrowerNote = Xy3Nft(addressProvider.getBorrowerNote());
        lenderNote = Xy3Nft(addressProvider.getLenderNote());
    }
}