machine
addresses
| chain id | 4 663 |
| rpc | |
| coil | |
| token | |
| pool | |
| adapter | |
| deploy block | 0 |
| burn address | 0x000000000000000000000000000000000000dead |
parameters
| quantum | |
| cap | |
| h0 | |
| d0 | |
| nmax | |
| reward bps | |
| window | |
| ring base | |
interface
// the coil, the flux machine
interface IFlux {
// immutable parameters
function quantum() external view returns (uint256); // wei, minimum jar for a press
function cap() external view returns (uint256); // wei, ceiling of one press before gain
function h0() external view returns (uint256); // wei, jar at which saturation is one half
function d0() external view returns (uint256); // 1e18 scaled fraction, drop at which lean reaches one
function nmax() external view returns (uint256); // distinct pressers at which gain reaches two
function rewardBps() external view returns (uint256); // presser share of spend, basis points
function window() external view returns (uint256); // blocks in the flux window
function ringBase() external view returns (uint256); // 1e18 scaled, ring width base
function token() external view returns (address);
function pool() external view returns (address);
function adapter() external view returns (address);
function deployBlock() external view returns (uint256);
// live state
function jar() external view returns (uint256); // wei held, equals address(this).balance
function totalIn() external view returns (uint256); // wei ever received
function totalSpent() external view returns (uint256); // wei ever sent to the adapter
function totalRewards() external view returns (uint256); // wei ever paid to pressers
function inductions() external view returns (uint256); // press count
function pressers() external view returns (uint256); // distinct presser count
function hasPressed(address) external view returns (bool);
function anchor() external view returns (uint256); // tokens per eth, 1e18, at end of last press
function lastBlock() external view returns (uint256); // block of last press
function reserve() external view returns (uint256); // tokens held by the adapter for pairing
function sample(uint256 i) external view returns (uint256 blockNumber, uint256 cumulative);
function rate() external view returns (uint256); // wei per block over the window
// preview of the next press, all computed the same way induce computes them
function preview() external view returns (
bool armed,
uint256 spend,
uint256 reward,
uint256 b, // 1e18 scaled lean
uint256 g, // 1e18 scaled gain
uint256 ringIndex,
uint256 lower, // tokens per eth, 1e18
uint256 upper
);
// the button
function induce() external;
receive() external payable;
event Received(uint256 amount, uint256 blockNumber, uint256 cumulative);
event Induced(
uint256 indexed press,
address indexed presser,
uint256 spend,
uint256 reward,
uint256 b,
uint256 tokensBought,
uint256 ethPaired,
uint256 tokensPaired,
uint256 spotBefore,
uint256 anchorBefore,
uint256 blockNumber
);
event RingMinted(
uint256 indexed press,
uint256 ring,
uint256 lower,
uint256 upper,
uint256 positionId,
uint256 ethPaired,
uint256 tokensPaired
);
}
// the pool adapter, written against the pons pool at deployment, set once, never changed
interface IFluxAdapter {
function spot() external view returns (uint256); // tokens per eth, 1e18
function burnedCount() external view returns (uint256); // positions held by the burn address
function reserve() external view returns (uint256);
function execute(uint256 b, uint256 ringIndex) external payable
returns (uint256 tokensBought, uint256 ethPaired, uint256 tokensPaired, uint256 positionId, uint256 lower, uint256 upper);
}Φ(n) = cumulative wei received up to block n
rate = (Φ(now) − Φ(now − window)) / window
armed = jar ≥ quantum and block.number > lastBlock
g = 1 + min(pressers, nmax) / nmax
S = min(jar, cap × g × jar / (jar + h0))
reward = S × rewardBps / 10000
deploy = S − reward
d = max(0, (anchor − spot) / anchor) (d = 0 on the first press)
b = ½ + ½ × min(1, d / d0)
buy = b × deploy
pairEth = (1 − b) × deploy
ringIndex = floor(log2(inductions + 1))
lower = spot / (1 + ringBase)^(ringIndex + 1)
upper = spot × (1 + ringBase)^(ringIndex + 1)
after : anchor = spot(after execute), lastBlock = block.number, inductions += 1
invariant : totalIn = jar + totalSpent + totalRewards
selectors
| function | selector | mutability |
|---|
| quantum | 0x9aa395f4 | view |
| cap | 0x355274ea | view |
| h0 | 0xf0fee9b1 | view |
| d0 | 0xa9874b2a | view |
| nmax | 0x6487a49f | view |
| rewardBps | 0x82328ffc | view |
| window | 0x461645bf | view |
| ringBase | 0xe84c070a | view |
| token | 0xfc0c546a | view |
| pool | 0x16f0115b | view |
| adapter | 0x03eadcfc | view |
| deployBlock | 0xa3ec191a | view |
| jar | 0xbe38a4fe | view |
| totalIn | 0xe221c871 | view |
| totalSpent | 0xfb346eab | view |
| totalRewards | 0x0e15561a | view |
| inductions | 0x6addee6c | view |
| pressers | 0x721b2c68 | view |
| hasPressed | 0xd6e3b89a | view |
| anchor | 0xd3fb73b4 | view |
| lastBlock | 0x806b984f | view |
| reserve | 0xcd3293de | view |
| sample | 0x10fa1878 | view |
| rate | 0x2c4e722e | view |
| preview | 0xefae2305 | view |
| induce | 0x24236805 | nonpayable |
| spot | 0x6f265b93 | view |
| burnedCount | 0x7cefcc52 | view |
| reserve | 0xcd3293de | view |
invariants
received equals jar plus spent plus paid. this is checked on every poll and printed on the landing page as the closed surface plate. if it ever fails, the site prints no and does not hide it.
rings recorded equals positions held by the burn address. checked on every poll and printed on the core page.
flux computed on chain equals flux computed here from events. checked on every poll and printed on the coil page.
storage
| slot | name | type |
|---|
| 0 | totalIn | uint256 |
| 1 | totalSpent | uint256 |
| 2 | totalRewards | uint256 |
| 3 | inductions | uint256 |
| 4 | pressers | uint256 |
| 5 | anchor | uint256 |
| 6 | lastBlock | uint256 |
| 7 | samples | uint256[window] packed (block << 128 | cumulative), ring buffer |
| 8 | hasPressed | mapping(address => bool) |