# FiraERC20

{% hint style="info" %}
**Source:** `src/fira_bonding/erc20/FiraERC20.sol`, `FiraERC20Permit.sol`, `FiraERC20Upg.sol`, `FiraERC20PermitUpg.sol`
{% endhint %}

## Variants

| Contract             | Permit   | Upgradeable         | Used by             |
| -------------------- | -------- | ------------------- | ------------------- |
| `FiraERC20`          | No       | No                  | BT, FiraMarket (LP) |
| `FiraERC20Permit`    | EIP-2612 | No                  | —                   |
| `FiraERC20Upg`       | No       | Yes (Initializable) | —                   |
| `FiraERC20PermitUpg` | EIP-2612 | Yes (Initializable) | FW tokens           |

## Reentrancy guard

A `_reentrancyStatus` slot flips between `_NOT_ENTERED` (1) and `_ENTERED` (2). The `nonReentrant` modifier is available to all contracts that inherit `FiraERC20`. This means `FiraMarket` (which extends `FiraERC20` as its LP token) gets reentrancy protection without extra inheritance.

## Transfer hooks

* `_beforeTokenTransfer` — Virtual, overridden by CT (distributes interest) and FW (enforces pause)
* `_afterTokenTransfer` — Virtual, available for derived contracts

## Permit (EIP-2612)

`FiraERC20Permit` adds gasless approvals via `permit(owner, spender, value, deadline, v, r, s)`. Uses EIP-712 typed data for domain separation. The `DOMAIN_SEPARATOR` is computed at construction time and cached.

## Design decisions

* No `receive` or `fallback` — only contracts that need ETH (FWBase, Router) add `receive()`
* Storage layout matches between upgradeable and non-upgradeable variants
