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.
104 lines
4.2 KiB
Solidity
104 lines
4.2 KiB
Solidity
// SPDX-License-Identifier: MIT
|
|
pragma solidity 0.8.23;
|
|
|
|
import "@openzeppelin/contracts/access/Ownable.sol";
|
|
|
|
/**
|
|
* @title AerePointsLedger — AERE Season 1 "Altitude" non-transferable points
|
|
* @notice A CREDIT-ONLY, NON-TRANSFERABLE ledger of "Altitude Points" (AP).
|
|
*
|
|
* HARD SAFETY DESIGN — AP is NOT a token and can never become one:
|
|
* - transfer / transferFrom / approve HARD-REVERT (NotTransferable). AP can
|
|
* never move between accounts, so it can never trade as a shadow token.
|
|
* - There is NO burn, NO redeem, NO conversion, NO "claim your tokens"
|
|
* path anywhere in this contract. AP is a scoreboard, nothing else.
|
|
* - Only Foundation-authorized attestors may `credit`. There is no mint()
|
|
* callable by users and no way for AP to leave an account.
|
|
*
|
|
* HONESTY / DISCLAIMER (must accompany any user-facing surfacing of AP):
|
|
* Altitude Points are NOT a token, carry NO guaranteed value, and confer
|
|
* NO right to returns. Any future reward depends on the network growing
|
|
* and is not promised. There is no listing.
|
|
*
|
|
* ERC-20 read shape (name/symbol/decimals/balanceOf/totalSupply) plus a
|
|
* mint-style Transfer(address(0), account, amount) event are emitted purely
|
|
* so block explorers / the AERE indexer can display balances. The WRITE side
|
|
* of ERC-20 is deliberately bricked.
|
|
*
|
|
* Owner = Foundation multisig. Ownable only manages the attestor allowlist;
|
|
* the owner cannot move, mint to itself for transfer, or reduce balances.
|
|
*/
|
|
contract AerePointsLedger is Ownable {
|
|
|
|
string public constant name = "AERE Altitude Points";
|
|
string public constant symbol = "AP";
|
|
uint8 public constant decimals = 0; // whole points, not a token
|
|
|
|
uint256 public totalSupply;
|
|
mapping(address => uint256) public balanceOf;
|
|
|
|
/// @notice Foundation-authorized credit sources (the quest attestor and the
|
|
/// referral registry are added here post-deploy).
|
|
mapping(address => bool) public isAttestor;
|
|
|
|
/* --------------------------------- events ------------------------------- */
|
|
|
|
/// @dev ERC-20 mint-style event for indexers. address(0) => account only.
|
|
event Transfer(address indexed from, address indexed to, uint256 value);
|
|
/// @dev Rich credit event carrying the quest attribution for the indexer.
|
|
event PointsCredited(address indexed account, uint256 amount, bytes32 indexed questId, uint256 newBalance);
|
|
event AttestorSet(address indexed attestor, bool allowed);
|
|
|
|
/* --------------------------------- errors ------------------------------- */
|
|
|
|
error NotTransferable();
|
|
error NotAttestor();
|
|
error ZeroAccount();
|
|
error ZeroAmount();
|
|
|
|
/* ------------------------------- attestors ------------------------------ */
|
|
|
|
function setAttestor(address attestor, bool allowed) external onlyOwner {
|
|
if (attestor == address(0)) revert ZeroAccount();
|
|
isAttestor[attestor] = allowed;
|
|
emit AttestorSet(attestor, allowed);
|
|
}
|
|
|
|
modifier onlyAttestor() {
|
|
if (!isAttestor[msg.sender]) revert NotAttestor();
|
|
_;
|
|
}
|
|
|
|
/* -------------------------------- credit -------------------------------- */
|
|
|
|
/// @notice Credit `amount` AP to `account`, attributed to `questId`.
|
|
/// Credit-only: balances can only ever go up.
|
|
function credit(address account, uint256 amount, bytes32 questId) external onlyAttestor {
|
|
if (account == address(0)) revert ZeroAccount();
|
|
if (amount == 0) revert ZeroAmount();
|
|
balanceOf[account] += amount;
|
|
totalSupply += amount;
|
|
emit Transfer(address(0), account, amount);
|
|
emit PointsCredited(account, amount, questId, balanceOf[account]);
|
|
}
|
|
|
|
/* --------------------------- bricked ERC-20 write ----------------------- */
|
|
|
|
function transfer(address, uint256) external pure returns (bool) {
|
|
revert NotTransferable();
|
|
}
|
|
|
|
function transferFrom(address, address, uint256) external pure returns (bool) {
|
|
revert NotTransferable();
|
|
}
|
|
|
|
function approve(address, uint256) external pure returns (bool) {
|
|
revert NotTransferable();
|
|
}
|
|
|
|
/// @notice Always zero — AP has no allowance concept.
|
|
function allowance(address, address) external pure returns (uint256) {
|
|
return 0;
|
|
}
|
|
}
|