Simple Offer

1. Summary

PWNSimpleLoanSimpleOffer.sol defines Simple Offer for the Simple Loan type.

3. Contract details

  • PWNSimpleLoanSimpleOffer.sol is written in Solidity version 0.8.16

Features

  • Make Simple Offer

  • Create Simple Loan terms from Simple Offer

  • Provides a function to encode Simple Offer

Inherited contracts, implemented Interfaces and ERCs

Functions

makeOffer

Overview

Make an on-chain simple offer.

This function takes one argument supplied by the caller:

  • Offer calldataoffer - Offer struct with the simple offer parameters

Implementation

function makeOffer(Offer calldata offer) external {
    _makeOffer(getOfferHash(offer), offer.lender);
}
createLOANTerms

Overview

Builds simple loan terms from given data.

This function takes three arguments supplied by the loan type:

  • addresscaller - The caller of the createLoan function on the Loan contract

  • bytes calldatafactoryData - Encoded data for the Loan Terms factory

  • bytes calldatasignature - Singed loan factory data

Implementation

function createLOANTerms(
    address caller,
    bytes calldata factoryData,
    bytes calldata signature
) external override onlyActiveLoan returns (PWNLOANTerms.Simple memory loanTerms) {

    Offer memory offer = abi.decode(factoryData, (Offer));
    bytes32 offerHash = getOfferHash(offer);

    address lender = offer.lender;
    address borrower = caller;

    // Check that offer has been made via on-chain tx, EIP-1271 or signed off-chain
    if (offersMade[offerHash] == false)
        if (PWNSignatureChecker.isValidSignatureNow(lender, offerHash, signature) == false)
            revert InvalidSignature();

    // Check valid offer
    if (offer.expiration != 0 && block.timestamp >= offer.expiration)
        revert OfferExpired();

    if (revokedOfferNonce.isNonceRevoked(lender, offer.nonce) == true)
        revert NonceAlreadyRevoked();

    if (offer.borrower != address(0))
        if (borrower != offer.borrower)
            revert CallerIsNotStatedBorrower(offer.borrower);

    if (offer.duration < MIN_LOAN_DURATION)
        revert InvalidDuration();

    // Prepare collateral and loan asset
    MultiToken.Asset memory collateral = MultiToken.Asset({
        category: offer.collateralCategory,
        assetAddress: offer.collateralAddress,
        id: offer.collateralId,
        amount: offer.collateralAmount
    });
    MultiToken.Asset memory loanAsset = MultiToken.Asset({
        category: MultiToken.Category.ERC20,
        assetAddress: offer.loanAssetAddress,
        id: 0,
        amount: offer.loanAmount
    });

    // Create loan object
    loanTerms = PWNLOANTerms.Simple({
        lender: lender,
        borrower: borrower,
        expiration: uint40(block.timestamp) + offer.duration,
        collateral: collateral,
        asset: loanAsset,
        loanRepayAmount: offer.loanAmount + offer.loanYield
    });

    // Revoke offer if not persistent
    if (!offer.isPersistent)
        revokedOfferNonce.revokeNonce(lender, offer.nonce);
}
encodeLoanTermsFactoryData

Overview

Returns encoded input data for the loan terms factory (inherited by this contract).

This function takes one argument supplied by the caller:

  • Offer memoryoffer - Simple offer struct to encode

Implementation

function encodeLoanTermsFactoryData(Offer memory offer) external pure returns (bytes memory) {
    return abi.encode(offer);
}

View Functions

getOfferHash

Overview

Returns a simple offer hash according to EIP-712.

This function takes one argument supplied by the caller:

  • Offer memoryoffer - Simple offer struct to get hash of

Implementation

function getOfferHash(Offer memory offer) public view returns (bytes32) {
    return keccak256(abi.encodePacked(
        hex"1901",
        DOMAIN_SEPARATOR,
        keccak256(abi.encodePacked(
            OFFER_TYPEHASH,
            abi.encode(offer)
        ))
    ));
}

Events

The PWN Simple Loan Simple Offer contract inherits events from the Simple Loan Offer contract and does not define any additional custom events or errors.

Simple Offer Struct

TypeNameComment

MultiToken.Category

collateralCategory

0 -> ERC-20 1 -> ERC-721 2 -> ERC-1155

address

collateralAddress

Address of an asset used as a collateral.

uint256

collateralId

Token id of an asset used as a collateral, in case of ERC20 should be 0.

uint256

collateralAmount

Amount of tokens used as a collateral, in case of ERC721 should be 0.

address

loanAssetAddress

Address of an loaned asset.

uint256

loanAmount

Amount of tokens which is requested as a loan.

uint256

loanYield

Amount of tokens which act as a lenders loan interest. Borrower has to pay back a borrowed amount + yield.

uint32

duration

Loan duration in seconds.

uint40

expiration

Request expiration unix timestamp in seconds.

address

borrower

Address of a borrower. This address has to sign a request for it to be valid. If the address is zero address, anybody with valid collateral can accept the offer.

address

lender

Address of a lender. Only this address can accept a request. If the address is zero address, anybody with a loan asset can accept the request.

bool

isPersistent

If true, offer will not be revoked on acceptance. Persistent offer can be revoked manually.

uint256

nonce

Additional value to enable identical requests in time. Without it, it would be impossible to make a request, which was once revoked. Nonce can be used to create a group of requests, where accepting one request will make other requests in the group invalid.

Last updated