aere-contracts/contracts/AereFeeBurnVault.sol
Aere Network a13a649b77
Some checks are pending
contracts-ci / Install (lockfile) → compile → full test suite (push) Waiting to run
contracts-ci / PQC known-answer tests (NIST vectors) (push) Waiting to run
contracts-ci / Coverage (scoped, with artifacts) (push) Waiting to run
Initial public release
Aere Network public source. Everything here can be checked against the live
chain (chain id 2800, https://rpc.aere.network).

Scope note, stated up front rather than buried: consensus on chain 2800 is
classical secp256k1 ECDSA QBFT. The post-quantum work in this repository is at
the signature, precompile, account and transport layers. Nothing here makes the
consensus post-quantum, and no document in it should be read as claiming so.
2026-07-20 01:02:37 +03:00

91 lines
3.9 KiB
Solidity

// 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;
}
}