> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mystockline.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# FeeCollector

> FeeCollector receives protocol revenue and splits it into a reserve and a treasury.

FeeCollector receives protocol revenue and splits it into a reserve and a treasury. Interest cash arrives from Stockline on repay; liquidation fees arrive as seized stock tokens and are sold for USDG with `sweepCollateral`. Unallocated USDG fills the reserve up to a target of 5% of pool borrows, then flows to the treasury. Anyone can spend the reserve on pool bad debt and burn treasury USDG into STK within an epoch budget.

`FeeCollector` lets you:

* Allocate fresh USDG into reserve, then treasury
* Cover pool bad debt from the reserve
* Buy and burn STK with treasury USDG inside the epoch budget
* Sell seized collateral for USDG along its zap route
* Credit reserve and treasury directly (used by CreatorFeeRouter)
* Read the reserve, treasury, target, and epoch state

Addresses per network. Every address is also on [Addresses](/resources/addresses).

| Network                 | Address                                                                                                                                       |
| ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| Robinhood Chain testnet | [0x35609322D14dDb08fFAAf844c4a02afAcC586D77](https://explorer.testnet.chain.robinhood.com/address/0x35609322D14dDb08fFAAf844c4a02afAcC586D77) |

The source code is [`src/core/FeeCollector.sol`](https://github.com/stockline-xyz/contracts/blob/main/src/core/FeeCollector.sol) on GitHub. The ABI is [`/abis/FeeCollector.json`](/abis/FeeCollector.json).

## Write methods

### notifyInterest

```solidity theme={"system"}
function notifyInterest(uint256 amount) external
```

Records that `amount` of reserve-factor interest has accrued. Only Stockline can call it. This is a counter; the cash arrives later on repay.

<Warning>
  Core only.
</Warning>

**Input parameters**

| Name   | Type      | Description                              |
| ------ | --------- | ---------------------------------------- |
| amount | `uint256` | USDG interest reserved for the protocol. |

### notifyLiquidationFee

```solidity theme={"system"}
function notifyLiquidationFee(uint256 amount) external
```

Records that `amount` of seized collateral arrived as the protocol's liquidation share. Only Stockline can call it.

<Warning>
  Core only.
</Warning>

**Input parameters**

| Name   | Type      | Description                                  |
| ------ | --------- | -------------------------------------------- |
| amount | `uint256` | Collateral tokens received, in native units. |

### credit

```solidity theme={"system"}
function credit(uint256 toReserve, uint256 toTreasury) external nonReentrant
```

Pulls `toReserve + toTreasury` USDG from the caller and credits the two buckets directly, skipping the target waterfall. Permissionless. CreatorFeeRouter uses it for the 40/30 split. Reverts with ZeroAmount when both are zero.

<Warning>
  The caller must approve FeeCollector for the total. USDG sent here belongs to the protocol.
</Warning>

<Note>
  Direct credits skip the allocate waterfall so a Pons split can raise reserve even when the 5% target is already full.
</Note>

**Input parameters**

| Name       | Type      | Description                    |
| ---------- | --------- | ------------------------------ |
| toReserve  | `uint256` | USDG credited to the reserve.  |
| toTreasury | `uint256` | USDG credited to the treasury. |

### setReserveTargetPct

```solidity theme={"system"}
function setReserveTargetPct(uint64 pct) external
```

Sets the reserve target as a share of `pool.borrowed()`. Owner only. Reverts with InvalidWad above 1e18.

<Warning>
  Owner (timelock) only.
</Warning>

**Input parameters**

| Name | Type     | Description                                          |
| ---- | -------- | ---------------------------------------------------- |
| pct  | `uint64` | Target share in WAD. Deployed value is 0.05e18 (5%). |

### setBurnEpoch

```solidity theme={"system"}
function setBurnEpoch(uint32 duration) external
```

Sets the length of each buy-and-burn epoch. Owner only. Reverts with InvalidEpoch outside \[1 day, 90 days].

<Warning>
  Owner (timelock) only.
</Warning>

**Input parameters**

| Name     | Type     | Description                                        |
| -------- | -------- | -------------------------------------------------- |
| duration | `uint32` | Epoch length in seconds. Deployed value is 7 days. |

### allocate

```solidity theme={"system"}
function allocate() public
```

Moves any USDG not yet assigned to reserve or treasury: first fills the reserve up to `reserveTarget`, then sends the rest to the treasury. Permissionless. Emits Allocated only when something moved.

### coverBadDebt

```solidity theme={"system"}
function coverBadDebt(uint256 amount) external nonReentrant
```

Spends up to `amount` of the reserve into USDGPool through `restore`, making suppliers whole after a write-off. Permissionless. Allocates first. Reverts with ZeroAmount when `amount` is 0 or the reserve is empty.

<Note>
  This does not check that the pool actually had bad debt. It always increases pool cash and the sUSDG share price.
</Note>

**Input parameters**

| Name   | Type      | Description                                          |
| ------ | --------- | ---------------------------------------------------- |
| amount | `uint256` | Maximum USDG to move. Capped at the current reserve. |

### buyAndBurn

```solidity theme={"system"}
function buyAndBurn(uint256 amount) external nonReentrant
```

Swaps `amount` treasury USDG along the buy-and-burn route and sends the output token to the dead address. Permissionless. Reverts with EpochBudgetExceeded above the unused epoch budget, InsufficientTreasury above the treasury balance, CapExceeded above `maxPerCall`, and InvalidRoute if the route does not start with USDG.

<Note>
  Each epoch's budget is 20% (2000 bps, fixed) of the treasury at roll time. The first epoch after deployment has a budget of 0, so burns can start only after the first roll. Slippage is checked against the router's TWAP quote.
</Note>

**Input parameters**

| Name   | Type      | Description                          |
| ------ | --------- | ------------------------------------ |
| amount | `uint256` | USDG to spend, in USDG native units. |

### sweepCollateral

```solidity theme={"system"}
function sweepCollateral(address token) external nonReentrant
```

Sells the whole balance of a seized collateral token for USDG using its zap route, then allocates. Permissionless. Reverts with InvalidRoute for USDG or a route that does not end in USDG, NotAllowed if the token has no allowed route, and ZeroAmount when the balance is 0.

**Input parameters**

| Name  | Type      | Description                   |
| ----- | --------- | ----------------------------- |
| token | `address` | The collateral token to sell. |

## Read methods

### reserveTarget

```solidity theme={"system"}
function reserveTarget() public view returns (uint256)
```

Returns the reserve the waterfall fills before the treasury: `pool.borrowed() * reserveTargetPct / 1e18`.

**Return values**

| Type      | Description  |
| --------- | ------------ |
| `uint256` | USDG amount. |

### unallocated

```solidity theme={"system"}
function unallocated() public view returns (uint256)
```

Returns USDG held here that is not yet assigned to reserve or treasury.

**Return values**

| Type      | Description  |
| --------- | ------------ |
| `uint256` | USDG amount. |

## Events

### Allocated

```solidity theme={"system"}
event Allocated(uint256 toReserve, uint256 toTreasury)
```

Fires when unallocated USDG moves into reserve and treasury.

### Credited

```solidity theme={"system"}
event Credited(uint256 toReserve, uint256 toTreasury)
```

Fires when someone credits reserve and treasury directly.

### ReserveTargetPctSet

```solidity theme={"system"}
event ReserveTargetPctSet(uint64 pct)
```

Fires when the reserve target share changes.

### BurnEpochSet

```solidity theme={"system"}
event BurnEpochSet(uint32 duration)
```

Fires when the epoch length changes.

### EpochRolled

```solidity theme={"system"}
event EpochRolled(uint256 start, uint256 budget)
```

Fires when a new burn epoch starts, with its start and budget.

### Covered

```solidity theme={"system"}
event Covered(uint256 amount)
```

Fires when reserve USDG is sent to the pool to cover bad debt.

### BuyAndBurn

```solidity theme={"system"}
event BuyAndBurn(uint256 usdgIn, uint256 stkBurned)
```

Fires when treasury USDG is swapped and the output is burned.

### CollateralSwept

```solidity theme={"system"}
event CollateralSwept(
    address indexed token,
    uint256 amountIn,
    uint256 usdgOut
)
```

Fires when seized collateral is sold for USDG.

## Errors

### ZeroAddress

```solidity theme={"system"}
error ZeroAddress()
```

A constructor address was zero, or the registry has no DEX router.

### NotCore

```solidity theme={"system"}
error NotCore()
```

Only Stockline can notify fees.

### NotOwner

```solidity theme={"system"}
error NotOwner()
```

Only the timelock can change the target or epoch.

### ZeroAmount

```solidity theme={"system"}
error ZeroAmount()
```

An amount was zero or nothing was available.

### InvalidWad

```solidity theme={"system"}
error InvalidWad()
```

The reserve target share is above 1e18.

### InsufficientTreasury

```solidity theme={"system"}
error InsufficientTreasury()
```

The burn amount exceeds the treasury.

### CapExceeded

```solidity theme={"system"}
error CapExceeded()
```

The burn amount exceeds `maxPerCall`.

### InvalidRoute

```solidity theme={"system"}
error InvalidRoute()
```

The swap route is missing, too short, or has the wrong endpoints.

### NotAllowed

```solidity theme={"system"}
error NotAllowed()
```

The token has no allowed zap route.

### InvalidEpoch

```solidity theme={"system"}
error InvalidEpoch()
```

The epoch length is outside 1 to 90 days.

### EpochBudgetExceeded

```solidity theme={"system"}
error EpochBudgetExceeded()
```

The burn amount exceeds the unused budget of the current epoch.
