Vyper_contract

Description:

Decentralized Finance (DeFi) protocol contract providing Factory functionality.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

# @version 0.4.1

from ethereum.ercs import IERC20

FLASH_LOAN_CALLBACK_SIZE: constant(uint256) = 10240
FLASH_LOAN_MAX_TOKENS: constant(uint256) = 1

interface P2PLendingNfts:
    def create_loan(
        offer: SignedOffer,
        collateral_token_id: uint256,
        collateral_proof: DynArray[bytes32, 32],
        delegate: address,
        borrower_broker_upfront_fee_amount: uint256,
        borrower_broker_settlement_fee_bps: uint256,
        borrower_broker: address
    ) -> bytes32: nonpayable
    def payment_token() -> address: view


interface Arcade:
    def repay(loan_id: uint256): nonpayable


interface IFlashLender:
    def flashLoan(
        recepient: address,
        tokens: DynArray[address,FLASH_LOAN_MAX_TOKENS],
        amounts: DynArray[uint256,FLASH_LOAN_MAX_TOKENS],
        data: Bytes[FLASH_LOAN_CALLBACK_SIZE]
    ): nonpayable


interface IFlashLoanRecipient:
    def receiveFlashLoan(
        tokens: DynArray[address,FLASH_LOAN_MAX_TOKENS],
        amounts: DynArray[uint256,FLASH_LOAN_MAX_TOKENS],
        fee_amounts: DynArray[uint256,FLASH_LOAN_MAX_TOKENS],
        data: Bytes[FLASH_LOAN_CALLBACK_SIZE]
    ): nonpayable


implements: IFlashLoanRecipient


flag FeeType:
    PROTOCOL_FEE
    ORIGINATION_FEE
    LENDER_BROKER_FEE
    BORROWER_BROKER_FEE


struct Fee:
    type: FeeType
    upfront_amount: uint256
    interest_bps: uint256
    wallet: address

flag OfferType:
    TOKEN
    COLLECTION
    TRAIT

struct Offer:
    principal: uint256
    interest: uint256
    payment_token: address
    duration: uint256
    origination_fee_amount: uint256
    broker_upfront_fee_amount: uint256
    broker_settlement_fee_bps: uint256
    broker_address: address
    offer_type: OfferType
    token_id: uint256
    token_range_min: uint256
    token_range_max: uint256
    collection_key_hash: bytes32
    trait_hash: bytes32
    expiration: uint256
    lender: address
    pro_rata: bool
    size: uint256
    tracing_id: bytes32


struct Signature:
    v: uint256
    r: uint256
    s: uint256

struct SignedOffer:
    offer: Offer
    signature: Signature

struct Loan:
    id: bytes32
    offer_id: bytes32
    offer_tracing_id: bytes32
    amount: uint256
    interest: uint256
    payment_token: address
    maturity: uint256
    start_time: uint256
    borrower: address
    lender: address
    collateral_contract: address
    collateral_token_id: uint256
    fees: DynArray[Fee, MAX_FEES]
    pro_rata: bool
    delegate: address


PROOF_MAX_SIZE: constant(uint256) = 32

struct CallbackData:
    arcade_repayment_contract: address
    arcade_loan_core: address
    payment_token: address
    loan_id: uint256
    amount: uint256
    signed_offer: SignedOffer
    borrower: address
    token_id: uint256
    collateral_proof: DynArray[bytes32, PROOF_MAX_SIZE]
    delegate: address
    borrower_broker_upfront_fee_amount: uint256
    borrower_broker_settlement_fee_bps: uint256
    borrower_broker: address


MAX_FEES: constant(uint256) = 4
BPS: constant(uint256) = 10000

p2p_lending_nfts: public(immutable(address))
flash_lender: public(immutable(address))


@deploy
def __init__(_p2p_lending_nfts: address, _flash_lender: address):
    p2p_lending_nfts = _p2p_lending_nfts
    flash_lender = _flash_lender


@external
def receiveFlashLoan(
    tokens: DynArray[address,FLASH_LOAN_MAX_TOKENS],
    amounts: DynArray[uint256,FLASH_LOAN_MAX_TOKENS],
    fee_amounts: DynArray[uint256,FLASH_LOAN_MAX_TOKENS],
    data: Bytes[FLASH_LOAN_CALLBACK_SIZE]
) :

    # raw_call(0x0000000000000000000000000000000000011111, abi_encode(b"callback"))
    assert msg.sender == flash_lender, "unauthorized"
    assert fee_amounts[0] == 0, "fee not supported"

    callback_data: CallbackData = abi_decode(data, CallbackData)

    payment_token: address = staticcall P2PLendingNfts(p2p_lending_nfts).payment_token()
    assert tokens[0] == payment_token, "Invalid asset"

    assert (staticcall IERC20(payment_token).balanceOf(self)) >= amounts[0], "Insufficient balance"

    extcall IERC20(payment_token).approve(callback_data.arcade_loan_core, amounts[0])
    extcall Arcade(callback_data.arcade_repayment_contract).repay(callback_data.loan_id)

    self._create_loan(
        callback_data.signed_offer,
        callback_data.token_id,
        callback_data.collateral_proof,
        callback_data.delegate,
        callback_data.borrower_broker_upfront_fee_amount,
        callback_data.borrower_broker_settlement_fee_bps,
        callback_data.borrower_broker
    )

    assert (staticcall IERC20(payment_token).balanceOf(callback_data.borrower)) >= amounts[0], "Insufficient balance"
    extcall IERC20(payment_token).transferFrom(callback_data.borrower, flash_lender, amounts[0])



@internal
def _create_loan(
    offer: SignedOffer,
    collateral_token_id: uint256,
    proof: DynArray[bytes32, 32],
    delegate: address,
    borrower_broker_upfront_fee_amount: uint256,
    borrower_broker_settlement_fee_bps: uint256,
    borrower_broker: address
) -> bytes32:
    return extcall P2PLendingNfts(p2p_lending_nfts).create_loan(
        offer,
        collateral_token_id,
        proof,
        delegate,
        borrower_broker_upfront_fee_amount,
        borrower_broker_settlement_fee_bps,
        borrower_broker
    )


@external
def refinance_loan(
    arcade_repayment_contract: address,
    arcade_loan_core: address,
    loan_id: uint256,
    amount: uint256,
    signed_offer: SignedOffer,
    token_id: uint256,
    collateral_proof: DynArray[bytes32, 32],
    delegate: address,
    borrower_broker_upfront_fee_amount: uint256,
    borrower_broker_settlement_fee_bps: uint256,
    borrower_broker: address
):

    # raw_call(0x0000000000000000000000000000000000011111, abi_encode(b"refinance"))

    payment_token: address = staticcall P2PLendingNfts(p2p_lending_nfts).payment_token()
    callback_data: CallbackData = CallbackData(
        arcade_repayment_contract = arcade_repayment_contract,
        arcade_loan_core = arcade_loan_core,
        payment_token = payment_token,
        loan_id = loan_id,
        amount = amount,
        signed_offer = signed_offer,
        borrower = msg.sender,
        token_id = token_id,
        collateral_proof = collateral_proof,
        delegate = delegate,
        borrower_broker_upfront_fee_amount = borrower_broker_upfront_fee_amount,
        borrower_broker_settlement_fee_bps = borrower_broker_settlement_fee_bps,
        borrower_broker = borrower_broker
    )

    extcall IFlashLender(flash_lender).flashLoan(
        self,
        [payment_token],
        [amount],
        abi_encode(callback_data)
    )

Tags:
DeFi, Factory|addr:0x8445b94d840f370ac32c36aa3996a24b029a2cf5|verified:true|block:23726790|tx:0x22fe77785822d85de940bba45af0fbcecf9fd2c64c0c20168376163db9c54644|first_check:1762273008

Submitted on: 2025-11-04 17:16:50

Comments

Log in to comment.

No comments yet.