# Helpers

{% hint style="info" %}
**Source:** `src/fira_bonding/libraries/`
{% endhint %}

## Errors.sol

Central registry of all custom error types. Errors are prefixed by module (`Market*`, `YC*`, `FW*`, `Router*`). Using custom errors instead of string reverts saves gas and makes off-chain decoding straightforward.

## TokenHelper.sol

Safe ERC20 transfer wrappers with native ETH handling:

* `_transferIn(token, from, amount)` — Handles ETH by checking `msg.value` and wrapping via WETH
* `_transferOut(token, to, amount)` — Handles ETH by unwrapping WETH
* `_selfBalance(token)` — Balance accounting for native ETH
* `_safeApproveInf(token, spender)` — Infinite approval only if current allowance is low

The `NATIVE` sentinel address (`0x000...000`) represents ETH in `TokenInput`/`TokenOutput` structs.

## BoringOwnableUpgradeable.sol

Two-step ownership transfer: `transferOwnership(newOwner, direct, renounce)` either transfers immediately or sets a pending owner who must call `claimOwnership()`. Used by FW tokens and factories.

## BaseSplitCodeFactory / CodeDeployer

Works around the 24KB EVM contract size limit (EIP-170):

1. At factory deployment, creation bytecode is split into two chunks, each deployed as a "code storage" contract
2. At creation time, bytecode is concatenated in memory and deployed via CREATE2

Used by both `FiraMarketFactory` and `YieldContractFactory` since `FiraMarket` and `CouponToken` exceed the size limit.

## Other helpers

* **`MiniHelpers.sol`** — `isCurrentlyExpired(expiry)`, `ensureNotExpired()` — used everywhere for pre/post-expiry gating
* **`ExpiryUtilsLib.sol` / `StringLib.sol`** — Generate deterministic token names like `FW-USDC-BT-07MAY2026` from symbols and expiry timestamps
* **`ArrayLib.sol`** — `create(a, b)` returns a 2-element `address[]`; `sum(arr)` sums a `uint256[]`
