Address
0x009cc13bce2c481eaf468aa0d5e2c45e5ea0c232Current Holdings
$0.00
TXs sent
not counted
First Active
2026-06-18
block 26,819,985
Last Active
90 days ago
block 26,819,985
Funded By
not identified
Net worth historyi
No net-worth snapshots recorded yet
exact matchEnginesolc 0.8.24+commit.e11b9ed9runtime exact · creation exact
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
/* ─────────────────────── INTERNAL CONCEPT MAP ─────────────────────────
Engine is the delegatecalled accounting implementation for the SUN/MOON protocol.
It classifies MOON transfers, records taxed value by pair, performs delayed swap-backs,
and distributes realized paired-token value to eligible SUN holders.
Engine owns no persistent protocol state. All storage is Kernel storage; this contract
is logic that must run through delegatecall.
Entities:
• Ray – a taxed V2 pair containing MOON (identified by pair address).
• Member – a SUN holder eligible for indexed value accrual.
• Global – aggregate accounting state (pool, oath, index, lists).
Global accounting:
• pool – total MOON-value of tokens currently available for distribution.
• oath – total nominal claim asserted by the index. (scaled by coverage)
• index – cumulative value-per-eligible-SUN used to track per member claims.
• Coverage is expressed implicitly as pool / oath; payouts are scaled by
this ratio so the system only pays value it actually holds.
• work – per-ray gas credit system that supports system liveliness by
throttling expensive rays and rewarding productive ones.
Value realization (reactive):
• A MOON transfer involving a Ray may be classified as a taxed swap via
pair reserve delta heuristics.
• SWAP_TAX MOON is attributed to the Ray as pending value.
• Pending MOON is not swapped immediately; it is swapped back later,
opportunistically, during the next Ray's transaction.
• swap-backs buy the paired token with pending MOON.
• Some pending is burnt to pay APPRECIATION_TAX.
• After taxation, newly credited value enters pool, oath, and the distribution index.
Distribution:
• Rays are separated into two value-tiered lists CORE and EDGE for emission
efficiency.
• Emissions pseudo-randomly select rays weighted by pool/core value share.
• Members are paid value proportional to token holdings from index.
*/
/// @notice Sun payout used in _emitRay.
interface ISun {
function releaseToMember(
address ray,
uint amount,
address member,
bool requireIncrease
) external;
}
/// @notice Internal channel to move MOON tokens.
interface IMoon {
function kernelTransfer(
address from,
address to,
uint256 amount
) external returns (uint moveAmt);
}
/// @dev Uniswap V2 Pair subset used by the contract’s swap-backs.
interface IUniswapV2Pair {
function swap(
uint amount0Out,
uint amount1Out,
address to,
bytes calldata data
) external;
}
/// @notice Internal logic engine for MOON tax, swap-back, and SUN distribution.
/// @dev
/// - Decides how much MOON tax applies to transfers involving rays.
/// - Executes swap-backs that convert taxed MOON into paired tokens.
/// - Distributes paired-token value to eligible SUN holders.
/// - This contract is logic-only and is intended to run only through delegatecall from the kernel.
/// - All persistent storage lives in the kernel, not in this implementation.
/// - Direct calls to Engine are invalid and should never be made by users or external contracts.
/// @custom:version Engine-1.0
contract Engine {
/*/////////////////////////////////////////////////////////////////////////
EVENTS
/////////////////////////////////////////////////////////////////////////*/
/// @dev Fired once when a new ray (paired token) is discovered & cached.
event RayInitialized(address indexed ray, address indexed token);
/*/////////////////////////////////////////////////////////////////////////
ERRORS
/////////////////////////////////////////////////////////////////////////*/
/// @dev Function restricted to callable only by SUN or MOON.
error InternalOnly();
/// @dev Reverts if engine is called directly instead of via proxy.
error ProxyOnly();
/*/////////////////////////////////////////////////////////////////////////
MODIFIERS
/////////////////////////////////////////////////////////////////////////*/
/// @notice Engine self.
address private immutable SELF = address(this);
/// @dev Only callable via proxy (delegatecall)
modifier onlyProxy() {
if (address(this) == SELF) revert ProxyOnly();
_;
}
/*/////////////////////////////////////////////////////////////////////////
IMMUTABLES
/////////////////////////////////////////////////////////////////////////*/
/// @notice MOON ERC‑20 contract linked for tax collection.
address private immutable moon;
/// @notice SUN ERC‑20 contract linked for distributions.
address private immutable sun;
/// @notice Wrapped native gas token.
address private immutable wbase;
/*/////////////////////////////////////////////////////////////////////////
CONSTANTS
/////////////////////////////////////////////////////////////////////////*/
/*───────────────────────────── CORE SYSTEM ─────────────────────────────*/
/// @notice Swap tax rate.
uint private constant SWAP_TAX = 3e16; // 3%
/// @notice Percentage of swap-back left in the pair as an LP bonus.
uint private constant PAIR_BONUS = 20e16; // 25%
/// @notice Appreciation tax applied to positive value deltas.
uint private constant APPRECIATION_TAX = 20e16; // 20%
/// @notice Sentinel transfer amount (wei) that requests MOON to re-probe an address.
uint private constant REFRESH_WEI = 369; // 369 wei SUN/MOON
/// @notice Protocol-internal MOON dust threshold (not user-facing).
uint private constant DUST = 1e9; // 1e-9 MOON
/*─────────────────────────── GAS MANAGEMENT ───────────────────────────*/
/// @notice Gas target for the radiation loop.
uint private constant GAS_RADIATE = 250_000;
/// @notice Gas target for swapBack with pair.
uint private constant GAS_BASE_SWAP = 200_000;
/// @notice Gas cap for swapBack with pair.
uint private constant GAS_CAP_SWAP = 400_000;
/// @notice Gas target for release to member call.
uint private constant GAS_BASE_RELEASE = 50_000;
/// @notice Gas cap for release to member call.
uint private constant GAS_CAP_RELEASE = 250_000;
/// @notice Low gas cap default.
uint private constant GAS_PROBE_LOW = 20_000;
/// @notice High gas cap default.
uint private constant GAS_PROBE_HIGH = 30_000;
/*─────────────────────────── WORK ACCOUNTING ───────────────────────────*/
/// @notice work credited to rays for running maintenance.
int private constant WORK_CREDIT = 150;
/// @notice work threshold to be added for swapBack.
int private constant WORK_SWAPBACK = 300;
/// @notice work threshold to be added for distribution.
int private constant WORK_DISTRIBUTION = 150;
/// @notice max work credits a ray can hold.
int private constant WORK_MAX = 750;
/// @notice work fee for priority emission.
int private constant PRIORITY_FEE = 450;
/// @notice work level that ray is removed from distribution lists.
int private constant WORK_REMOVAL = -450;
/*────────────────────────── MEMBER THRESHOLDS ──────────────────────────*/
/// @notice Minimum SUN tokens for active member list
uint private constant MIN_ACTIVE = 1e20; // 100
/// @notice Minimum SUN tokens for prime member list
uint private constant MIN_PRIME = 5e22; // 50k
/*────────────────────────── SYSTEM ADDRESSES ───────────────────────────*/
/// @notice Conventional burn sink address (irretrievable).
address private constant DEAD =
0x000000000000000000000000000000000000dEaD;
/*/////////////////////////////////////////////////////////////////////////
GLOBAL STATE
/////////////////////////////////////////////////////////////////////////*/
// packedGlobal0 layout (low -> high):
// [ 0..111] index (uint112) // cumulative value owed per eligible SUN token (1e27-scaled)
// [112..203] eligible (uint92) // total SUN held by eligible members (1e18-scaled)
// [204..242] amLen (uint39) // activeMembers length
// [243..255] bits0 (uint13) // core bits [62..74]
uint private packedGlobal0;
// packedGlobal1 layout (low -> high):
// [ 0..38 ] amCursor (uint39)
// [ 39..77] pmCursor (uint39)
// [ 78..116] erLen (uint39)
// [117..155] crLen (uint39)
// [156..194] pmLen (uint39)
// [195..213] rPhase (uint19)
// [214..232] mPhase (uint19)
// [233..254] bits1 (uint22) // core bits [75..96]
// [255 ] unused (uint1)
uint private packedGlobal1;
// packedGlobal2 layout (low -> high):
// [ 0..96 ] oath (uint97) // total value owed (1e18-scaled)
// [ 97..193] pool (uint97) // total value ready for emission (1e18-scaled)
// [194..255] coreLo62 (uint62) // low 62 bits of core
//
// core (uint97) is reconstructed as:
// core = uint97(coreLo62) | (uint97(bits0) << 62) | (uint97(bits1) << 75)
uint private packedGlobal2;
/// @dev Ephemeral decoded view of global state.
struct Global {
// full packed slots
uint slot0; // packed slot0
uint slot1; // packed slot1
uint slot2; // packed slot2
bool load0; // true if slot0 was loaded
bool load1; // true if slot1 was loaded
bool load2; // true if slot2 was loaded
// slot0
uint112 index; // cumulative nominal value-per-eligible-SUN (1e27-scaled)
uint eligible; // total SUN held by eligible members (storage uint92; 1e18-scaled)
uint amLen; // activeMembers length (storage uint39)
uint16 bits0; // core bits [62..74] (storage uint13)
// slot1
uint amCursor; // cursor in activeMembers (storage uint39)
uint pmCursor; // cursor in primeMembers (storage uint39)
uint erLen; // edgeRays length (storage uint39)
uint crLen; // coreRays length (storage uint39)
uint pmLen; // primeMembers length (storage uint39)
uint rPhase; // weighted ray-list phase: coreRays vs edgeRays (storage uint19; 2^18-scaled)
uint mPhase; // weighted member-list phase: primeMembers vs activeMembers (storage uint19; 2^18-scaled)
uint32 bits1; // core bits [75..96] (storage uint22)
// slot2
uint oath; // approximate aggregate nominal claims outstanding (storage uint97; 1e18-scaled)
uint pool; // aggregate value credited for distribution (storage uint97; 1e18-scaled)
uint core; // pool value in core list (uint97 reconstructed from coreLo62 + bits0 + bits1)
// transient helpers (NEVER written to storage)
address priority; // priority ray
uint minCore; // minimum value to be in core list (computed in memory; 1e18-scaled)
int penalty; // work collected as penalty.
address nextPair; // pair to be set as nextSwap;
}
/// @dev Ray that will be swapped next.
address private nextSwap;
/*/////////////////////////////////////////////////////////////////////////
RAY TOKEN STATE
/////////////////////////////////////////////////////////////////////////*/
/// slot0 layout (low -> high):
/// [ 0..159] token (address)
/// [160 ] moon0 (bool) // stored in slot 0 and 1 for efficiency
/// [161 ] swapLock (bool)
/// [162..225] lastAdd (uint64)
/// [226..255] unused (uint30)
///
/// slot1 layout (low -> high):
/// [ 0..72 ] avail73 (uint73) // float73 encoded available
/// [ 73..145] cred73 (uint73) // float73 encoded credited
/// [146..147] class2 (uint2)
/// [148..237] pending90 (uint90)
/// [238..249] work12 (int12) // signed two's complement work
/// [250..255] flags6 (uint6) // unused|edge|core|eStale|cStale|moon0
///
/// slot2 layout (low -> high):
/// [ 0..95 ] quote96 (uint96) // float96 encoded committed quote (1e38-scaled)
/// [ 96..191] candQuote96 (uint96) // float96 encoded candidate intra-block high
/// [192..255] lastBlock (uint64)
mapping(address => Ray) internal rays;
/// @dev Per-pair accounting keyed by pair address.
struct Ray {
// packed storage
uint slot0; // packed slot0
uint slot1; // packed slot1
uint slot2; // packed slot2
bool load0; // true if slot0 is loaded
bool load1; // true if slot1 is loaded
bool load2; // true if slot2 is loaded
// slot0
address token; // other token in the pair
bool moon0; // true if MOON is token0 in the pair
bool swapLock; // blocks swaps during untaxed mints/burns
uint lastAdd; // block of last detected liquidity add
// slot1
uint available; // token balance held by SUN available to this ray
uint credited; // taxed portion of available ready for emission
uint pending; // pending MOON earmarked for swap-back
int work; // work credit (1 work = 1k gas)
uint8 class; // 0 unknown | 1 no code | 2 not pair | 3 V2 pair
bool edge; // true if in edgeRays
bool core; // true if in coreRays
bool eStale; // true if should be removed from edge
bool cStale; // true if should be removed from core
// slot2
uint quote; // decoded committed quote (1e38-scaled)
uint candQuote; // decoded candidate intra-block high quote (1e38-scaled)
uint lastBlock; // last block quote was updated
// transient helpers (NEVER written to storage)
address pair; // pair address (ray identity)
bool justInit; // true if Ray was initialized this transaction
uint value; // MOON-denominated value
uint rt; // pair token reserve
uint rm; // pair MOON reserve
uint cursor; // index during emitRay
bool corePick; // true if current emission is from coreRays
bool edgePick; // true if current emission is from edgeRays
}
/// @dev Recorded aggregate available balance by token; reconciled against SUN's live token balance when a ray is touched.
mapping(address => uint) totalAvailable;
/*/////////////////////////////////////////////////////////////////////////
SUN MEMBER STATE
/////////////////////////////////////////////////////////////////////////*/
// memberPacked layout (low -> high):
// [ 0..111] pastIndex (uint112)
// [112..207] uncollected (uint96)
// [208..209] class (uint2)
// [210 ] active (bool)
// [211 ] prime (bool)
// [212..251] idxPlusOne (uint40)
// [252 ] redirect (bool)
// [253..255] unused (uint3)
mapping(address => uint) internal memberPacked;
mapping(address => address) internal memberReceiver;
/// @dev Member accounting snapshot.
struct Member {
// packed slot
uint slot0; // packed slot0
// slot0
uint112 pastIndex; // index snapshot (1e27-scaled)
uint uncollected; // nominal claim used for proportional value distribution
uint8 class; // 0 unknown | 1 no code | 2 eligible | 3 ineligible
bool prime; // true if member is in primeMembers list
bool active; // true if member is in activeMembers list
uint40 idxPlusOne; // index in list plus 1
bool redirect; // true if rewards should be redirected to 'receiver'
// transient helpers (NEVER written to storage)
address addr; // member address (member identity)
uint8 oldClass; // class when member was loaded
uint balance; // SUN balance (never stored)
address receiver; // Reward receiver if 'redirect' is true
}
/*/////////////////////////////////////////////////////////////////////////
MANUAL LIST BASES
/////////////////////////////////////////////////////////////////////////*/
uint private constant SWAPQUEUE = 1;
uint private constant EDGERAYS = 2;
uint private constant CORERAYS = 3;
uint private constant ACTIVEMEMBERS = 4;
uint private constant PRIMEMEMBERS = 5;
/*/////////////////////////////////////////////////////////////////////////
PRECOMPUTED SELECTORS
/////////////////////////////////////////////////////////////////////////*/
bytes4 constant SEL_BALANCEOF = bytes4(keccak256("balanceOf(address)")); // ERC-20 style balanceOf(owner)
bytes4 constant SEL_RAW_BALANCEOF = bytes4(keccak256("rawBalanceOf(address)")); // Moon raw balanceOf
bytes4 constant SEL_TOKEN0 = bytes4(keccak256("token0()")); // token0()
bytes4 constant SEL_TOKEN1 = bytes4(keccak256("token1()")); // token1()
bytes4 constant SEL_GETRESERVES = bytes4(keccak256("getReserves()")); // V2: getReserves()
bytes4 constant SEL_EXTSLOAD = bytes4(keccak256("extsload(bytes32)")); // V4 probe
bytes4 constant SEL_SLOT0 = bytes4(keccak256("slot0()")); // V3 probe
bytes4 constant SEL_RECEIVER = bytes4(keccak256("rewardsReceiver()")); // Member rewards receiver
/*/////////////////////////////////////////////////////////////////////////
CONSTRUCTOR
/////////////////////////////////////////////////////////////////////////*/
/// @notice Deploys the Engine implementation and stores immutable contract references.
/// @dev
/// - Sets immutable references to MOON, SUN, and the wrapped native gas token.
/// - Proxy storage initialization happens later in `_initialize`.
/// @param moonAddress MOON ERC-20 contract used for tax collection.
/// @param sunAddress SUN ERC-20 contract used for distributions.
/// @param wbaseAddress Wrapped native gas token address (pairs with this token are untaxed).
/// @param sunDeployer Initial SUN holder; synthetic SUN seed is applied during `_initialize`.
constructor(
address moonAddress,
address sunAddress,
address wbaseAddress,
address sunDeployer
)
{
require(
moonAddress != address(0) &&
sunAddress != address(0) &&
wbaseAddress != address(0) &&
sunDeployer != address(0)
);
// Immutable configuration
moon = moonAddress;
sun = sunAddress;
wbase = wbaseAddress;
}
/*/////////////////////////////////////////////////////////////////////////
INITIALIZATION
/////////////////////////////////////////////////////////////////////////*/
/// @dev True once initialize has been executed successfully.
bool private initialized;
/// @notice Initializes engine state exactly once.
/// @dev Seeds initial member exclusions and reflection index.
function _initialize(address sunDeployer) internal {
if (initialized) revert();
require(sunDeployer != address(0), "Zero address");
initialized = true;
// Mark MOON, SUN, zero, DEAD as reflection-ineligible
Member memory m;
m.class = 3;
m.addr = moon; storeMember(m);
m.addr = sun; storeMember(m);
m.addr = DEAD; storeMember(m);
m.addr = address(0); storeMember(m);
// Seed reflection index via synthetic SUN transfer
uint sunScaled = 1e27; // 1e9 SUN with 18 decimals
_onSunTransfer(address(0), sunDeployer, sunScaled, 0, sunScaled);
}
/*/////////////////////////////////////////////////////////////////////////
VIEW GETTERS
/////////////////////////////////////////////////////////////////////////*/
/// @notice Returns the decoded global accounting state.
/// @dev Can only be called by proxy.
function getGlobalState()
external
view
onlyProxy
returns (
uint pool,
uint oath,
uint core,
uint112 index,
uint eligible,
uint minCore,
uint activeMembersLength,
uint primeMembersLength,
uint coreRaysLength,
uint edgeRaysLength,
uint activeMembersCursor,
uint primeMembersCursor,
address nextSwapRay
)
{
Global memory g = loadGlobal();
return (
g.pool,
g.oath,
g.core,
g.index,
g.eligible,
g.minCore,
g.amLen,
g.pmLen,
g.crLen,
g.erLen,
g.amCursor,
g.pmCursor,
nextSwap
);
}
/// @notice Returns the decoded stored state for a ray.
/// @dev Can only be called by proxy.
/// @param pair Ray pair address.
function getRayState(address pair)
external
view
onlyProxy
returns (
address token,
uint8 class,
bool moon0,
bool swapLock,
uint available,
uint credited,
uint value,
uint pending,
uint quote,
uint candQuote,
uint lastBlock,
int work,
bool edge,
bool core
)
{
Ray memory r;
r.pair = pair;
r = loadRay0(r);
r = loadRay1(r);
r = loadRay2(r);
return (
r.token,
r.class,
r.moon0,
r.swapLock,
r.available,
r.credited,
r.value,
r.pending,
r.quote,
r.candQuote,
r.lastBlock,
r.work,
r.edge,
r.core
);
}
/// @notice Returns stored state for a member and its current SUN balance.
/// @dev Can only be called by proxy.
/// @param member Member address.
function getMemberState(address member)
external
view
onlyProxy
returns (
address receiver,
uint currentBalance,
bool balanceOk,
uint112 pastIndex,
uint uncollected,
uint8 class,
bool active,
bool prime,
uint40 idxPlusOne,
bool redirect
)
{
Member memory m = loadMember(member);
(balanceOk, currentBalance) = _safeBalanceOf(sun, member);
return (
m.receiver,
currentBalance,
balanceOk,
m.pastIndex,
m.uncollected,
m.class,
m.active,
m.prime,
m.idxPlusOne,
m.redirect
);
}
/*/////////////////////////////////////////////////////////////////////////
MOON TRANSFER ENGINE AND TAX DETECTION
/////////////////////////////////////////////////////////////////////////*/
/// @notice Core MOON transfer hook.
/// @dev
/// - Called on every MOON transfer.
/// - Classifies each leg (from/to) via `_transferType`:
/// • Determines taxed swap vs untaxed flow.
/// • Returns per-leg tax rate.
/// - Applies tax:
/// • `fromTax` and `toTax` are proportional to `amount`.
/// • Transfer can be double taxed if `from` and `to` are both pairs.
/// - If either leg is taxed or initializes a ray:
/// • Credit work and possibly assign priority.
/// • Record pending MOON and admit rays to distribution.
/// • Run one swap-back and radiation cycle.
/// • Apply penalty work.
/// - Otherwise:
/// • No maintenance, just persist ray state.
function _onMoonTransfer(
address from,
address to,
uint256 amount
)
internal
returns (int fromTax, int toTax)
{
if (from == to) return (fromTax, toTax);
Global memory g;
// Classify: verified‑pair swap (taxed) vs everything else (untaxed)
Ray memory f;
Ray memory t;
int fTax;
int tTax;
(g, f, fTax) = _transferType(g, amount, from, true);
(g, t, tTax) = _transferType(g, amount, to, false);
// From and to legs are examined separately and have separate work accounting.
fromTax = int(amount) * fTax / 1e18;
toTax = int(amount) * tTax / 1e18;
bool fWork = (fTax > 0 || f.justInit);
bool tWork = (tTax > 0 || t.justInit);
// perform system maintenance, only if transfer is part of taxed swap or ray was initialized.
if (fWork || tWork) {
if (!g.load0) g = loadGlobal(); // If not loaded in `_transferType()`.
// credit ray with maintenance work and schedule for priority.
if (fWork) (g, f) = _creditWork(g, f, (fWork && tWork));
if (tWork) (g, t) = _creditWork(g, t, (fWork && tWork));
// Record rays pending and admit them to distribution.
if (fromTax > 0) {
(g, f) = _recordPending(g, f, uint(fromTax));
(g, f) = _admitRayDist(g, f);
}
if (toTax > 0) {
(g, t) = _recordPending(g, t, uint(toTax));
(g, t) = _admitRayDist(g, t);
}
storeRay(f);
storeRay(t);
g = _swapBack(g, f.pair, t.pair); // swapBack for another ray
g = _radiate(g); // distribute rays to members
// credit ray with maintenance penalty work.
if (fWork) _creditPenalty(g, f.pair, (fWork && tWork));
if (tWork) _creditPenalty(g, t.pair, (fWork && tWork));
} else {
storeRay(f);
storeRay(t);
}
storeGlobal(g);
return (fromTax, toTax);
}
/// @notice Distinguishes taxed swaps from untaxed LP mints, burns, and non-pair transfers.
/// @dev
/// Classification rules:
/// - This function evaluates a single transfer leg against the given address.
/// - If the address is not a class 3 pair, the transfer leg is untaxed.
/// - If the address is a class 3 pair, we check the following:
/// • If either reserve is zero (bootstrap phase), the transfer is untaxed.
/// • Opposite-sign reserve deltas indicate a swap so the transfer is taxed.
/// • Same-sign reserve deltas enter a proportionality check to confirm deltas
/// are within 10% of each other. Outside the window the transfer is taxed.
/// • Inside the window, the action is treated as an untaxed LP mint or burn,
/// a Swap-lock is enabled to confirm the LP operation later in the transaction.
///
/// Swap-lock confirmation:
/// - While swapLock is enabled, MOON requires observed reserve deltas to remain
/// consistent with an LP-style operation during final balance checks.
/// - Transactions deliberately crafted to trick tax detection will revert.
/// - This revert path should never be reachable during legitimate swaps
/// or LP operations.
/// - If an apparent LP add increases MOON balance by more than 2% of stored
/// MOON reserves, lastAdd is set to the current block to block same-block swap-back.
///
/// Expected V2 execution model:
/// - In any operation that moves tokens, the pair is expected to transfer tokens
/// first and read final balances at the end of the operation.
/// - MOON performs its initial classification during the transfer phase and
/// confirms correctness when the pair later reads balances.
/// - To distinguish LP mints and burns from swaps, MOON must be the second token
/// transferred, matching canonical V2 behavior where the lower-address token
/// is sent first and motivating MOON’s deliberately high address.
/// @param amount MOON amount moved.
/// @param addr Pair candidate for this leg.
/// @param sender true if addr is sending moon
/// @return r Ray context for taxed pair
/// @return tax Signed WAD tax rate: positive for taxed swap, zero for neutral,
/// negative for LP mint/burn classification.
function _transferType(
Global memory g,
uint amount,
address addr,
bool sender
)
internal
returns (
Global memory,
Ray memory,
int
)
{
Ray memory r;
if (amount == 0) return (g, r, 0); // UNTAXED: 0 amount.
r = _getMoonClass(addr, amount);
if (r.class != 3) return (g, r, 0); // UNTAXED: Not ray.
// All breaks will return with SWAP_TAX tax.
do {
// 1) Probe pair reserves.
if (!r.load0) r = loadRay0(r);
bool okR;
(okR, r) = _probeReserves(r);
if (!okR) break; // TAXED: Broken pair
if (r.rt == 0 && r.rm == 0) return (g, r, 0); // UNTAXED: Bootstrap
// 2) Reconcile swapLock.
if (r.swapLock) (g, r) = _reconcileSwapLock(g, r, amount, sender);
// 3) Get live moon balance.
uint bm = _moonBalance(r.pair);
(bool okB, uint bt) = _safeBalanceOf(r.token, r.pair);
if (!okB) break; // TAXED: Broken token
// 4) Calculate pair's MOON balance after transfer.
if (sender) bm = _satSub(bm, amount);
else bm = _satAdd(bm, amount);
if (bm == r.rm) return (g, r, 0); // UNTAXED: No moon delta
// 5) Easy swap test, tax if deltas are opposite sign.
bool sameSign = _sameSign(bt, r.rt, bm, r.rm);
if (!sameSign || bt == r.rt) break; // TAXED: Swap
// 6) Confirm same sign deltas are proportional.
uint dt = _diff(bt, r.rt);
uint dm = _diff(bm, r.rm);
unchecked {
// Confirm deltas are within 10% of eachother.
uint b = dm * r.rt;
uint a10 = dt * r.rm * 10;
if (a10 > b * 11 || a10 < b * 9) break; // TAXED: Unproportional
}
// 7) LP mint/burn → untaxed; engage lock until completion
r.swapLock = true;
if (_satSub(bm, r.rm) * 50 > r.rm) {
r.lastAdd = uint64(block.number);
}
return (g, r, -int(SWAP_TAX)); // UNTAXED: mint/burn
} while (false);
return (g, r, int(SWAP_TAX));
}
/// @notice Classifies an address for MOON pair semantics (tax eligibility).
/// @dev
/// - EOAs and non-V2-pair contracts are not taxed (class 1/2).
/// - Class 3 (ray) requires a canonical V2 interface:
/// • Exposes `getReserves()`, `token0()`, and `token1()`.
/// • one and only one side is MOON.
/// • The other token must respond to `balanceOf()`
/// • Neither side may be SUN or wBase(wrapped native currency).
/// - Once an address is classified as class 3:
/// • The paired token is cached.
/// • MOON directionality (token0 vs token1) is cached.
/// - Classification is cached but not immutable:
/// • EOAs that later gain code are automatically reprobed.
/// • Sending exactly `REFRESH_WEI` forces a reprobe.
/// • Class 3 (ray) is sticky and cannot be changed.
///
/// Compatibility notes for rays and paired tokens:
/// - All probed balances and reserves are saturated to uint112; excess
/// precision is intentionally discarded.
/// - Fee-on-transfer tokens are supported for distribution and can tax
/// up to (PAIR_BONUS - V2 pair fee) percent.
/// - Rays that consume excessive gas remain eligible but receive reduced
/// distribution throughput via work accounting.
/// - Tokens transferred or donated directly to the SUN are automatically
/// incorporated into the distribution system on reconciliation.
function _getMoonClass(address addr, uint amount) internal returns (Ray memory r) {
r.pair = addr;
r = loadRay1(r);
if ((r.class == 2) && amount != REFRESH_WEI || r.class == 3) return r; // Quick exit for already probed contract.
if (addr.code.length == 0) {r.class = 1; return r; } // class 1 (EOA) is never cached.
r.class = 2; // All failures below will force class 2.
bool okR = _probeOk(addr, SEL_GETRESERVES, 0, 0, GAS_PROBE_LOW, 96); // getReserves probe
if (!okR) return r;
(bool ok0, address t0) = _probeToken(addr, SEL_TOKEN0, GAS_PROBE_LOW); // token0() probe
if (!ok0 || t0 == sun || t0 == wbase ) return r; // can't be sun or wbase
(bool ok1, address t1) = _probeToken(addr, SEL_TOKEN1, GAS_PROBE_LOW); // token1() probe
if (!ok1 || t1 == sun || t1 == wbase || !(t0 == moon || t1 == moon)) return r; // one of them must be MOON
// Determine pair orientation.
address token;
bool moon0;
if (t1 == moon) { token = t0; moon0 = false; }
else if (t0 == moon) { token = t1; moon0 = true; }
(bool okB,) = _safeBalanceOf(token, addr); // token must return balance
if (!okB || token == moon) return r;
// Initialize ray state
r.class = 3;
r.token = token;
r.moon0 = moon0;
r.justInit = true; // tell _transfer() to run maintenance
r.load0 = true; // tell storeRay() to save slot0
emit RayInitialized(r.pair, r.token);
}
/// @notice Reconciles a ray's prior swap lock before current transfer classification.
/// @dev
/// - Taxes old MOON surplus still above reserves after current outgoing MOON is netted out.
/// - Records collected tax as pending ray value.
/// - Keeps `swapLock` active while an old MOON deficit remains unrepaired.
function _reconcileSwapLock(
Global memory g,
Ray memory r,
uint amount,
bool sender
)
internal
returns (Global memory, Ray memory)
{
uint bm = _moonBalance(r.pair);
// Default: old lock is resolved.
// Current transfer may set a new lock later in _transferType().
r.swapLock = false;
if (bm > r.rm) {
// Old positive MOON surplus.
uint retroBase = bm - r.rm;
// Current outgoing MOON consumes old surplus.
if (sender) retroBase = _satSub(retroBase, amount);
if (retroBase != 0) {
uint tax = retroBase * SWAP_TAX / 1e18;
uint moveAmt = IMoon(moon).kernelTransfer(r.pair, moon, tax);
if (!g.load0) g = loadGlobal();
(g, r) = _recordPending(g, r, moveAmt);
}
} else if (bm < r.rm) {
// Old negative MOON gap.
uint deficit = r.rm - bm;
// If current transfer does not repair the old deficit,
// keep the proof obligation alive.
if (sender || amount < deficit) {
r.swapLock = true;
}
// If !sender && amount >= deficit:
// old deficit is nominally repaired/crossed, so clear old lock.
// Current classification handles the transfer.
}
return (g, r);
}
/// @notice Adds MOON to a ray’s pending balance.
/// @dev
/// - Increases `r.pending` by `amount`.
/// - If pending and work thresholds are met, stages this ray in `g.nextPair` for future swapBack.
/// Design note:
/// • The work credited during ray initialization and its first taxed swap
/// is typically sufficient to satisfy `WORK_SWAPBACK`
function _recordPending(Global memory g, Ray memory r, uint amount)
internal
returns (Global memory, Ray memory)
{
r.pending += amount;
if (r.pending >= DUST &&
r.work >= WORK_SWAPBACK
) { g.nextPair = r.pair; }
return (g, r);
}
/// @notice Read‑only guard used by `balanceOf` to enforce swap‑lock semantics.
/// @dev - While `swapLock` is set and pair is querying itself, verifies (balance - reserve)
/// are the same sign for each token. If not, returns false.
/// - Returns true when unlocked but returns false if probes fail. (fails closed)
/// Note: - SwapLock is designed to revert any swaps disguised as liquidity mints/burns to avoid tax.
/// - This function ensures that the action is an authentic LP action and not a swap.
/// - This function should never return false outside of a malicious swap or broken paired token.
/// @param sender The address requesting the MOON balance; only pair self-queries are lock-checked.
/// @param pair The pair address to check.
/// @return unlocked True if the balance query is allowed to proceed.
function _isUnlocked(address sender, address pair) internal view returns (bool){
if (sender != pair) return true; // not called by self
Ray memory r;
r.pair = pair;
r = loadRay0(r);
if (!r.swapLock) return true; // lock not on
// Stored reserves
bool okR;
(okR, r) = _probeReserves(r);
if (!okR) return false; // Fail closed
// Live balances
uint bm = _moonBalance(pair);
(bool ok, uint bt) = _safeBalanceOf(r.token, pair);
if (!ok) return false; // Fail closed
// Allow if signs match
// Note: will return true if either delta is 0.
if (_sameSign(bt, r.rt, bm, r.rm)) return true;
return false;
}
/*/////////////////////////////////////////////////////////////////////////
WORK & PRIORITY ACCOUNTING
/////////////////////////////////////////////////////////////////////////*/
/// @notice Credits base work and grants emission priority to an overworked ray.
/// @dev
/// - Credits the ray with WORK_CREDIT for processing global maintenance.
/// - If a listed ray reaches `WORK_SWAPBACK` + `PRIORITY_FEE`, `PRIORITY_FEE` is spent.
/// - The ray pair is marked as priority and emitted first in this transaction.
/// @param half true if two rays are credited, each is credited half work.
function _creditWork(Global memory g, Ray memory r, bool half)
internal pure
returns (Global memory, Ray memory)
{
if (half) r.work += WORK_CREDIT/2;
else r.work += WORK_CREDIT;
if (r.work > WORK_MAX) r.work = WORK_MAX;
if (r.work >= WORK_SWAPBACK + PRIORITY_FEE &&
((r.core && !r.cStale) || (r.edge && !r.eStale)) &&
g.priority == address(0))
{
r.work -= PRIORITY_FEE;
g.priority = r.pair;
}
return (g, r);
}
/// @notice Credits a ray with work earned during the current transaction.
/// @dev
/// - Adds excess work accumulated in `g.penalty`, accumulated when other rays
/// exceeded their base gas targets in this tx. Saturated to WORK_CREDIT.
/// @param half true if two rays are credited, each is credited half work.
function _creditPenalty(Global memory g, address pair, bool half) internal {
if (g.penalty > WORK_CREDIT) g.penalty = WORK_CREDIT;
if (g.penalty > 0){
Ray memory r;
r.pair = pair;
r = loadRay1(r);
if (half) r.work += g.penalty/2;
else r.work += g.penalty;
if (r.work > WORK_MAX) r.work = WORK_MAX;
storeRay(r);
}
}
/// @notice Charges gas penalties to a ray and attributes excess work to the caller.
/// @dev
/// - `fail` = full gas used when the call fails.
/// - `over` = gas used above `limit`, regardless of success.
/// - Ray pays both `fail + over` (over is effectively doubled during failure)
/// - Global receives only `over` (failure gas is never credited).
/// @param ok Whether the bounded call succeeded; failure applies an extra penalty.
/// @param startGas Gas remaining immediately before the call, used to measure gas spent.
/// @param limit Gas target for the call; usage above this is charged as overuse work.
function _penaltyWork(
Global memory g,
Ray memory r,
bool ok,
uint startGas,
uint limit
) internal view returns (Global memory, Ray memory) {
uint used = startGas - gasleft();
int fail = ok ? int(0) : int((used + 999) / 1000);
int over = used > limit ? int((used - limit + 999) / 1000) : int(0);
if (over != 0 || fail != 0) r.work -= (over + fail);
if (over != 0) g.penalty += over;
return (g, r);
}
/*/////////////////////////////////////////////////////////////////////////
SWAPBACK (QUEUE & SWAP)
/////////////////////////////////////////////////////////////////////////*/
/// @notice Attempts one swap-back for the ray currently staged in `nextSwap`.
/// @dev
/// - Pulls the current ray from `nextSwap`.
/// - Seeds `nextSwap` from transient `g.nextPair`.
/// - Makes at most one swap-back attempt for that ray.
/// - Stops early if the ray is part of the current transaction or is not currently swappable.
/// - Stops early if the ray had a liquidity add this block (same-block pair-bonus defense).
/// - If attempted, swaps some pending MOON for the paired token through the ray pair.
/// - Reconciles only after the staged ray passes skip, pending, liquidity, and lastAdd gates.
/// @param skip1 Ray (pair) to exclude, typically the sender-side active ray in the current transfer.
/// @param skip2 Ray (pair) to exclude when both sides of the current transfer are rays.
function _swapBack(Global memory g, address skip1, address skip2)
internal
returns (Global memory)
{
bool ok;
Ray memory r;
address oldNext = nextSwap;
r.pair = oldNext;
if (oldNext != g.nextPair && g.nextPair != DEAD) nextSwap = g.nextPair; // seed nextSwap
if (r.pair == skip1 || r.pair == skip2 || r.pair == DEAD) return g; // skip active ray / no queued ray
if (g.nextPair == DEAD) nextSwap = DEAD;
r = loadRay1(r);
if (r.pending < DUST) return g; // require sufficient pending
(ok, r) = _probeReserves(r);
if (r.rm < DUST || r.rt == 0 || !ok) return g; // require sufficient liquidity
r = loadRay0(r);
if (r.lastAdd == uint64(block.number)) return g; // can't swapBack during block with mint
r = loadRay2(r);
uint maxInApp = _maxInForAppreciation(r);
uint maxInFee = (r.rm * SWAP_TAX) / 1e18;
uint amountIn = _min(uint(r.pending), maxInFee, maxInApp);
// Attempt swapBack through a bounded self-call so failures become work penalties.
if (amountIn > 0) {
uint startGasCall = gasleft();
(ok, ) = address(this).call{gas: GAS_CAP_SWAP}(
abi.encodeWithSelector(
SEL_SWAP_WITH_PAIR,
r.pair,
r.swapLock,
r.moon0,
amountIn,
r.rm,
r.rt
)
);
(g, r) = _penaltyWork(g, r, ok, startGasCall, GAS_BASE_SWAP);
if (ok) {
r.pending = _satSub(r.pending, amountIn);
r.swapLock = false; // now disabled from swapWithPair
}
}
(g, r) = _reconcileRayValue(g, r); // does not require swap
storeRay(r);
return g;
}
/// @notice Computes the maximum MOON amount that can be swapped back
/// such that remaining `pending` covers appreciation tax.
/// @dev
/// - Let x be MOON input to the swap-back.
/// - Let M = rm (MOON reserve), A = rt (token reserve).
/// - Let r = available / A, v₀ = oldValue / M, p = pending / M.
/// - Let k = APPRECIATION_TAX, b = PAIR_BONUS, α = 1 − b.
///
/// - The tax constraint k·ΔV(x) ≤ p expands to:
/// A·x² + B·x + C ≤ 0
/// where:
/// • A = b + k·(r + α)
/// • B = b·p − 1 − k·(2r + α) + k·b·v₀
/// • C = p + k·v₀ − k·r
///
/// - Solves for the largest admissible x using:
/// x = 2C / (√(B² + 4AC) − B)
///
/// - All arithmetic is executed inside `unchecked` blocks and is constructed
/// to neither revert nor wrap across the full domain of inputs.
/// - This function is an imperfect approximation whose objective is to maximize
/// swap-back efficiency while preserving the appreciation invariant.
/// - Small numerical error is acceptable and cannot violate system safety.
/// @return x Maximum safe MOON input for swap-back.
function _maxInForAppreciation(Ray memory r) internal pure returns (uint x) {
unchecked {
uint P = _cap112(r.pending);
uint M = _cap112(r.rm);
uint A = _cap112(r.rt);
if (P == 0 || M == 0 || A == 0) return 0;
uint B = _cap112(r.available);
uint V0 = _cap112(_moonVal(r.credited, r.quote)); // old value
uint WAD = 1e18;
uint bW = PAIR_BONUS; // b
uint kW = APPRECIATION_TAX; // k
uint aW = WAD - bW; // α = 1 - b
// Dimensionless ratios in WAD:
uint pW = P * WAD / M; // p = P/M
uint rW = B * WAD / A; // r = B/A
uint v0W = V0 * WAD / M; // v0 = V0/M
// C = p + k*v0 - k*r (WAD)
uint krW = kW * rW / WAD;
uint kv0W = kW * v0W / WAD;
uint CWpos = pW + kv0W;
if (CWpos <= krW) return 0;
uint CW = CWpos - krW;
// Bcoeff = b*p - 1 - k*(2r + α) + k*b*v0 (WAD, signed)
uint BWpos = bW * pW / WAD + kv0W * bW / WAD;
uint BWneg = WAD + (kW * (rW + rW + aW) / WAD);
bool bNeg = BWpos < BWneg;
uint absBW = bNeg ? (BWneg - BWpos) : (BWpos - BWneg);
// A2 = b + k*(r + α) (WAD)
uint A2W = bW + (kW * (rW + aW) / WAD);
// We need sqrt(B^2 + 4*A2*C) in WAD.
// Do it with power-of-two scaling so we never need 512-bit sqrt.
uint bwBits = absBW == 0 ? 0 : (_log2(absBW) + 1);
uint termBits = (_log2(A2W) + 1) + (_log2(CW) + 1) + 2; // +2 for the *4
uint s = bwBits > 128 ? (bwBits - 128) : 0;
if (termBits > 256) {
uint s2 = (termBits - 256 + 1) >> 1; // ceil((termBits-256)/2)
if (s2 > s) s = s2;
}
// d1 = ceil(|B|/2^s)^2 >= B^2 / 2^{2s}
uint bwCeil = absBW;
if (s != 0) {
uint mask = (uint(1) << s) - 1;
bwCeil = (absBW >> s) + ((absBW & mask) != 0 ? 1 : 0);
if (bwCeil >> 128 != 0) bwCeil = type(uint128).max; // clamp 2^128 -> 2^128-1
}
uint d1 = bwCeil * bwCeil;
// term2 = ceil(4*A2*C / 2^{2s})
// For s>=1: 4/2^{2s} = 1/2^{2s-2}
// For s==0: term2 = 4*A2*C
uint term2;
if (s == 0) {
term2 = A2W * CW * 4; // term2 = 4*A2W*CW
} else {
uint k = (s << 1) - 2; // k in [0..256] when s in [1..129]
term2 = _mulShiftUp(A2W, CW, k); // term2 = ceil(A2W*CW / 2^k)
}
uint Q = _satAdd(d1, term2);
// root = ceil_sqrt(Q) * 2^s >= sqrt(B^2 + 4*A2*C)
uint root = _isqrt(Q);
if (root * root < Q) root++;
root <<= s;
// t = 2*C / (sqrt(D) - B) (stable root form, avoids cancellation)
uint denom = bNeg ? _satAdd(root, absBW) : _satSub(root, absBW);
if (denom == 0) return 0;
uint tW = CW * 2 * WAD / denom; // WAD-scaled t
x = tW * M / WAD; // x = t*M
if (x > P) x = P;
}
}
/// @notice Internal router for MOON→token swaps on a verified V2 pair (self-call only).
/// @dev
/// - Transfers `amountIn` MOON into the pair, recomputes the *actual* input,
/// applies pair bonus, and routes output directly to SUN.
/// - Reverts on zero output to avoid no-op swaps.
/// - Allows pair fee to be <= PAIR_BONUS
/// - Orientation-aware: if MOON is token0, outputs token1; otherwise token0.
/// @param pair V2 pair to swap against.
/// @param swapLock True if swapLock is enabled for pair.
/// @param moon0 True if MOON is token0 in the pair.
/// @param amountIn Intended MOON input (ledger transfer).
/// @param reserveIn Pre-swap MOON reserve (orientation-correct).
/// @param reserveOut Pre-swap other-token reserve (orientation-correct).
function _swapWithPair(
address pair,
bool swapLock,
bool moon0,
uint amountIn,
uint reserveIn,
uint reserveOut
) internal {
if (swapLock) { // safe for internal swapBack; pair reads final balances after swap.
Ray memory r;
r.pair = pair;
r = loadRay0(r);
r.swapLock = false;
storeRay(r);
}
IMoon(moon).kernelTransfer(moon, pair, amountIn);
uint realIn = _satSub(_moonBalance(pair), reserveIn); // actual input observed by the pair
// V2 x*y = k
uint numerator = realIn * reserveOut;
uint denominator = reserveIn + realIn;
uint amountOut = (denominator == 0) ? 0 : (numerator / denominator);
// Apply pair bonus (leave a fraction in the pool).
amountOut = amountOut * (1e18 - PAIR_BONUS) / 1e18;
require(amountOut != 0);
if (moon0) {
IUniswapV2Pair(pair).swap(0, amountOut, sun, new bytes(0));
} else {
IUniswapV2Pair(pair).swap(amountOut, 0, sun, new bytes(0));
}
}
/*//////////////////////////////////////////////////////////////////////////
VALUE & QUOTE TRACKING
//////////////////////////////////////////////////////////////////////////*/
/// @notice Revalues a ray and reconciles its effect on global accounting.
/// @dev
/// - Refreshes available reserves by reconciling SUN-held token balance deltas.
/// - Updates the committed price quote using spot price and intra-block highs.
/// - Computes old vs new MOON-denominated value and applies appreciation tax:
/// • Burns from pending MOON first.
/// • Withholds unpaid appreciation by reducing credited reserves.
/// - Resolves the final ray value after tax and rounding normalization.
/// - Applies signed value deltas to global pool, core, oath, and index:
/// • Positive deltas increase pool/core and advance oath and index.
/// • Negative deltas reduce pool/core only.
/// - Evaluates and updates ray admission to core and edge distribution lists.
// NOTE:
// Any mismatch between SUN’s real token balance and `totalAvailable` is
// absorbed by the first ray touched. Donations add value here; unexpected
// losses are charged to that ray to preserve global invariants.
function _reconcileRayValue(
Global memory g,
Ray memory r
) internal returns (Global memory, Ray memory){
// Probe balance and reserves.
(bool okb, uint balance) = _safeBalanceOf(r.token, sun);
bool okr;
(okr, r) = _probeReserves(r);
if(!okb || !okr) return (g, r);
// Update rays available tokens.
// `totalAvailable[r.token]` will be updated in storeRay()
uint totalAvail = totalAvailable[r.token];
if (balance > totalAvail) {
r.available = _satAdd(r.available, balance - totalAvail);
} else {
r.available = _satSub(r.available, totalAvail - balance);
}
// Update quote.
r = _updateQuote(r);
// Apply appreciation tax and calculate new value.
uint oldVal = r.value;
r = _applyAppTax(r); // updates r.value
// apply value change to global accounting
int delta = int(r.value) - int(oldVal);
(g, r) = _updateGlobalValue(g, r, delta);
// admit to distribution lists if thresholds are met.
(g, r) = _admitRayDist(g, r);
return (g, r);
}
/// @notice Applies a ray value delta to global accounting.
/// @dev
/// - Positive change increases `pool` and `core` if ray is in core,
/// and advances both `oath` and `index` when eligible supply exists.
/// - Negative change reduces `pool` and `core` only.
/// - No effect if the ray is not in edge or core distribution.
function _updateGlobalValue(Global memory g, Ray memory r, int change)
internal
pure
returns (Global memory, Ray memory)
{
if (r.core || r.edge) {
if (change > 0) {
uint inc = uint(change);
g.pool = _satAdd(g.pool, inc);
if (r.core) g.core = _satAdd(g.core, inc);
if (g.eligible > 0) {
g.oath = _satAdd(g.oath, inc);
unchecked { g.index += _cap112(_mulDivDown(inc, 1e27, g.eligible)); } // index can wrap
}
} else {
uint dec = uint(-change);
g.pool = _satSub(g.pool, dec);
if (r.core) g.core = _satSub(g.core, dec);
}
}
return(g, r);
}
/// @notice Applies appreciation tax coverage for positive ray value changes.
/// @dev
/// - Recomputes the ray’s MOON-denominated value using the committed quote.
/// - If fullVal increased vs `r.value`, a tax equal to
/// ceil(APPRECIATION_TAX × (fullVal − r.value))
/// must be paid to unlock the appreciation.
/// - Payment is taken from `r.pending` first by burning MOON.
/// - Any unpaid portion is withheld by reducing `r.credited`,
/// preventing untaxed value from entering the distribution pool.
///
/// Note:
/// Withheld (available but uncredited) reserves are not lost.
/// They remain parked on the ray and can be rapidly unlocked later
/// when additional pending MOON arrives, at an effective 1 / APPRECIATION_TAX ratio.
function _applyAppTax(
Ray memory r
)
internal
returns (Ray memory)
{
if (r.quote == 0) return r;
uint fullVal = _moonVal(r.available, r.quote);
if (fullVal > r.value) {
if (r.pending != 0){
uint dVal;
unchecked { dVal = fullVal - r.value; } // untaxed increase
// Burn pending to unlock value.
uint unpaidTax = _mulDivUp(dVal, APPRECIATION_TAX, 1e18);
uint payNow = _min(unpaidTax, r.pending, _moonBalance(moon)); // cap to what is available
IMoon(moon).kernelTransfer(moon, DEAD, payNow);
unchecked { r.pending -= payNow; }
// Unlock new taxed value.
uint unlockVal = _mulDivDown(payNow, 1e18, APPRECIATION_TAX);
r.value = _satAdd(r.value, unlockVal);
}
r.credited = _mulDivDown(r.value, 1e38, r.quote); // convert back into tokens
if (r.credited > r.available) r.credited = r.available; // saturate
} else r.credited = r.available;
r.credited = _roundFloat73(r.credited); // canonicalize so encode→decode doesn’t change value
r.value = _moonVal(r.credited, r.quote);
return r;
}
/// @notice Updates a ray’s committed quote using spot and intra‑block highs.
/// @dev
/// Policy:
/// - If spot > committed: lift immediately (quote=candidate=spot).
/// - Same block: candidate tracks the running max.
/// - New block: commit last block’s high to `quote`, seed `candidate` with current spot.
/// Quotes are 1e38‑scaled MOON‑per‑token and encoded/decoded via Float96.
/// Note: This system prevents artificial price dips that increase ray emission amount.
function _updateQuote(Ray memory r)
internal
view
returns (Ray memory)
{
// Need nonzero reserves to form a spot quote.
if (r.rt == 0 || r.rm == 0) return r;
uint spot = _roundFloat96(r.rm * 1e38 / r.rt);
uint64 currentBlock = uint64(block.number);
if (r.lastBlock != currentBlock) {
// New block: commit last block’s intra-block high; seed candidate with current spot.
r.quote = r.candQuote;
r.candQuote = spot;
r.lastBlock = currentBlock;
} else if (spot > r.candQuote) {
// Same block: candidate tracks running max.
r.candQuote = spot;
}
if (r.candQuote > r.quote) r.quote = r.candQuote; // always raise quote to candidate.
return r;
}
/// @notice Manages ray admission into the core and edge distribution lists.
/// @dev
/// - Determines whether a ray should be admitted to `coreRays` or `edgeRays`
/// based on its value, work, and dynamic core threshold.
/// - Core admission criteria:
/// • Not already core
/// • work greater then `WORK_DISTRIBUTION`
/// • value ≥ `g.minCore`
/// - Edge admission criteria:
/// • Not already edge or core
/// • work greater then `WORK_DISTRIBUTION`
/// • value ≥ DUST
/// - Admission effects:
/// • Adds the ray to the appropriate list
/// • Adds ray value to the global pool on first admission
/// • Adds value to `g.core` when admitted or promoted to core
function _admitRayDist(Global memory g, Ray memory r) internal returns(Global memory, Ray memory){
if (r.core) return (g, r);
if (r.work < WORK_DISTRIBUTION) return (g, r); // not enough work.
if (!r.load2) r = loadRay2(r);
if (r.value < DUST) return (g, r); // not enough value.
if (r.value >= g.minCore) {
r.core = true;
r.cStale = false;
(g,) = _addToList(g, CORERAYS, r.pair);
if (!r.edge) (g, r) = _updateGlobalValue(g, r, int(r.value)); // adds value to core and pool
else g.core = _satAdd(g.core, r.value);
} else if (!r.edge) {
r.edge = true;
r.eStale = false;
(g,) = _addToList(g, EDGERAYS, r.pair);
if (!r.core) (g, r) = _updateGlobalValue(g, r, int(r.value)); // adds value to pool
}
return (g, r);
}
/*/////////////////////////////////////////////////////////////////////////
EMISSION ENGINE (RADIATION & PAYOUT)
/////////////////////////////////////////////////////////////////////////*/
/// @notice Distributes accumulated ray value to SUN members under a fixed gas budget.
/// @dev
/// - Selects between prime and active member lists by weighted round-robin,
/// with prime capped to at least half.
/// - Uses `_emitRay` to settle accrued member value from core and edge rays.
/// - Persists the last touched ray after the loop.
/// - Stops when gas is exhausted or no eligible emissions remain.
function _radiate(Global memory g)
internal
returns (Global memory)
{
Ray memory r;
bool pickPrime;
// Gas budget is decreased if SwapBack went over BASE.
uint budgetGas = GAS_RADIATE;
if (g.penalty != 0) budgetGas = _satSub(budgetGas, uint(g.penalty) * 1000);
// Loop through members using weighted round-robin between prime and active lists.
uint startGas = gasleft();
while (startGas - gasleft() < budgetGas &&
g.pool >= DUST &&
g.oath >= DUST)
{
Member memory m;
// Picks prime or active based on size (prime is chosen at least half the time).
(pickPrime, g.mPhase) = chooseList(g.pmLen, g.amLen, g.mPhase);
if ((pickPrime || g.amLen == 0) && g.pmLen != 0){
pickPrime = true; // emit to prime member
if (g.pmCursor >= g.pmLen) g.pmCursor = 0;
m = loadMember(get(PRIMEMEMBERS, g.pmCursor));
} else {
if (g.amLen == 0) break; // no one to emit to
pickPrime = false; // emit to active member
if (g.amCursor >= g.amLen) g.amCursor = 0;
m = loadMember(get(ACTIVEMEMBERS, g.amCursor));
}
// Attempt emission to member.
uint gasLeft = _satSub(gasleft() + budgetGas, startGas);
(g, r) = _emitRay(g, r, m, gasLeft, 3); // emit up to 3 rays to member
unchecked {
if (pickPrime) ++g.pmCursor;
else ++g.amCursor;
}
}
if (r.pair != address(0)) storeRay(r); // Persist new credited reserve
return g;
}
/// @notice Settles a SUN member’s accrued MOON-value by emitting value from rays.
/// @dev
/// - Accrues the member’s uncollected MOON-denominated claim via {_recordUncollected}.
/// - Selects rays from the core or edge lists, weighted by pool/core value share.
/// - Converts the member’s unscaled claim into a scaled payout using the live
/// coverage ratio (pool / oath).
/// - Releases paired-token value from SUN to the member when possible.
/// - On success, debits the member/oath claim; failed releases still remove ray value from pool.
/// - Ray value is removed from the pool regardless of transfer success, ensuring
/// grief resistance and invariant preservation.
/// - Failed releases or rays that fall below thresholds are lazily removed
/// from distribution lists.
/// - Returns the last touched ray for caller-side persistence.
/// @param r Reusable ray cursor; persisted only when required.
/// @param gasBudget Gas available for emission work.
/// @param maxSteps Maximum rays that may be emitted from in this call.
function _emitRay(
Global memory g,
Ray memory r,
Member memory m,
uint gasBudget,
uint maxSteps
) internal returns (Global memory, Ray memory) {
// Get members current claim.
(, m.balance) = _safeBalanceOf(sun, m.addr);
m = _recordUncollected(g, m);
if (m.uncollected < DUST) return (g, r); // skip storeMember (gas savings)
uint seed; // entropy for ray selection
uint steps; // settle against at most maxSteps rays.
uint startGas = gasleft();
uint stopGas;
unchecked { stopGas = startGas > gasBudget ? (startGas - gasBudget) : 0; }
while (
steps < maxSteps &&
m.uncollected >= DUST &&
g.pool >= DUST &&
g.oath >= DUST &&
gasleft() > stopGas
) {
unchecked { ++steps; }
// Select ray.
if (r.pair == address(0)) {
if (g.priority != address(0)) { // priority ray is used first
r.pair = g.priority;
} else {
if (seed == 0) { // generate seed from prevrandao + member entropy.
seed = uint(keccak256(abi.encodePacked(block.prevrandao, m.addr)));
} else { // cheap XOR shift to mix the seed between members.
unchecked {
seed ^= (seed << 13);
seed ^= (seed >> 7);
seed ^= (seed << 17);
}
}
// Pick core or edge proportional to value held (edge is chosen at least half the time).
bool pickEdge;
(pickEdge, g.rPhase) = chooseList(_satSub(g.pool, g.core), g.core, g.rPhase);
if ((pickEdge || g.crLen == 0) && g.erLen != 0) { // edge pick
r.edgePick = true;
r.cursor = seed % g.erLen;
r.pair = get(EDGERAYS, r.cursor);
} else { // core pick
if(g.crLen == 0) break;
r.corePick = true;
r.cursor = seed % g.crLen;
r.pair = get(CORERAYS, r.cursor);
}
}
r = loadRay1(r);
r = loadRay2(r);
}
// Attempt ray payout.
bool ok;
if (r.value >= DUST && r.work > WORK_REMOVAL && r.quote != 0) {
if (!r.load0) r = loadRay0(r);
// Scale the member’s unscaled claim by the live coverage ratio.
uint scaled = _mulDivDown(m.uncollected, g.pool, g.oath);
// Convert scaled MOON-value into token amount
uint payAmt = _mulDivUp(scaled, 1e38, r.quote); // 1 wei floor
if (payAmt > r.credited) payAmt = r.credited;
// Reduce credited reserve.
r.credited = _satSub(r.credited, payAmt);
r.credited = _roundFloat73(r.credited); // canonicalize so encode→decode doesn’t change value
// Calculate exact change in value.
uint oldVal = r.value;
r.value = _moonVal(r.credited, r.quote);
uint payVal = oldVal - r.value; // realized value (no rounding)
// Attempt release from SUN.
if (payAmt > 0) {
uint startCallGas = gasleft();
(ok, ) = sun.call{gas: GAS_CAP_RELEASE}(
abi.encodeWithSelector(ISun.releaseToMember.selector, r.token, payAmt, m.receiver, true));
(g, r) = _penaltyWork(g, r, ok, startCallGas, GAS_BASE_RELEASE);
} else ok = true;
// If the transfer succeeds, debit unscaled claim, oath and available balance.
if (ok) {
r.available = _satSub(r.available, payAmt);
uint payValUnscaled = _mulDivDown(payVal, uint(g.oath), uint(g.pool)); // scale back to original claim.
if (payValUnscaled > m.uncollected) payValUnscaled = m.uncollected; // safety clamp
m.uncollected = m.uncollected - _cap96(payValUnscaled);
g.oath = _satSub(g.oath, payValUnscaled);
}
(g, r) = _updateGlobalValue(g, r, -int(payVal)); // pool reduced regardless of transfer success
}
// Update rays inclusion in distribution lists, remove if cursor known.
if (r.pair != address(0)) (g, r) = _removeRayDist(g, r, ok);
}
storeMember(m);
return (g, r);
}
/// @notice Removes or updates a ray in the distribution lists.
/// @dev
/// - Evaluates whether the ray has become stale based on value and work.
/// - All rays become stale if `belowEdge`, with core rays additionally
/// becoming stale if below half `g.minCore`
/// - If stale and the cursor is known, removes the ray immediately.
/// - Otherwise, marks the ray as stale for lazy cleanup.
/// - If removed from core, adds back to edge if eligible.
/// - If the ray exits both core and edge lists, its value is removed from the pool.
/// - On removal, failure, or priority is stale, resets the ray cursor.
/// @param ok true if release was successful.
/// @return Updated global accounting and ray state.
function _removeRayDist(Global memory g, Ray memory r, bool ok)
internal
returns (Global memory, Ray memory)
{
// determine if ray is below minimum distribution requirements.
bool belowEdge = r.value < DUST || r.work <= WORK_REMOVAL;
// should r be reset for new ray.
bool reset = !ok || (g.priority != address(0) && (belowEdge));
// update core staleness and remove if cursor known.
if (r.core) r.cStale = belowEdge || (r.value * 2) < g.minCore;
if (r.corePick && r.cStale) {
(g, ) = _removeFromList(g, CORERAYS, r.cursor);
g.core = _satSub(g.core, r.value);
r.core = false;
r.cStale = false;
reset = true;
// If still above thresholds, add to edge.
if (!r.edge && !belowEdge) {
(g,) = _addToList(g, EDGERAYS, r.pair);
r.edge = true;
r.eStale = false;
}
}
// update edge staleness and remove if cursor known.
if (r.edge) r.eStale = belowEdge || r.core;
if (r.edgePick && r.eStale) {
(g, ) = _removeFromList(g, EDGERAYS, r.cursor);
r.edge = false;
r.eStale = false;
reset = true;
}
// Remove from pool if in neither list.
if (!r.core && !r.edge) {
g.pool = _satSub(g.pool, r.value);
r.credited = 0; // clear value
}
// Reset for new ray selection.
if (reset) {
g.priority = address(0);
storeRay(r);
Ray memory resetRay;
r = resetRay;
}
return(g, r);
}
/*/////////////////////////////////////////////////////////////////////////
SUN ACCOUNTING AND ENTRY POINTS
/////////////////////////////////////////////////////////////////////////*/
/// @notice Claims caller’s SUN emissions and opportunistically advances maintenance.
/// @dev If eligible, settles the caller against up to 6 rays under a 300k gas budget.
/// Does not run swapBack or general radiation. Calling is optional; emissions accrue automatically.
function _collect(address sender) internal {
// Snapshot caller and their membership record.
Member memory m = loadMember(sender);
Global memory g = loadGlobal();
// If the caller is an eligible SUN holder, settle their pending value.
if (m.class == 1 || m.class == 2) {
Ray memory r;
(g, r) = _emitRay(g, r, m, 300_000, 6); // 300k gas and 6 ray limit
if (r.pair != address(0)) storeRay(r);
storeGlobal(g);
}
}
/// @notice Hooks SUN transfers into MOON accounting.
/// @dev
/// - Called only by SUN via the internal router.
/// - Accrues uncollected MOON-value for sender and receiver using pre-transfer balances.
/// - Updates global eligible SUN supply when class boundaries are crossed.
/// - Maintains active and prime member lists based on post-transfer balances.
/// - Does not move tokens; may perform bounded static probes during member classification.
function _onSunTransfer(
address from,
address to,
uint fromBal,
uint toBal,
uint amount
) internal {
if (amount == 0 || from == to) return;
Global memory g = loadGlobalLight();
Member memory f;
Member memory t;
(g, f) = _getSunClass(g, from, fromBal, amount);
(g, t) = _getSunClass(g, to, toBal, amount);
// Accrue `uncollected` using the pre-transfer balances at this index.
f = _recordUncollected(g, f);
t = _recordUncollected(g, t);
// Update global count of eligible (class-1) SUN tokens used by index math.
g = _updateEligible(g, f, t, amount);
// Maintain member rotations: eligible balances above MIN_ACTIVE are listed.
unchecked {f.balance -= amount; t.balance += amount;} // Calculate post transfer balances.
(g, f, t) = _updateMemberLists(g, f, t);
(g, t, f) = _updateMemberLists(g, t, f);
storeMember(f);
storeMember(t);
storeGlobal(g);
return;
}
/// @notice Classifies a SUN holder for reflection eligibility.
/// @dev
/// - EOAs and non-pair contracts are eligible for rewards (class 1/2).
/// - Contracts with a valid `rewardsReceiver()` will have rewards redirected
/// to that address and are forced to class 2.
/// - Addresses that positively match an AMM probe are ineligible (class 3):
/// • V2-style pairs via `getReserves()`
/// • V3-style pools via `slot0()`
/// • V4-style pool managers via `extsload(bytes32)`
/// - If an address flips from eligible (class 1/2) to ineligible (class 3),
/// any uncollected value is recycled back into the system.
/// - Classification is cached but not immutable:
/// • EOAs that later gain code are automatically reprobed.
/// • Sending exactly `REFRESH_WEI` forces a reprobe.
/// • Class 3 (ineligible) is sticky and cannot be changed.
function _getSunClass(Global memory g, address addr, uint balance, uint amount)
internal
returns (Global memory, Member memory)
{
Member memory m = loadMember(addr);
m.balance = balance;
if ((m.class == 2 && amount != REFRESH_WEI) || m.class == 3) return (g, m); // quick exit for already probed contract
if (addr.code.length == 0) { m.class = 1; return (g, m); } // EOAs eligible by default
// Test for reward redirection receiver.
(bool okRR, address rec) = _probeToken(addr, SEL_RECEIVER, GAS_PROBE_HIGH);
m.redirect = okRR && rec != address(0) && rec != addr && rec != sun; // receiver cannot be sun, address(0) or self
if (!m.redirect) delete memberReceiver[addr];
if (m.redirect || (okRR && rec == addr)) {
if (m.redirect) memberReceiver[addr] = rec; // only use redirect slot if redirect is not self
m.class = 2; // eligible non-pair contract
return (g, m);
}
// Test for ineligibility.
bool okV2 = _probeOk(addr, SEL_GETRESERVES, 0, 0, GAS_PROBE_HIGH, 96); // 1) V2 probe: getReserves() returns 96 bytes
if (!okV2) {
bool okV3 = _probeOk(addr, SEL_SLOT0, 0, 0, GAS_PROBE_HIGH, 224); // 2) V3 probe: slot0() returns 224 bytes (7 ABI words)
if (!okV3) {
bool okV4 = _probeOk(addr, SEL_EXTSLOAD, 0, 1, GAS_PROBE_HIGH, 32); // 3) V4 probe: extsload(bytes32) returns 32 bytes
if (!okV4) {
m.class = 2; // eligible non-pair contract
return (g, m);
}
}
}
// Mark ineligible and remove from accounting.
if (m.balance != 0 || m.uncollected != 0) {
g.eligible = _satSub(g.eligible, m.balance);
m = _recordUncollected(g, m);
Global memory gFull = loadGlobal(); // safe, only oath is mutated and nothing else. Caller doesn't touch slot2
gFull.oath = _satSub(gFull.oath, m.uncollected); // Remove claim from oath
storeGlobal(gFull);
m.uncollected = 0;
}
m.class = 3; // ineligible pair contract.
return (g, m);
}
/// @notice Accrues a member’s uncollected nominal claim based on the global index.
/// @dev
/// - Computes the incremental nominal claim accumulated since the member’s last
/// snapshot using:
/// (SUN balance × (globalIndex − pastIndex)) / 1e27.
/// - Rounds to nearest (ties round down) to maintain deterministic aggregation.
/// - Updates `pastIndex` to the current global index.
/// - No-op if the member is ineligible, has zero balance, or the index is unchanged.
function _recordUncollected(Global memory g, Member memory m)
internal
pure
returns (Member memory)
{
if (m.oldClass != 0 && m.class != 3 && m.balance != 0 && g.index != m.pastIndex) {
uint112 delta;
unchecked { delta = g.index - m.pastIndex; } // index advances modulo uint112; unchecked math supports wrap
// Newly earned unscaled value rounded to nearest
uint num = uint(m.balance) * uint(delta);
uint add = num / 1e27;
uint rem = num - add * 1e27;
if (rem * 2 > 1e27) {
unchecked { add += 1; } // strictly above half -> round up
}
m.uncollected = _satAdd(m.uncollected, add);
}
m.pastIndex = g.index;
return m;
}
/// @notice Adjusts global eligible SUN supply when tokens enter/exit ineligible class 3.
/// @dev
/// - Adjusts eligible supply when tokens move between eligible classes `!= 3` and ineligible class `3`.
/// @param amount SUN amount moved (1e18‑scaled).
function _updateEligible(
Global memory g,
Member memory f,
Member memory t,
uint amount
) internal pure returns(Global memory) {
if (f.class == 3 && t.class != 3) {
g.eligible = _satAdd(g.eligible, amount); // Enter eligible
} else if (f.class != 3 && t.class == 3) {
g.eligible = _satSub(g.eligible, amount); // Leave eligible
}
return g;
}
/// @notice Updates a member’s active/prime list membership.
/// @dev
/// - Prime and active membership are mutually exclusive.
function _updateMemberLists(Global memory g, Member memory m, Member memory o)
internal
returns (Global memory, Member memory, Member memory)
{
bool primeOk = m.class != 3 &&
m.balance >= MIN_PRIME;
bool activeOk = m.class != 3 &&
(m.balance >= MIN_ACTIVE) &&
!primeOk;
// Leave lists if no longer eligible
if (m.prime && !primeOk) {
(g, m, o) = _removeMember(g, m, o, true);
} else if (m.active && !activeOk) {
(g, m, o) = _removeMember(g, m, o, false);
}
// Enter lists if newly eligible
if (!m.prime && primeOk) {
uint idx;
(g, idx) = _addToList(g, PRIMEMEMBERS, m.addr);
m.idxPlusOne = uint40(idx + 1);
m.prime = true;
} else if (!m.active && activeOk) {
uint idx;
(g, idx) = _addToList(g, ACTIVEMEMBERS, m.addr);
m.idxPlusOne = uint40(idx + 1);
m.active = true;
}
return (g, m, o);
}
/// @notice Removes a member from the active or prime list.
/// @dev
/// - Uses swap-pop removal.
/// - Repairs idxPlusOne for the moved member.
/// - Clears active and prime flags and idxPlusOne.
/// - Updates list length in Global.
/// - Safe no-op if the member is not listed.
function _removeMember(Global memory g, Member memory m, Member memory o, bool isPrime)
internal
returns (Global memory, Member memory, Member memory)
{
if (m.idxPlusOne == 0) return (g, m, o); // inconsistent list metadata; treat as already removed
uint base = isPrime ? PRIMEMEMBERS : ACTIVEMEMBERS;
uint len = isPrime ? g.pmLen : g.amLen;
uint idx = uint(m.idxPlusOne) - 1;
m.idxPlusOne = 0;
if (idx >= len) {
return (g, m, o); // inconsistent list metadata; treat as already removed
}
m.prime = false;
m.active = false;
// Swap-pop remove; returns the element moved into `idx` (or 0 if idx==last)
address moved;
(g, moved) = _removeFromList(g, base, idx);
// Fix the moved member’s idxPlusOne (it is now sitting at `idx`)
if (moved != address(0)) {
if (moved == o.addr) {
o.idxPlusOne = uint40(idx + 1);
} else {
Member memory s= loadMember(moved);
s.idxPlusOne = uint40(idx + 1);
storeMember(s);
}
}
return (g, m, o);
}
/*/////////////////////////////////////////////////////////////////////////
LIST HELPERS
/////////////////////////////////////////////////////////////////////////*/
/// @notice Deterministically selects A or B by weighted round-robin.
/// @dev Uses a 2^18 scale so `acc` fits in 19 bits even after the temporary add.
/// B is always capped to A so A gets at least 50% when both lists are nonempty.
/// @param aLen Current A weight.
/// @param bLen Current B weight.
/// @param acc Prior 2^18-scaled accumulator.
/// @return useA True for A, false for B.
/// @return newAcc Updated accumulator.
function chooseList(
uint256 aLen,
uint256 bLen,
uint256 acc
) internal pure returns (bool useA, uint256 newAcc) {
if (aLen == 0) return (false, acc);
if (bLen == 0) return (true, acc);
if (bLen > aLen) bLen = aLen; // enforce A gets as much as B
unchecked {
acc += (aLen << 18) / (aLen + bLen);
if (acc >= 1 << 18) {
acc -= 1 << 18;
return (true, acc);
}
}
return (false, acc);
}
/// @dev Element slot = (listId << 39) + index.
/// Each list owns a disjoint 2^39-sized storage window.
function _listElemSlot(uint listId, uint index)
internal
pure
returns (bytes32 slot)
{
unchecked {
slot = bytes32((listId << 39) | index);
}
}
/// @dev sload address stored in a slot (mask to 160 bits).
function _sloadAddr(bytes32 slot) internal view returns (address a) {
assembly ("memory-safe") {
a := and(sload(slot), 0xffffffffffffffffffffffffffffffffffffffff)
}
}
/// @dev sstore address into a slot.
function _sstoreAddr(bytes32 slot, address a) internal {
assembly ("memory-safe") {
sstore(slot, a)
}
}
/// @dev Read the authoritative logical length from Global for a given listId.
function _getListLen(Global memory g, uint listId) internal pure returns (uint) {
if (listId == EDGERAYS ) return g.erLen;
if (listId == CORERAYS ) return g.crLen;
if (listId == ACTIVEMEMBERS) return g.amLen;
if (listId == PRIMEMEMBERS ) return g.pmLen;
revert();
}
/// @dev Write the authoritative logical length into Global for a given listId.
function _setListLen(Global memory g, uint listId, uint newLen) internal pure {
if (listId == EDGERAYS ) { g.erLen = newLen; return; }
if (listId == CORERAYS ) { g.crLen = newLen; return; }
if (listId == ACTIVEMEMBERS) { g.amLen = newLen; return; }
if (listId == PRIMEMEMBERS ) { g.pmLen = newLen; return; }
revert();
}
function get(uint listId, uint index)
internal
view
returns (address)
{
bytes32 slot = _listElemSlot(listId, index);
return _sloadAddr(slot);
}
/// @notice Manual “push” into one of the active manual lists.
/// @dev Stores `item` at element[len] and increments the Global length.
/// @return index The index the item was inserted at.
function _addToList(
Global memory g,
uint listId,
address item
)
internal
returns (Global memory, uint index)
{
uint len = _getListLen(g, listId);
if (len == MASK_39) revert();
bytes32 slot = _listElemSlot(listId, len);
_sstoreAddr(slot, item);
_setListLen(g, listId, len + 1);
return (g, len);
}
/// @notice Manual “swap-pop remove” from one of the active manual lists.
/// @dev Does NOT clear the old last slot (gas savings).
/// @return moved The element that got moved into `i` (zero if i == last).
function _removeFromList(
Global memory g,
uint listId,
uint i
)
internal
returns (Global memory, address moved)
{
uint len = _getListLen(g, listId);
if(len == 0) return (g, address(0));
uint last = len - 1;
if(i > last) return (g, address(0));
bytes32 slotI = _listElemSlot(listId, i);
if (i != last) {
bytes32 slotLast = _listElemSlot(listId, last);
moved = _sloadAddr(slotLast);
_sstoreAddr(slotI, moved);
} else moved = address(0);
_setListLen(g, listId, last);
return (g, moved);
}
/*/////////////////////////////////////////////////////////////////////////
STORAGE HELPERS
/////////////////////////////////////////////////////////////////////////*/
uint private constant MASK_2 = (uint(1) << 2) - 1; // 2 bits
uint private constant MASK_12 = (uint(1) << 12) - 1; // 12 bits
uint private constant MASK_13 = (uint(1) << 13) - 1; // 13 bits
uint private constant MASK_19 = (uint(1) << 19) - 1; // 19 bits
uint private constant MASK_22 = (uint(1) << 22) - 1; // 22 bits
uint private constant MASK_39 = (uint(1) << 39) - 1; // 39 bits
uint private constant MASK_40 = (uint(1) << 40) - 1; // 40 bits
uint private constant MASK_62 = (uint(1) << 62) - 1; // 62 bits
uint private constant MASK_73 = (uint(1) << 73) - 1; // 73 bits
uint private constant MASK_90 = (uint(1) << 90) - 1; // 90 bits
uint private constant MASK_92 = (uint(1) << 92) - 1; // 92 bits
uint private constant MASK_97 = (uint(1) << 97) - 1; // 97 bits
/// @notice Loads global slot0 + slot1 (light) if not already loaded.
/// @dev Ray-style: respects g.load0/g.load1 and only SLOADs missing slots.
function loadGlobalLight() internal view returns (Global memory g) {
uint x = packedGlobal0;
g.slot0 = x;
g.load0 = true;
// slot0
g.index = uint112(x);
g.eligible = uint((x >> 112) & MASK_92); // stored uint92
g.amLen = uint((x >> 204) & MASK_39); // stored uint39
g.bits0 = uint16(x >> 243); // stored uint13
uint y = packedGlobal1;
g.slot1 = y;
g.load1 = true;
// slot1
g.amCursor = uint(y & MASK_39);
g.pmCursor = uint((y >> 39) & MASK_39);
g.erLen = uint((y >> 78) & MASK_39);
g.crLen = uint((y >> 117) & MASK_39);
g.pmLen = uint((y >> 156) & MASK_39);
g.rPhase = uint((y >> 195) & MASK_19);
g.mPhase = uint((y >> 214) & MASK_19);
g.bits1 = uint32((y >> 233) & MASK_22); // stored uint22
return g;
}
/// @notice Loads slot0 + slot1 + slot2 (full) if not already loaded.
/// @dev Calls loadGlobalLight first to ensure bits0/bits1 are available for core reconstruction.
function loadGlobal() internal view returns (Global memory g) {
g = loadGlobalLight();
uint z = packedGlobal2;
g.slot2 = z;
g.load2 = true;
g.oath = uint(z & MASK_97);
g.pool = uint((z >> 97) & MASK_97);
uint coreLo62 = uint(z >> 194) & MASK_62;
// core = low62 | (bits0<<62) | (bits1<<75)
g.core = coreLo62 | (uint(g.bits0) << 62) | (uint(g.bits1) << 75);
// only refreshed once when globals are loaded, never stored.
g.minCore = DUST;
if (g.pool != 0 && g.core != 0) {
// This curve was chosen deliberately because it ramps up fast and gives the
// core threshold the desired shape.
unchecked {
uint base = (g.core * 1e10 / g.pool); // (1e10-scaled)
base = base > 1e10 ? 1e10 : base; // saturate to 1
uint ratio = base * base * base * base / 1e30;
g.minCore += 0.1e10 * ratio * g.pool / 1e20; // 0.1(core/pool)^4 * pool + DUST (1e18-scaled)
}
}
g.nextPair = DEAD; // avoids writing address(0) to nextPair.
return g;
}
/// @notice stores any loaded global slots back to storage, skipping unchanged words.
function storeGlobal(Global memory g) internal {
// If slot2 is loaded, core’s high bits live in slot0/slot1, so ensure light is loaded.
if (g.load2 && (!g.load0 || !g.load1)) revert();
// Canonicalize core bits into bits0/bits1 when slot2 is in play.
if (g.load2) {
uint core97 = _cap97(g.core);
uint c = core97;
g.bits0 = uint16((c >> 62) & MASK_13); // core[62..74]
g.bits1 = uint32((c >> 75) & MASK_22); // core[75..96]
g.core = core97; // keep in-memory canonical too
}
// slot0 pack/write
if (g.load0) {
if (g.eligible > MASK_92) g.eligible = MASK_92;
uint new0 =
uint(uint112(g.index)) |
(uint(g.eligible) << 112) |
(uint(_cap39(g.amLen)) << 204) |
(uint(uint16(g.bits0) & uint16(MASK_13)) << 243);
if (new0 != g.slot0) {
packedGlobal0 = new0;
g.slot0 = new0;
}
}
// slot1 pack/write
if (g.load1) {
uint new1 =
uint(_cap39(g.amCursor)) |
(uint(_cap39(g.pmCursor)) << 39) |
(uint(_cap39(g.erLen)) << 78) |
(uint(_cap39(g.crLen)) << 117) |
(uint(_cap39(g.pmLen)) << 156) |
(uint(g.rPhase & MASK_19) << 195) |
(uint(g.mPhase & MASK_19) << 214) |
(uint(uint32(g.bits1) & uint32(MASK_22)) << 233);
if (new1 != g.slot1) {
packedGlobal1 = new1;
g.slot1 = new1;
}
}
// slot2 pack/write
if (g.load2) {
uint oath97 = _cap97(g.oath);
uint pool97 = _cap97(g.pool);
uint core97 = _cap97(g.core);
uint coreLo62 = core97 & MASK_62;
uint new2 =
uint(oath97) |
(uint(pool97) << 97) |
(uint(coreLo62) << 194);
if (new2 != g.slot2) {
packedGlobal2 = new2;
g.slot2 = new2;
}
}
}
/// @notice Loads ray slot0 (token, moon0, swapLock, lastAdd) from storage into `r`.
/// @dev Expects `r.pair` to be set. Sets `r.load0 = true` and copies the raw packed word into `r.slot0`.
function loadRay0(Ray memory r)
internal
view
returns (Ray memory)
{
uint x = rays[r.pair].slot0;
r.slot0 = x;
r.load0 = true;
r.token = address(uint160(x));
r.moon0 = ((x >> 160) & 1) != 0;
r.swapLock = ((x >> 161) & 1) != 0;
r.lastAdd = uint64(x >> 162);
return r;
}
/// @notice Loads ray slot1 (available, credited, class, pending, work, flags) from storage into `r`.
/// @dev Expects `r.pair` to be set. Sets `r.load1 = true` and copies the raw packed word into `r.slot1`.
/// Uses float73 for `available` and `credited` and stores `r.class` in a contiguous 2-bit field.
function loadRay1(Ray memory r)
internal
view
returns (Ray memory)
{
uint x = rays[r.pair].slot1;
r.slot1 = x;
r.load1 = true;
// [0..72] available73, [73..145] credited73
uint avail73 = x & MASK_73;
uint cred73 = (x >> 73) & MASK_73;
r.available = _decodeFloat73(avail73);
r.credited = _decodeFloat73(cred73);
// [146..147] class2 (contiguous)
r.class = uint8((x >> 146) & MASK_2);
// [148..237] pending90 (unsigned)
r.pending = (x >> 148) & MASK_90;
// [238..249] work12 (signed two's complement)
uint wBits = (x >> 238) & MASK_12;
r.work = (wBits & 0x800) != 0
? int16(int256(wBits) - 4096)
: int16(int256(wBits));
// [250..255] flags6
uint f = x >> 250;
r.edge = (f & 2) != 0;
r.core = (f & 4) != 0;
r.eStale = (f & 8) != 0;
r.cStale = (f & 16) != 0;
r.moon0 = (f & 32) != 0;
return r;
}
/// @notice Loads ray slot2 (quote96, candQuote96, lastBlock) from storage into `r`.
/// @dev Expects `r.pair` to be set. Sets `r.load2 = true` and copies the raw packed word into `r.slot2`.
function loadRay2(Ray memory r)
internal
view
returns (Ray memory)
{
uint x = rays[r.pair].slot2;
r.slot2 = x;
r.load2 = true;
uint96 q96 = uint96(x);
uint96 cq96 = uint96(x >> 96);
r.quote = _decodeFloat96(q96);
r.candQuote = _decodeFloat96(cq96);
r.lastBlock = uint64(x >> 192);
if (!r.load1) r = loadRay1(r);
r.value = _moonVal(r.credited, r.quote); // current credited value
return r;
}
/// @notice Stores any loaded ray slots back to storage, writing only when the packed word changed.
/// @dev
/// - Updates `totalAvailable` for this ray's token based on `r.available` changes.
/// @return r with new memory slots
function storeRay(Ray memory r) internal returns (Ray memory){
if (r.load0) {
uint x0 =
(uint(uint160(r.token)) ) |
(uint(r.moon0 ? 1 : 0) << 160) |
(uint(r.swapLock ? 1 : 0) << 161) |
(uint(uint64(r.lastAdd)) << 162);
if (x0 != r.slot0) {
rays[r.pair].slot0 = x0;
r.slot0 = x0;
}
}
if (r.load1) {
// Apply change in available to totalAvailable[r.token].
uint oldAvail = _decodeFloat73(r.slot1 & MASK_73);
uint newAvail = _roundFloat73(r.available);
if (oldAvail != newAvail) {
if (!r.load0) r = loadRay0(r); // get `r.token`
if (newAvail > oldAvail) {
totalAvailable[r.token] = _satAdd(totalAvailable[r.token], newAvail - oldAvail);
} else if (newAvail < oldAvail) {
totalAvailable[r.token] = _satSub(totalAvailable[r.token], oldAvail - newAvail);
}
}
// Encode available and credited
uint avail73 = _encodeFloat73(r.available) & MASK_73;
uint cred73 = _encodeFloat73(r.credited) & MASK_73;
// Only cache class 2 or 3; class 1 or out-of-range -> 0 (forces reprobe semantics)
uint c = (r.class == 3 || r.class == 2) ? uint(r.class) : 0;
// Clamp pending into 90 bits
uint p = r.pending > ((uint(1) << 90) - 1) ? ((uint(1) << 90) - 1) : r.pending;
// Saturate work to signed 12-bit range [-2048, 2047]
int wClamped = r.work;
if (wClamped > 2047) wClamped = 2047;
if (wClamped < -2048) wClamped = -2048;
// Pack as signed 12-bit two's complement
uint w = uint(int256(wClamped)) & MASK_12;
// Pack flags (6 bits): unused, edge, core, eStale, cStale, moon0
uint flags =
(uint(r.edge ? 1 : 0) << 1) |
(uint(r.core ? 1 : 0) << 2) |
(uint(r.eStale ? 1 : 0) << 3) |
(uint(r.cStale ? 1 : 0) << 4) |
(uint(r.moon0 ? 1 : 0) << 5);
// slot1 layout (low -> high):
// [0..72]=avail73, [73..145]=cred73, [146..147]=class2,
// [148..237]=pending90, [238..249]=work12, [250..255]=flags6
uint x1 =
(avail73 ) |
(cred73 << 73) |
(c << 146) |
(p << 148) |
(w << 238) |
(flags << 250);
if (x1 != r.slot1) {
rays[r.pair].slot1 = x1;
r.slot1 = x1;
}
}
if (r.load2) {
uint x2 =
(uint(_encodeFloat96(r.quote)) ) |
(uint(_encodeFloat96(r.candQuote)) << 96) |
(uint(uint64(r.lastBlock)) << 192);
if (x2 != r.slot2) {
rays[r.pair].slot2 = x2;
r.slot2 = x2;
}
}
return r;
}
/// @notice Loads a member’s packed slot and decodes persisted fields.
/// @dev Caches the raw packed word into `m.slot0` for write-skipping in {storeMember}.
/// @dev Loads m.receiver if 'redirect' is true.
function loadMember(address addr)
internal
view
returns (Member memory m)
{
m.addr = addr;
uint x = memberPacked[m.addr];
m.slot0 = x;
m.pastIndex = uint112(x);
m.uncollected = uint(uint96(x >> 112));
m.class = uint8((x >> 208) & MASK_2);
m.active = ((x >> 210) & 1) != 0;
m.prime = ((x >> 211) & 1) != 0;
m.idxPlusOne = uint40((x >> 212) & MASK_40);
m.redirect = ((x >> 252) & 1) != 0;
// Set receiver
if (m.redirect) m.receiver = memberReceiver[m.addr];
else m.receiver = m.addr;
m.oldClass = m.class;
return m;
}
/// @notice Stores persisted fields for a SUN member, skipping the write if unchanged.
/// @dev Packs to one word; compares against `m.slot0` (loaded by {loadMember}) before SSTORE.
function storeMember(Member memory m) internal {
// saturate uncollected to uint96 max
uint u = uint(_cap96(m.uncollected));
// class stored in 2 bits; out-of-range -> 0
uint c = (m.class <= 3) ? uint(m.class) : 0;
uint packed =
uint(m.pastIndex) |
(u << 112) |
(c << 208) |
(uint(m.active ? 1 : 0) << 210) |
(uint(m.prime ? 1 : 0) << 211) |
(uint(m.idxPlusOne) << 212) |
(uint(m.redirect ? 1 : 0) << 252);
if (packed != m.slot0) {
memberPacked[m.addr] = packed;
}
}
/*/////////////////////////////////////////////////////////////////////////
SAFE STATIC PROBE SYSTEM
/////////////////////////////////////////////////////////////////////////*/
/// @dev Word-copy static probe.
/// Caller invariant:
/// - argWords is 0 or 1.
/// - copyLen is 32 or 64.
/// - copyLen <= minLen.
/// This function does not bubble target failure.
function _staticProbeWords(
address target,
bytes4 selector,
uint arg0,
uint argWords,
uint gasCap,
uint minLen,
uint copyLen
)
internal
view
returns (bool ok, uint w0, uint w1)
{
assembly ("memory-safe") {
mstore(0x00, selector)
mstore(0x04, arg0)
let inLen := add(0x04, shl(5, argWords))
// Copy only the fixed words the caller needs.
let success := staticcall(gasCap, target, 0x00, inLen, 0x00, copyLen)
ok := and(success, iszero(lt(returndatasize(), minLen)))
if ok {
w0 := mload(0x00)
if gt(copyLen, 0x20) {
w1 := mload(0x20)
}
}
}
}
/// @dev Boolean-only static probe. No return-data copy.
function _probeOk(
address target,
bytes4 selector,
uint arg0,
uint argWords,
uint gasCap,
uint minLen
)
internal
view
returns (bool ok)
{
assembly ("memory-safe") {
mstore(0x00, selector)
mstore(0x04, arg0)
let inLen := add(0x04, shl(5, argWords))
let success := staticcall(gasCap, target, 0x00, inLen, 0x00, 0x00)
ok := and(success, iszero(lt(returndatasize(), minLen)))
}
}
function _probeToken(address target, bytes4 selector, uint gasCap)
internal
view
returns (bool ok, address token)
{
uint word;
uint unused;
(ok, word, unused) =
_staticProbeWords(target, selector, 0, 0, gasCap, 32, 32);
if (!ok) return (false, address(0));
token = address(uint160(word));
}
function _probeReserves(Ray memory r)
internal
view
returns (bool ok, Ray memory)
{
uint a;
uint b;
// Require full V2 return shape, copy only reserve0/reserve1.
(ok, a, b) =
_staticProbeWords(r.pair, SEL_GETRESERVES, 0, 0, GAS_PROBE_LOW, 96, 64);
if (!ok) return (false, r);
uint112 r0 = _cap112(a);
uint112 r1 = _cap112(b);
r.rt = r.moon0 ? r1 : r0;
r.rm = r.moon0 ? r0 : r1;
return (true, r);
}
function _safeBalanceOf(address token, address owner)
internal
view
returns (bool ok, uint bal)
{
uint unused;
(ok, bal, unused) = _staticProbeWords(
token,
SEL_BALANCEOF,
uint(uint160(owner)),
1,
30_000,
32,
32
);
if (!ok) return (false, 0);
bal = _cap112(bal);
}
/// @notice Reads a MOON balance via MOON’s raw balance getter.
/// @dev Assumes MOON's internal rawBalanceOf cannot fail; staticcall success is intentionally ignored.
function _moonBalance(address owner) internal view returns (uint256 bal) {
address _moon = moon;
bytes4 sel = SEL_RAW_BALANCEOF;
assembly ("memory-safe") {
mstore(0x00, sel)
mstore(0x04, and(owner, 0xffffffffffffffffffffffffffffffffffffffff))
pop(staticcall(gas(), _moon, 0x00, 0x24, 0x00, 0x20))
bal := mload(0x00)
}
}
/*/////////////////////////////////////////////////////////////////////////
INTERNAL MATH UTILITIES
/////////////////////////////////////////////////////////////////////////*/
/// @notice Saturating subtraction – clamps at zero instead of underflowing.
function _satSub(uint a, uint b) internal pure returns (uint r) {
unchecked { r = a > b ? a - b : 0; }
}
/// @notice Saturating addition – clamps at max uint instead of overflowing.
function _satAdd(uint a, uint b) internal pure returns (uint r) {
unchecked {
r = a + b;
if (r < a) {
// Overflow happened, clamp to max
r = type(uint).max;
}
}
}
/// @notice Caps a uint value down to uint112, clamping at the max if overflow.
function _cap112(uint x) internal pure returns (uint112) {
return x > type(uint112).max ? type(uint112).max : uint112(x);
}
/// @dev Saturating clamp to 39 bits.
function _cap39(uint x) internal pure returns (uint) {
return x > MASK_39 ? MASK_39 : x;
}
/// @notice Caps a uint value down to uint96, clamping at the max if overflow.
function _cap96(uint x) internal pure returns (uint96) {
return x > type(uint96).max ? type(uint96).max : uint96(x);
}
/// @dev Saturating clamp to 97 bits.
function _cap97(uint x) internal pure returns (uint) {
return x > MASK_97 ? MASK_97 : x;
}
/// @notice Compare signs of (a1 - a2) and (b1 - b2) without subtracting.
/// @dev Zero is inclusive; only false when one delta >0 and the other <0
function _sameSign(uint a1, uint a2, uint b1, uint b2)
internal
pure
returns (bool)
{
return (a1 >= a2 && b1 >= b2) || (a1 <= a2 && b1 <= b2);
}
/// @notice Returns the absolute difference between a and b.
function _diff(uint a, uint b) internal pure returns (uint) {
return a > b ? a - b : b - a;
}
/// @notice Returns the minimum of 3 values.
function _min(uint a, uint b, uint c) internal pure returns(uint) {
uint d = a < b ? a : b;
return d < c ? d : c;
}
/// @notice Returns MOON-denominated value for `amount` tokens at quote `q` (1e38-scaled).
/// @dev Saturates to uint112 on overflow.
function _moonVal(uint a, uint b) internal pure returns (uint) {
unchecked {
uint q = b / 1e38;
uint r = b - q * 1e38;
// If a is too large, saturate
// q+1 is safe since q <= b/1e38 and b fits uint
uint maxA = type(uint).max / (q + 1);
if (a > maxA) return type(uint).max;
// Safe under the bound above
return _cap112(a * q + (a * r) / 1e38);
}
}
/// @notice Returns ceil(a * b / 2^k) using a full 512-bit product.
/// @dev Handles overflow by computing the high and low product limbs, then right-shifting
/// the combined 512-bit value. Rounds up if any discarded low bits are nonzero.
function _mulShiftUp(uint a, uint b, uint k) internal pure returns (uint) {
if (a == 0 || b == 0) return 0;
uint prod0;
uint prod1;
assembly ("memory-safe") {
prod0 := mul(a, b)
let mm := mulmod(a, b, not(0))
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
if (k == 0) {
// When k == 0, the product must fit in 256 bits; otherwise saturate.
if (prod1 != 0) return type(uint).max;
return prod0;
}
// Caller bounds k to <= 256.
uint shifted = (prod1 << (256 - k)) | (prod0 >> k);
// ceil: if any of the low k bits of the full product are nonzero, add 1
uint mask = (k == 256) ? type(uint).max : ((uint(1) << k) - 1);
if ((prod0 & mask) != 0) {
unchecked { shifted += 1; }
}
return shifted;
}
/// @notice Returns floor(a * b / d), treating multiply overflow or d == 0 as saturated.
function _mulDivDown(
uint a,
uint b,
uint d
) internal pure returns (uint) {
unchecked {
if (d == 0) return type(uint).max;
uint p = a * b;
if (a != 0 && p / a != b) {
return type(uint).max / d; // overflow, saturate
}
return p / d;
}
}
/// @notice Returns ceil(a * b / d), treating multiply overflow or d == 0 as saturated.
function _mulDivUp(
uint a,
uint b,
uint d
) internal pure returns (uint) {
unchecked {
if (d == 0) return type(uint).max;
uint p = a * b;
if (a != 0 && p / a != b) {
return type(uint).max / d; // overflow, saturate
}
return p == 0 ? 0 : (p - 1) / d + 1;
}
}
/// @dev Integer floor sqrt with a good first guess; 7 Newton steps are enough for 256-bit.
function _isqrt(uint x) internal pure returns (uint y) {
if (x == 0) return 0;
uint z = uint(1) << (_log2(x) >> 1);
unchecked {
// 7 Newton iterations
for (uint i; i < 7; ++i) { z = (z + x / z) >> 1; }
}
y = z;
// Safe clamp: avoids overflow when y >= 2^128
if (y > 0 && y > x / y) y--;
}
function _log2(uint x) internal pure returns (uint n) {
unchecked {
if (x >> 128 != 0) { x >>= 128; n += 128; }
if (x >> 64 != 0) { x >>= 64; n += 64; }
if (x >> 32 != 0) { x >>= 32; n += 32; }
if (x >> 16 != 0) { x >>= 16; n += 16; }
if (x >> 8 != 0) { x >>= 8; n += 8; }
if (x >> 4 != 0) { x >>= 4; n += 4; }
if (x >> 2 != 0) { x >>= 2; n += 2; }
if (x >> 1 != 0) { n += 1; }
}
}
/// @dev uint -> Float96 (88-bit mantissa + 8-bit exponent).
/// Layout: packed[95:88] = exponent, packed[87:0] = mantissa.
/// Decodes as (mantissa << exponent).
function _encodeFloat96(uint x) internal pure returns (uint96 packed) {
if (x == 0) return 0;
unchecked {
uint bitLen = _log2(x) + 1;
// exponent = 0, mantissa = x (fits in 88 bits)
if (bitLen <= 88) return uint96(x);
// shift is exponent, mantissa is top 88 bits after shifting down
uint shift = bitLen - 88; // for uint256 range, max is 168
uint mantissa = x >> shift;
uint mantMask = (uint(1) << 88) - 1;
return (uint96(uint8(shift)) << 88) | uint96(mantissa & mantMask);
}
}
/// @dev uint -> Float73 (67-bit mantissa + 6-bit exponent).
/// Layout: packed[72:67] = exponent, packed[66:0] = mantissa.
/// Decodes as (mantissa << exponent).
/// Note: This encoder enforces a uint112 cap on `x` (and thus shift <= 45).
function _encodeFloat73(uint x) internal pure returns (uint packed) {
if (x == 0) return 0;
x = _cap112(x); // enforce uint112 domain
unchecked {
uint bitLen = _log2(x) + 1;
// exponent = 0, mantissa = x (fits in 67 bits)
if (bitLen <= 67) return x;
// shift is exponent, mantissa is top 67 bits after shifting down
uint shift = bitLen - 67; // for uint112 range, max is 45
uint mantissa = x >> shift;
uint mantMask = (uint(1) << 67) - 1;
return (uint(uint8(shift)) << 67) | (mantissa & mantMask);
}
}
/// @dev Float96 -> uint. Clamps exponent field if malformed.
/// Layout: packed[95:88] = exponent, packed[87:0] = mantissa.
/// Decodes as (mantissa << exponent).
function _decodeFloat96(uint96 packed) internal pure returns (uint x) {
uint8 exponent = uint8(uint(packed) >> 88);
if (exponent > 168) exponent = 168;
uint mantMask = (uint(1) << 88) - 1;
uint mantissa = uint(packed) & mantMask;
return mantissa << exponent;
}
/// @dev Float73 -> uint. Clamps exponent field if malformed.
/// Layout: packed[72:67] = exponent, packed[66:0] = mantissa.
/// Decodes as (mantissa << exponent).
function _decodeFloat73(uint packed) internal pure returns (uint x) {
uint8 exponent = uint8(packed >> 67);
if (exponent > 45) exponent = 45;
uint mantMask = (uint(1) << 67) - 1;
uint mantissa = packed & mantMask;
return mantissa << exponent;
}
/// @dev Rounds `x` exactly as `_decodeFloat96(_encodeFloat96(x))` would.
/// For Float96: mantissa is 88 bits, exponent is `bitLen - 88`.
/// This is equivalent to clearing the low `shift` bits (rounding down).
function _roundFloat96(uint x) internal pure returns (uint) {
if (x == 0) return 0;
unchecked {
uint bitLen = _log2(x) + 1;
if (bitLen <= 88) return x;
uint shift = bitLen - 88; // in [1..168] for uint256 domain
return (x >> shift) << shift; // round down exactly like encode+decode
}
}
/// @dev Rounds `x` exactly as `_decodeFloat73(_encodeFloat73(x))` would.
/// For Float73: mantissa is 67 bits, exponent is `bitLen - 67`.
/// This is equivalent to clearing the low `shift` bits (rounding down).
function _roundFloat73(uint x) internal pure returns (uint) {
if (x == 0) return 0;
x = _cap112(x);
unchecked {
uint bitLen = _log2(x) + 1;
if (bitLen <= 67) return x;
uint shift = bitLen - 67; // normally <= 45 for the uint112-capped domain
return (x >> shift) << shift; // round down exactly like encode+decode
}
}
/*/////////////////////////////////////////////////////////////////////////
FALLBACK ROUTER
/////////////////////////////////////////////////////////////////////////*/
/// @dev Conceptual ABI selectors used only for internal protocol routing.
bytes4 private constant SEL_INITIALIZE =
bytes4(keccak256("initialize(address)")); // initialize(sunDeployer)
bytes4 private constant SEL_SWAP_WITH_PAIR =
bytes4(keccak256("swapWithPair(address,bool,bool,uint256,uint256,uint256)")); // swapWithPair(pair,swapLock,moon0,amountIn,reserveIn,reserveOut)
bytes4 private constant SEL_IS_UNLOCKED =
bytes4(keccak256("isUnlocked(address,address)")); // isUnlocked(sender,pair)
bytes4 private constant SEL_ON_MOON_TRANSFER =
bytes4(keccak256("onMoonTransfer(address,address,uint256)")); // onMoonTransfer(from,to,amount)
bytes4 private constant SEL_COLLECT =
bytes4(keccak256("collect(address)")); // collect(sender)
bytes4 private constant SEL_ON_SUN_TRANSFER =
bytes4(keccak256("onSunTransfer(address,address,uint256,uint256,uint256)")); // onSunTransfer(from,to,fromBal,toBal,amount)
/// @notice Internal protocol router.
/// @dev
/// All protocol-internal entrypoints, MOON hooks, SUN hooks, and
/// self-maintenance, are routed through this fallback and strictly
/// gated by `msg.sender`.
/// The compact selector router is an API-surface choice; the `msg.sender`
/// checks are the actual internal access-control boundary.
fallback() external {
if (address(this) == SELF) revert ProxyOnly(); // proxy calls only
bytes4 sel;
assembly { sel := calldataload(0) }
// initialize(address)
if (sel == SEL_INITIALIZE) {
address sunDeployer;
assembly {
sunDeployer := and(calldataload(4), 0xffffffffffffffffffffffffffffffffffffffff)
}
_initialize(sunDeployer);
return;
}
// swapWithPair(address,bool,bool,uint256,uint256,uint256)
if (sel == SEL_SWAP_WITH_PAIR) {
if (msg.sender != address(this)) revert InternalOnly();
address pair;
bool swapLock;
bool moon0;
uint amountIn;
uint reserveIn;
uint reserveOut;
assembly {
pair := and(calldataload(4), 0xffffffffffffffffffffffffffffffffffffffff)
swapLock := iszero(iszero(calldataload(36)))
moon0 := iszero(iszero(calldataload(68)))
amountIn := calldataload(100)
reserveIn := calldataload(132)
reserveOut := calldataload(164)
}
_swapWithPair(pair, swapLock, moon0, amountIn, reserveIn, reserveOut);
return;
}
// isUnlocked(address,address)
if (sel == SEL_IS_UNLOCKED) {
if (msg.sender != moon) revert InternalOnly();
address sender;
address pair;
bool unlocked;
assembly {
sender := and(calldataload(4), 0xffffffffffffffffffffffffffffffffffffffff)
pair := and(calldataload(36), 0xffffffffffffffffffffffffffffffffffffffff)
}
unlocked = _isUnlocked(sender, pair);
assembly {
mstore(0x00, unlocked)
return(0x00, 0x20)
}
}
// onMoonTransfer(address,address,uint256)
if (sel == SEL_ON_MOON_TRANSFER) {
if (msg.sender != moon) revert InternalOnly();
address from;
address to;
uint amount;
int fromTax;
int toTax;
assembly {
from := and(calldataload(4), 0xffffffffffffffffffffffffffffffffffffffff)
to := and(calldataload(36), 0xffffffffffffffffffffffffffffffffffffffff)
amount := calldataload(68)
}
(fromTax, toTax) = _onMoonTransfer(from, to, amount);
assembly {
mstore(0x00, fromTax)
mstore(0x20, toTax)
return(0x00, 0x40)
}
}
// collect(address)
if (sel == SEL_COLLECT) {
if (msg.sender != sun) revert InternalOnly();
address sender;
assembly {
sender := and(calldataload(4), 0xffffffffffffffffffffffffffffffffffffffff)
}
_collect(sender);
return;
}
// onSunTransfer(address,address,uint256,uint256,uint256)
if (sel == SEL_ON_SUN_TRANSFER) {
if (msg.sender != sun) revert InternalOnly();
address from;
address to;
uint fromBal;
uint toBal;
uint amount;
assembly {
from := and(calldataload(4), 0xffffffffffffffffffffffffffffffffffffffff)
to := and(calldataload(36), 0xffffffffffffffffffffffffffffffffffffffff)
fromBal := calldataload(68)
toBal := calldataload(100)
amount := calldataload(132)
}
_onSunTransfer(from, to, fromBal, toBal, amount);
return;
}
revert();
}
}