# Edge Cases and Risk Situations

In this section, we explain some edge cases and risk situations, whether they are managed and covered automatically, and what the procedure is case by case.

Attack vectors mainly focus around the risk to Lenders' deposits, there are also risks to consider for Borrowers too.

<details>

<summary>Negative Impact of Whitelisted functions on the Spigot</summary>

*related to updateWhitelist(), updateWhitelistedFunction() and operate()*

**Attack Vector**

A bad actor could propose a whitelisted function that affects the normal functioning of the Spigot

**Background Information**

Whitelisted functions are those allowed to be performed on a Revenue contract so that the Operator (Borrower) can still use the contract whilst providing Revenue Tokens to repay debt.

**Mitigation Strategies**

Only whitelisted functions can be called by an Operator on the Revenue Contract.

operate() can only work on Revenue Contracts authorised by the Spigot Owner

The Spigot Owner has verified the function logic of the whitelisted function and ensured that they poses no risk to the Spigot’s functionality

</details>

<details>

<summary>Upgradeable Revenue Contract</summary>

**Attack Vector**

A Borrower could upgrade the Revenue Contract securing the Line of Credit.

They could change the underlying logic of the already whitelisted functions.

They could create new functions with the same function signatures.

Either of these can cause the Spigot to lose control of the underlying Revenue Contract(s) and to not be able to claim Revenue Tokens.

**Mitigation Strategies**

Spigot Owners should only consider immutable smart contracts as candidates to be Revenue Contracts

</details>

<details>

<summary>Attack on Revenue Contract</summary>

**Attack Vector**

A Spigot could be deployed that has been approved for transferring Revenue Tokens to a malicious contract

**Mitigation Strategies**

Although this is mitigated by only letting the Owner add Revenue Contracts to a Spigot it could still be susceptible to social engineering.

<img src="/files/L5MfvoIdkXYabQtduSeU" alt="" data-size="original">

</details>

<details>

<summary>Intentional Default by Borrower</summary>

**Attack Vector**

A Borrower could try to take out a loan partly secured by a Revenue Contract that they intend to deprecate or which they know won't make enough revenue to repay the loan with the agreed revenue split.

**Mitigation Strategies**

To ensure repayment to a Borrower’s full ability, the Spigot will automatically switch to escrowing 100% of Revenue Tokens if the loan is past due or if the spot value of any collateral becomes too low.

It is also theoretically possible to repossess a Borrower's entire protocol using contracts controlled by the Spigot and sell it off to an investment DAO or related protocol DAO to repay Lenders.

</details>

<details>

<summary>Malicious Spigot Owner</summary>

**Attack Vector**

A Spigot Owner could be configured to retain ownership of Revenue Contracts even though all debt has been repaid

**Mitigation Strategies**

Before giving control of a Revenue Contract to a Spigot, a Borrower should ensure that the Owner is a smart contract with the proper functions in place to later return ownership as and when appropriate.

The Owner should not be an EOA and if it is a smart contract that is not a Line of Credit contract then a Borrower should ensure it is verified on etherscan and has smart contract audits specifically related to those functions related to a Spigot integration.

</details>

<details>

<summary>Borrower Trading Revenue Tokens for a Fake Credit Token</summary>

**Attack Vector**

Borrower creates a fake credit token and creates an LP pool with the fake credit token and a second token in which they earn revenue in (use ETH for simplicity). Pool has really high ETH price so they don’t need a lot of ETH to initiate an attack.

When calling claimAndRepay(), they trade the Revenue Tokens (ETH) into the fake credit token that they created allowing them to capture the value instead of Lenders being repaid.

**Mitigation strategies**

The Credit Tokens into which Revenue Tokens are converted are selected automatically according to the first position in the repayment queue. This way the acquired Credit Tokens will always be those which a Lender has deposited.

0x (the DEX we’re using) generally doesn’t support illiquid and/or unknown tokens

0x only allows 1 <>1 token trading so it can’t trade a tiny amount of the Revenue tokens into Credit Token and the rest to the fake token. It must trade all Revenue tokens into Credit Tokens\
\
A further mitigation strategy implemented is limit access to the Arbiter for claimAndTrade() and claimAndRepay().

</details>

<details>

<summary>Abuse of Split of Revenue Tokens from a Spigot</summary>

*related to updateOwnerSplit()*

**Attack Vector**

In a Spigoted Line of Credit, the updateOwnerSplit() function could be abused by the Borrower or the Lender.

If the ownerSplit parameter is set below the defaultRevenueSplit parameter, the Lender could call it to increase the split percentage which would lead to more Revenue Tokens being used to pay off the debt more quickly.

If the ownerSplit parameter is set above the defaultRevenueSplit parameter, the Borrower could call it to decrease the split percentage. This would lead to less revenue being used to pay off the debt, and more revenue would return to the Borrower’s Treasury.

No authorization check is implemented for who can call this function.

**Mitigation Strategies**

Borrower and Lender have agreed to the defaultRevenueSplit terms so there's not really “abuse”

The terms are transparent and deterministic so can't really be exploited, just favorable for certain stakeholders in certain situations

It makes the default revenue split a schilling point for all revenue splits (we can customize per contract if we wanted to)

</details>

<details>

<summary>Borrower can still claim Revenue Tokens from a Spigot after failing to repay by the end of the term</summary>

*related to claimRevenue()*&#x20;

**Background Information**

If a Line of Credit hasn’t been fully repaid by the due date, the healthcheck () function must be called explicitly to set the status to liquidatable. The Arbiter can then act to ensure that 100% of Revenue Tokens are escrowed until the loan can be fully repaid.

**Attack Vector**

A loan’s liquidatable status is not automatically propagated to the Spigot if a Line hasn’t been fully repaid by its expiry date and healthcheck() has been run.

claimRevenue() function has no authorization implemented.

As a result, the borrower can front-run the Arbiter reset of the updateOwnerSplit() function with claimRevenue() to obtain one more revenue share from spigot.

**Mitigation Strategies**

All Borrowers and Lenders are incentivized to call claimRevenue() as frequently as gas allows because Borrows need cashflow and Lenders want to escrow as much collateral as possible.

Although the risk is not zero, we expect the surface area to be negligible compared to the size of the loans and interest payments.

</details>

<details>

<summary>Malicious Arbiter could transfer Spigot Ownership to a Borrower before a loan has been repaid</summary>

**Background Information**

When setting up a Secured Line of Credit, it’s assumed that a Borrower adds a Spigot with a Revenue Contract and transfers the ownership of that Spigot to the Line of Credit, acting as new Owner for the benefit of Lenders.

The Arbiter can call updateWhitelist() to allow or disallow execution of the transfer ownership function for the Operator (Borrower) for the Revenue Contract.

**Attack Vector**

A malicious Arbiter could whitelist the transfer ownership function for the Borrower.

The Borrower could then transfer the ownership from the Line back to itself using the \_operate() function.

The Borrower can already have drawn down funds before this attack, leaving Lenders with no recourse.

**Mitigation Strategies**

Whilst an Arbiter is supposed to be a 3rd party negotiator between all Lenders and a Borrower, based on its roles in a Line of Credit the Arbiter is more like an advocate or an agent for Lenders.

Lenders should select trusted arbiters as that is the only trusted part of our system currently but we plan on automating/decentralising them later.

</details>

<details>

<summary>Borrower can prevent Lender from withdrawing (and can minimize drawn interest accruing)</summary>

**Attack Vector**

When a Lender attempts to withdraw(), a Borrower could front-run it with the borrow() function, and immediately call the repay() function to repay what it had drawn down.

No drawn interest would be applied and all funds would still be available to borrow.

The borrower could repeat that until the end of the term at which point the Borrower wouldn't be able to borrow again or would be liquidated if they didn't fully repay

**Mitigation Strategies**

Whilst this is technically possible, a flashbot transaction sent by the Lender ought still be able to withdraw the funds

</details>

<details>

<summary>Enabling token collateral - internal transaction error</summary>

A Borrower can post any ERC-20 or ERC-4626 token as collateral, provided that the token has been whitelisted (enabled) by the Arbiter.

If however enableCollateral() is called for a token that is not ERC-4626 compliant then an internal transaction error will be returned (an example is provided below)

<img src="/files/jtdrkKspLczKp8P41eI1" alt="" data-size="original">

Whilst ERC-4626 tokens can be enabled, only the underlying collateral is used for pricing.

ERC-20 and ERC-4626 contracts must be verified for malicious code / exploits before enabling.\\

</details>

<details>

<summary>Lender can deposit after Line expiry</summary>

A Borrower can no longer draw down after a Line has expired.\
\
If however there are no outstanding drawdowns at expiry and therefore the Line is not in default, it's still possible for a Lender to deposit funds to the Line.\
\
This creates a 'technical default' which causes the Line to be liquidatable.

In this case, a Lender simply has to withdraw the deposited funds.

</details>

Archived Items

<details>

<summary>Bad Actor Claiming Revenue Tokens from a Spigot</summary>

*This risk has been fully mitigated.*&#x20;

*claimAndTrade() and claimAndRepay() can now only be called by the Arbiter*

*related to claimRevenue()*

**Attack Vector**

A Revenue Contract could be called by a bad actor via claimRevenue() with the intention of siphoning off Revenue Tokens.

**Background Information**

claimFunction is the function signature to call a Revenue Contract and claim Revenue Tokens

claimRevenue() claims Revenue Tokens and leaves them in escrow (i.e. unlike claimAndTrade() and claimAndRepay() it doesn’t convert Revenue Tokens to Credit Tokens to be made available for Lender withdrawal or actually repaid to Lenders respectively).

**Mitigation Strategies**

The contracts are written such that claimFunction is restricted to being only capable of calling a Revenue Contract with the sole purpose of escrowing Revenue Tokens.

claimRevenue() can only call the predetermined claimFunction as set by the Spigot Owner

claimFunction can’t be called in operate(), the Spigot function that allows a Borrower to call the whitelisted functions on its Revenue Contracts and carry on its business as usual activities.

The Borrower should verify that claimFunction does not modify any other state on the underlying Revenue Contract.<br>

</details>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.creditcoop.xyz/developer-material/v1-developer-material/edge-cases-and-risk-situations.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
