Repayment

The borrower must repay the loan before the Maturity Time to avoid liquidation by the DCA.

Recall that during Loan Assignment, BTC collateral for the loan was locked into the Collateral Vault. One of the spending conditions are a 2-of-2 multi-sig UTXO where one side is the DCA, and the other side is the Borrower, with an aggregatable adaptor signature scheme, allowing a signature from the Borrower to publicly reveal a repayment_secret.

Assuming the loan is denominated in USDC, the borrower must submit a transaction to the Lending Contract on the Side Chain that includes:

  1. A USDC transfer from the Borrower to the Lending Contract to repay the loan principal and interest.

  2. A partially signed Bitcoin transaction to withdraw the BTC collateral

The repaid USDC funds are secured in a Repayment Escrow on the Side Chain, using a hash of a randomly generated repayment_secret from the borrower. Anyone who provides the pre-image of this hash can transfer the funds from the Repayment Escrow back to the liquidity pool.

The USDC repayment is subject to a timelock (e.g., 24 hours). If the loan repayment is not completed before the timelock expires, the transaction will be automatically canceled, and the funds will be returned to the Borrower.

let borrower_signature = sign_partial(
        agg_pubkey, 
        sec_key,
        repayment_adaptor_point, 
        message
);

function lock_repayment(hash_of_repayment_secret) {
	 loan.repayment_hash_lock = hash_of_repayment_secret
}

The Lending Contract verifies the repayment and produces a SignRequest. The DCA then fetches and partially signs the adaptor signature of the Bitcoin transaction and submits it to the Lending Contract. The contract aggregates these partial signatures from both the borrower and the DCA into an aggregated signature.

let valid = verify_partial(
        agg_pubkey, 
        borrower_pubkey,
        borrower_signature, 
        repayment_adaptor_point, 
        message,
);

let dca_partial_signature = sign_partial(
        agg_pubkey, 
        repayment_adaptor_point, 
        message
~~~~);

~~~~let adaptor_signature = aggregate_partial_signatures(
        agg_pubkey,
        repayment_adaptor_point,
        [borrower_signature, dca_partial_signature],
        message,
)

The borrower can adapt the withdrawal signature from the aggregated adaptor signature with their repayment_secret and broadcast the withdrawal signature on the Bitcoin chain to reclaim their BTC collateral.

verify_single(
    agg_pubkey,
    adaptor_signature,
    message,
    adaptor_point,
)
.expect("invalid aggregated adaptor signature");

let collateral_withdrawal_signature = adaptor_signature.adapt(repayment_secret);

Once the signature is broadcast on Bitcoin, anyone can extract the repayment_secret from the Bitcoin collateral withdrawal to move funds from the Repayment Escrow to the liquidity pool. This is then verified by the contract:

let repayment_secret = adaptor_signature.reveal_secret(collateral_withdrawal_signature);
if (sha256(usdc_repayment_secret) == loan.repayment_hash_lock) {
    // send funds to liquidity pool
}

Last updated