// SPDX-License-Identifier: MIT pragma solidity ^0.8.19; /** * @title AereFeeBurnVault * @notice Permanent, on-chain burn destination for protocol fees. * * Whitepaper §3.3 promises that "up to 37.5% of all transaction fees are * permanently obliterated." This contract is the burn endpoint that makes * that claim measurable and publicly auditable. * * Design: * - Stateless sink: anyone can send native AERE here via `burn()`, or any * ERC-20 via `burnToken()`. The contract has NO withdraw function and * NO admin escape hatch — funds that enter are permanently removed * from circulation. * - Counters: tracks `totalBurnedAERE` and per-token `totalBurnedToken[token]` * so the chain's deflation can be queried in a single read. * - Sources: protocol contracts that earn fees (AereSwapRouter, the NFT * marketplace, future card-fee router, etc.) can route a configurable * share to this address — but the vault doesn't care WHO sends; any * value arriving here is burned. * * This contract holds no privilege over any other system. Ownable is not * needed because there are no admin operations. */ interface IERC20 { function transfer(address to, uint256 amount) external returns (bool); function transferFrom(address from, address to, uint256 amount) external returns (bool); function balanceOf(address account) external view returns (uint256); } contract AereFeeBurnVault { /// Total native AERE that has flowed into this contract. /// Equal to address(this).balance EXCEPT after the eventual /// "send to zero-address" sweep — see note below. uint256 public totalBurnedAERE; /// Cumulative native AERE actually forwarded to address(0). uint256 public totalSentToZero; /// Per-ERC20 lifetime burn counter. mapping(address => uint256) public totalBurnedToken; event AereBurned(address indexed from, uint256 amount, uint256 newTotal); event TokenBurned(address indexed token, address indexed from, uint256 amount, uint256 newTotal); event AereSentToZero(uint256 amount, uint256 newTotalSentToZero); /// Plain ETH transfer = burn. receive() external payable { totalBurnedAERE += msg.value; emit AereBurned(msg.sender, msg.value, totalBurnedAERE); } /// Explicit native-AERE burn (same as `receive`, but lets callers attach a tag in the event log). function burn() external payable { totalBurnedAERE += msg.value; emit AereBurned(msg.sender, msg.value, totalBurnedAERE); } /// Burn an ERC-20 by pulling it from `msg.sender` via prior approval. /// Tokens are accepted but never sent anywhere; they stay on this contract /// forever. Counters reflect cumulative arrivals. function burnToken(address token, uint256 amount) external { require(token != address(0), "BurnVault: zero token"); require(amount > 0, "BurnVault: zero amount"); require(IERC20(token).transferFrom(msg.sender, address(this), amount), "BurnVault: transferFrom failed"); totalBurnedToken[token] += amount; emit TokenBurned(token, msg.sender, amount, totalBurnedToken[token]); } /// Optional: forward accumulated native AERE to address(0). /// QBFT Besu permits sending to address(0); the AERE is then unreachable. /// Anyone can call this; it has no parameters and no admin gate. This is /// the "obliteration" step — until called, AERE sits on this contract. function sweepToZero() external { uint256 bal = address(this).balance; require(bal > 0, "BurnVault: nothing to sweep"); totalSentToZero += bal; (bool ok, ) = address(0).call{ value: bal }(""); require(ok, "BurnVault: zero-send failed"); emit AereSentToZero(bal, totalSentToZero); } /// Convenience read. function currentAEREBalance() external view returns (uint256) { return address(this).balance; } }