> For the complete documentation index, see [llms.txt](https://mars-20.gitbook.io/mars-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://mars-20.gitbook.io/mars-docs/marscoin-reward-engine.md).

# Marscoin Reward Engine

**Version:** 1.0 | **Network:** BNB Smart Chain | **Protocol:** Hybrid on-chain settlement + off-chain indexing

***

### Overview

MerkBot automates `$SPCXB` distribution to `$MARS` holders. Each epoch:

1. Native BNB accumulated in the distributor contract is swapped to `$SPCXB` via Uniswap V3.
2. An off-chain indexer reconstructs eligible `$MARS` holder balances from `Transfer` logs.
3. A Merkle tree commits pro-rata allocations on-chain via `publishRoot`.
4. Holders claim `$SPCXB` with Merkle proofs, or the operator batch-pushes claims.

***

### Protocol Addresses

| Role                    | Address                                      |
| ----------------------- | -------------------------------------------- |
| Distributor             | `0x9eb159EF7732b6024D838DA2F70B351a50e84b72` |
| `$SPCXB` (reward token) | `0xbe9D156892E55e7154BcD3cB0FEA677F9D3103E1` |
| `$MARS` (holder token)  | `0xec5196c10b719abd317ff550006471c9dc2556a0` |
| Excluded LP pair        | `0xb7dC89Ca603E98E48172739d0Df5eA8b8836A6D5` |
| Snapshot start block    | `104704588`                                  |

**Uniswap V3 route:**

| Role               | Address                                      |
| ------------------ | -------------------------------------------- |
| SwapRouter02       | `0xB971eF87ede563556b2ED4b1C0b0019111Dd85d2` |
| QuoterV2           | `0x78D78E420Da98ad378D7799bE8f4AF69033EB077` |
| Quote token (USDT) | `0x55d398326f99059fF775485246999027B3197955` |

Route: `WBNB →(0.05%)→ USDT →(0.30%)→ $SPCXB`

***

### Architecture

```mermaid
flowchart LR
    BNB["BNB (tax / funding)"] --> Dist["TaxBuybackMerkleDistributor"]
    Dist -->|buyback| V3["Uniswap V3 SwapRouter02"]
    V3 -->|"WBNB → USDT → $SPCXB"| Dist

    MARS["$MARS Transfer logs"] --> Idx["Off-chain Indexer"]
    Idx --> Tree["StandardMerkleTree"]
    Tree -->|publishRoot| Dist

    Dist -->|"distribute"| Holders["$MARS holders"]
```

#### Components

| Component                     | Responsibility                                                                            |
| ----------------------------- | ----------------------------------------------------------------------------------------- |
| `TaxBuybackMerkleDistributor` | Holds BNB / `$SPCXB`; executes buyback; stores Merkle roots; verifies proofs; pays claims |
| Uniswap V3 route              | Converts BNB → `$SPCXB` via two-hop path                                                  |
| Off-chain indexer             | Reconstructs `$MARS` holder balances from `Transfer` logs                                 |
| Operator bot                  | Runs epochs: quote → buyback → snapshot → publishRoot → claimMany                         |

***

### Contract: `TaxBuybackMerkleDistributor`

#### Key State

```solidity
IV3SwapRouter public router;
address public quoteToken;      // USDT
address public tokenB;          // $SPCXB
uint24  public nativeToQuoteFee;  // 500
uint24  public quoteToTokenBFee;  // 3000
uint256 public slippageBps;
uint256 public minSwapBnb;
uint256 public currentEpoch;

mapping(uint256 epoch => bytes32 root)                          public merkleRoot;
mapping(uint256 epoch => mapping(address => bool hasClaimed))   public claimed;
```

#### Events

```solidity
event BuybackExecuted(uint256 bnbIn, uint256 bOut, uint256 minOut);
event RootPublished(uint256 indexed epoch, bytes32 root);
event Claimed(uint256 indexed epoch, address indexed account, uint256 amount);
```

***

### Buyback Engine

The bot quotes the route off-chain before submitting. The contract only enforces `amountOutMinimum`.

```mermaid
sequenceDiagram
    participant Bot
    participant Quoter as QuoterV2
    participant Dist as Distributor
    participant Router as SwapRouter02

    Bot->>Dist: getBuybackPath()
    Bot->>Quoter: quoteExactInput(path, amountIn)
    Quoter-->>Bot: expectedOut
    Bot->>Bot: amountOutMin = expectedOut × (1 - slippageBps)
    Bot->>Dist: buyback(amountIn, amountOutMin)
    Dist->>Router: exactInput{value: amountIn}(path, amountOutMin)
    Router-->>Dist: $SPCXB received
    Dist-->>Bot: emit BuybackExecuted
```

**Route:** `WBNB →(500)→ USDT →(3000)→ $SPCXB`

The two-hop design routes through the deep WBNB/USDT pool before hitting the `$SPCXB` market, reducing price impact compared to a direct WBNB/`$SPCXB` swap.

**Safety checks:**

* `amountIn > 0` and `amountIn >= minSwapBnb`
* `amountOutMinimum > 0` — never zero
* `$SPCXB` received ≥ `amountOutMinimum` (enforced by router)

***

### Holder Snapshot

Eligible balances are reconstructed from `$MARS` ERC-20 `Transfer` events. No on-chain holder registry exists.

```mermaid
flowchart TD
    A["Scan Transfer logs from DEPLOY_BLOCK"] --> B["Apply balance deltas"]
    B --> C["Exclude: zero, dead, LP pair, distributor, EXCLUDE_EXTRA"]
    C --> D["Keep positive balances only"]
    D --> E["Compute pro-rata $SPCXB allocation"]
    E --> F["Build StandardMerkleTree"]
    F --> G["Save epoch_N.json"]
```

**Excluded addresses:**

```
0x0000000000000000000000000000000000000000
0x000000000000000000000000000000000000dEaD
LP_PAIR
Distributor contract
EXCLUDE_EXTRA (configurable)
```

***

### Allocation Formula

```
D   = total $SPCXB available for the epoch
B_i = eligible $MARS balance of account i
S   = sum of all eligible balances

R_i = floor(D × B_i / S)
```

* Rounding dust (`D − Σ R_i`) stays in the contract and rolls to the next epoch.
* Allocations below `MIN_PAYOUT` are dropped from the tree (keeps leaf count manageable and avoids dust-gas waste).

***

### Merkle Commitment

Uses OpenZeppelin `StandardMerkleTree`. Each leaf encodes `(account, amount)`:

```solidity
keccak256(bytes.concat(keccak256(abi.encode(account, amount))))
```

Root lifecycle:

```mermaid
sequenceDiagram
    participant Idx as Indexer
    participant Bot
    participant Dist as Distributor

    Idx->>Idx: reconstruct balances
    Idx->>Idx: build StandardMerkleTree
    Idx->>Bot: root + proof file
    Bot->>Dist: publishRoot(root)
    Dist-->>Bot: emit RootPublished(epoch, root)
    Note over Dist: currentEpoch++, root stored permanently
```

***

### Claim System

#### User claim (self-serve)

```solidity
function claim(
    uint256 epoch,
    address account,
    uint256 amount,
    bytes32[] calldata proof
) external;
```

Checks: `!claimed[epoch][account]` → `MerkleProof.verify(proof, root, leaf)` → mark claimed → transfer `$SPCXB`.

#### Operator batch push

```solidity
function claimMany(uint256 epoch, ClaimData[] calldata items) external;
```

* Already-claimed entries → skip (not revert).
* Invalid proofs → skip.
* Idempotent: safe to rerun on partial failure.

```mermaid
flowchart LR
    P["Merkle proof"] --> V["Verify against epoch root"]
    V --> C["Check !claimed"]
    C --> M["Mark claimed"]
    M --> T["Transfer $SPCXB"]
    T --> E["Emit Claimed"]
```

***

### Epoch Lifecycle

```mermaid
stateDiagram-v2
    [*] --> Funding
    Funding --> Buyback : BNB available
    Buyback --> Snapshot : $SPCXB received
    Snapshot --> MerkleBuild : balances indexed
    MerkleBuild --> RootPublished : root on-chain
    RootPublished --> Claimable : users can claim
    Claimable --> Settled : all claims complete
```

| Step | Action                                                           |
| ---- | ---------------------------------------------------------------- |
| 1    | Distributor accumulates BNB                                      |
| 2    | Bot quotes V3 route off-chain                                    |
| 3    | Bot calls `buyback(amountIn, amountOutMin)`                      |
| 4    | Indexer snapshots `$MARS` holders                                |
| 5    | Indexer builds Merkle tree; asserts `Σ R_i ≤ contract B balance` |
| 6    | Bot calls `publishRoot(root)`                                    |
| 7    | Users call `claim`, or bot calls `claimMany` in batches          |

Optional two-step mode: publish root → review dashboard → push claims. Allows manual verification before distribution.

***

### Security Model

| Layer             | Enforcement                                                        |
| ----------------- | ------------------------------------------------------------------ |
| Buyback slippage  | `amountOutMinimum` enforced by Uniswap V3 router on-chain          |
| Reward accounting | Recomputable from public `Transfer` logs by anyone                 |
| Root publication  | Operator publishes; anyone can independently verify the epoch file |
| Claim validity    | Merkle proof verified fully on-chain                               |
| Token transfer    | `SafeERC20` inside `ReentrancyGuard`                               |

**Contract protections:**

* `onlyRole(OPERATOR_ROLE)` on `buyback`, `publishRoot`, `claimMany`
* `onlyOwner` on config setters
* `ReentrancyGuard` on all fund-moving paths
* CEI pattern: `claimed[epoch][account] = true` set **before** transfer
* `rescue` uses low-level `call` (not `.transfer`) for native BNB

**Operational risks:**

* Operator key can publish an incorrect root → mitigate by publishing epoch JSON for independent verification before claiming
* Snapshot timing allows last-block balance manipulation → future mitigation: time-weighted snapshots (out of scope v1)
* Thin `$SPCXB` liquidity can cause poor buyback execution → monitor QuoterV2 output before each epoch

***

### On-Chain Audit Trail

Every protocol action emits an event:

| Event             | Data                         |
| ----------------- | ---------------------------- |
| `BuybackExecuted` | `bnbIn`, `bOut`, `minOut`    |
| `RootPublished`   | `epoch`, `root`              |
| `Claimed`         | `epoch`, `account`, `amount` |
| `ConfigUpdated`   | `key`                        |

Derived metrics:

```
Total $SPCXB bought  = Σ BuybackExecuted.bOut
Total BNB used       = Σ BuybackExecuted.bnbIn
Total $SPCXB claimed = Σ Claimed.amount
```

***

### Dashboard Reads

```solidity
currentEpoch()
merkleRoot(epoch)
claimed(epoch, account)
tokenB.balanceOf(distributor)    // $SPCXB available
provider.getBalance(distributor) // BNB pending buyback
slippageBps()
minSwapBnb()
```

***

***


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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://mars-20.gitbook.io/mars-docs/marscoin-reward-engine.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.
