the exponential curve

the exponential curve

the reserve, the kernel, the stepper

abstract: there is a token on pons and there are fees, and the only question a fee ever gets asked is how old it is. this page describes a contract on robinhood chain that is set as the creator fee recipient of one token whose every swap carries a 4% fee, keeps everything that fee brings in a single reserve, and every epoch spends a fixed fraction of that reserve buying the token from its own market and sending what it bought to the dead address. because the fraction is fixed and the reserve is a sum, every fee that has ever arrived is still being spent, weighted by an exponential in its age. half of any fee is gone within one half life and the other half is never gone at all. the curve does not care whether anyone was watching: if the stepper was idle for a thousand epochs, one call performs all thousand in closed form. this document is the whole of the machine. there is nothing behind it.

note: this page is a reader. it renders public accounts and signs nothing on its own.

keywords: exponential kernels, 4% swap fee routing, geometric telescoping, fixed point ladders, fixed capacity machines

the curve

the object described here is a reserve and a rule. the reserve is the native coin balance of one contract. the rule is that every epoch, the contract spends the fraction λ of whatever the reserve holds, and only that. the spend buys the token on the pons market and the tokens bought are sent to an address no one holds the key to. that is the entire product. there is no schedule, no vote, no treasury manager, no second mechanism behind the first. a fee that arrives today begins to be spent today, and it is still being spent, in ever smaller pieces, on every epoch that follows.

the fraction is small on purpose. λ is chosen so that the reserve halves in exactly 2048 epochs if nothing new arrives, and an epoch is 128 blocks, so the half life is 2^18 blocks of chain time. the page you are reading measures the chain's block interval and renders the half life in seconds in the state of the curve at the end; the machine itself only counts blocks. the shape of the spend against the age of the money is the curve in fig. 1, and it is the same shape on the first day and on the thousandth.

fees

every swap of the token, buy or sell, pays a fee of 4% of the amount swapped, and pons pays that fee to the creator address of the token. the creator address of this token is the contract, so the fee accumulates at pons in the contract's name until someone asks for it. there is no other source of inflow that the machine is designed around. a day of heavy trading fills the reserve quickly and a quiet day fills it slowly, and in both cases the reserve is spent on the same curve, so the burn rate on any given epoch is 4% of all past volume weighted by how long ago it happened.

the contract exposes one function, collect, that asks pons for what has accrued. anyone may call it. collect pulls whatever pons is holding for the token into the reserve, records the amount, and does nothing else. it does not step, it does not buy, and it does not care who called. a fee and a gift are the same to the kernel: the contract also accepts a plain transfer of the native coin, adds it to the reserve, and records it under a separate name, pour, so that the two inflows can be told apart when the history is recounted.

the reserve

the reserve is one unsigned integer in storage, and it is always equal to the contract's native balance. there is no other balance, no token balance held for later, no owner's share carved out, no fee on the fee. money enters by collect or pour and leaves only by step, and step can only ever move the reserve to the market in exchange for tokens that are immediately burned. the reserve is therefore the sum of everything that has arrived minus everything that has been spent, and both of those sums are events on chain that anyone can add up.

what makes the reserve interesting is not its size but its composition. after a step, what remains is the reserve times one minus λ. after k steps it is the reserve times one minus λ to the k. a fee that arrived j epochs ago has therefore been multiplied by that factor j times and has weight one minus λ to the j inside the reserve today. write that out for every fee ever received and the reserve is a sum of fees, each weighted by an exponential in its age. the spend each epoch is λ times that sum, which is the definition of an exponential kernel applied to the fee stream, and it is written in full in the next section.

the kernel

let V_j be the swap volume of the token during epoch j in the native coin, f_j the fee that volume produced, R_n the reserve at the start of epoch n after that epoch's inflow, and s_n the amount spent by the step that closes epoch n. the machine is these four lines:

f_j      =  0.04 · V_j

λ        =  1 − 2^(−1 / 2048)

s_n      =  λ · R_n

R_(n+1)  =  (1 − λ) · R_n + f_(n+1)
         =  0.04 · Σ_(j ≤ n+1)  V_j · (1 − λ)^((n+1) − j)

B_n      =  y_n − (x_n · y_n) / (x_n + (1 − γ) · s_n)

the last line is the burn. x_n and y_n are the coin and token reserves of the pons market at the moment of the step, γ is the market's swap fee, and B_n is the number of tokens the step buys and burns, which is exactly what a constant product market returns for an input of s_n after its fee. the machine does not estimate B_n; it observes it, because the market computes it and the contract counts the tokens it received before sending them on. every symbol in the block is either a constant of the contract, a value in the contract's storage, or a value in the market's storage, so every s_n and every B_n in the history can be recomputed by anyone with an rpc connection and the receipts of the record.

2048 epochshalfquartereighthweight of a fee, by ageone bar = 128 epochs

fig. 1: the curve. every fee ever received is still in the reserve, at a weight that halves every 2048 epochs.

the step

the contract exposes exactly four functions, and it is worth seeing how short the whole interface is:

collect   pull the token's creator fees from pons into the reserve
step      close every whole epoch since the last step, spend, buy, burn
pour      accept a plain transfer into the reserve
pending   view: the epochs owed and the spend a step would make now

step is the only function that moves money out, and it can be called by anyone at any time. it reads the block number, divides the blocks since the last step by 128 to find k, the number of whole epochs that have elapsed, and refuses to run if k is zero. it then advances the last step block by exactly k times 128, not to the current block, so that partial epochs are never lost or double counted. it computes the fraction of the reserve that survives k epochs, keeps that, spends the rest through the market, forwards every token received to the dead address, and writes a receipt. there is no bounty paid to the caller and no priority given to anyone. the caller pays gas and the holders receive a burn. on a chain where gas is cheap that is the whole incentive, and it is stated here so that no one looks for a hidden one.

there is no withdraw function, no pause, no owner, no upgrade, no parameter that can be changed after deployment, and no function that can send the native coin anywhere except the market. the surface area of the machine is those four verbs, and everything else in this document is a description of what they do.

idle epochs

a machine that depends on being called every epoch would be a machine that depends on someone, so this one does not. if step is called after k idle epochs, it does what k separate steps would have done, in one multiplication. the reason is that the rule is multiplicative: k applications of "keep one minus λ" is one application of "keep one minus λ to the k", and the spend is the reserve times one minus that. the geometric series telescopes, so the cost of catching up is the same whether k is one or one million. nothing is owed, nothing accrues, no backlog builds. the curve simply has a position on it for every block, and step moves the reserve to wherever the block says it should be.

stepped every epochidle for seven, stepped oncethe same total spend, exactly

fig. 2: one call after k idle epochs spends exactly what k calls would have spent. the series telescopes.

the ladder

the contract must compute one minus λ to the k for any k up to the age of the chain, in integer arithmetic, in bounded gas. it does so with a ladder. seventeen constants are baked into the code, the i th being one minus λ raised to the power two to the i, each expressed as an eighteen decimal fixed point integer. to raise to the k, the contract walks the bits of k and multiplies together the rungs whose bit is set. every rung from the seventeenth on is zero, because one minus λ to the 2^17 is below the resolution of the fixed point, so any k of 131072 or more epochs simply empties the reserve, which is also what the real number would do to eighteen decimals. the rungs are drawn to scale in fig. 3 and listed with their exact integers in the docs.

2^00.999661612^10.999323332^20.998647112^30.997296062^40.994599422^50.989228012^60.978572062^70.957603282^80.917004042^90.840896422^100.707106782^110.52^120.252^130.06252^140.003906252^150.00001525882^162.3283e-10one half

fig. 3: the seventeen rungs. rung i is (1 − λ) to the power 2^i. any k is a product of rungs; past rung sixteen the product is zero.

the burn

the spend goes into the pons market for the token as a plain buy with no minimum output. the contract counts the tokens it holds before and after the buy and treats the difference as bought, then transfers exactly that many to the dead address, so the number burned is measured rather than predicted. the market decides the price; the contract does not read it, quote it, or check it. what it does instead is never spend much at once. each step spends λ of the reserve, and at the machine's λ that is about three hundredths of a percent per epoch, so the largest buy the market ever sees from the curve after a long idle stretch is bounded by the reserve itself and the usual one is tiny. the sandwich that could be built around it is bounded the same way, and this is discussed under failure. note that the step is itself a swap, so it pays the same 4% as any other swap, and that 4% returns to pons in the contract's name and is collected back into the reserve on the next collect. the curve feeds itself a little on every step; the amount is 4% of the spend and it is already accounted for in the next f_j.

(1 − γ) · sBthe market, x · y = c

fig. 4: one step moves the market along its own curve by (1 − γ)·s in coin and takes B in token. the contract observes B; it does not compute it.

the record

every step writes a receipt: the step index, the block it happened in, the number of epochs it closed, the amount spent, the number of tokens burned, and the reserve left behind. every collect and every pour writes a receipt of its amount and the reserve after. receipts are events, they are never modified, and they are indexed by the step counter so that the n th receipt can be found without scanning. the history of the curve is therefore chain state rather than a claim: anyone can enumerate the receipts from a public rpc node, replay the reserve from zero, check that every spend was λ applied k times to the reserve at that moment, and check that the tokens burned sit at the dead address.

this is the part of the design that removes the operator from the trust equation. a hosted counter can be wrong in either direction and no one can tell. a receipt cannot. the tape at the end of this page is computed from these receipts and from the live reserve, and from nothing else, and its emptiness means only that there is nothing yet to count.

the adapter

the contract touches two other programs and nothing else: the pons fee vault, to collect, and the pons market for the token, to buy. both are addressed by immutables set at deployment and both are called through a thin adapter that does exactly one thing each. the adapter is the only part of the machine written against someone else's code, so it is the only part that could be wrong for reasons outside this document, and its two calls are printed in full in the docs so that anyone can compare them against the pons contracts on the explorer. if pons changed its interface, collect or step would revert and the reserve would sit untouched. nothing in the adapter can move the reserve anywhere other than into the market.

one contract

the entire machine lives in one contract with four storage slots and seven fixed values. the fixed values are the token, the market, the fee vault, the dead address, the epoch length of 128 blocks, the fixed point value of one minus λ, and the block the contract was deployed in. the four storage slots hold the reserve, the step counter and last step block and epochs done packed together, the total spent, and the total burned. that is the whole of the state, and it is drawn to scale in fig. 5. no mapping, no array, no dynamic allocation, no growth. the gas cost of every function is known in advance and does not depend on how popular the token becomes or how long the curve has been running.

slot 0 lastStepBlock · stepCount · epochsDone · unusedslot 1 reserveslot 2 totalSpentslot 3 totalBurned

fig. 5: the whole state. four slots, one hundred and twenty eight bytes, allocated once and never grown.

failure

the failure modes are few and all of them are visible. if no one calls step, nothing is spent and the reserve waits; the next call catches up in closed form and no value is lost. if no one calls collect, the fees wait at pons in the contract's name; they are not in the reserve yet and the page says so, because the reserve it shows is the contract's balance and not a promise. if pons reverts on collect or buy, the step reverts, the reserve is untouched, and the receipt is not written. if an rpc node lies to this page, the page renders the lie, which is why the page is pointed at one rpc in a config file anyone can change and why every figure it shows can be recomputed elsewhere.

the sandwich deserves precision. a step is a public buy with no minimum output, so a searcher can buy before it and sell after it. the profit available is bounded by the price impact of the step, and the step is λ of the reserve, so a searcher's take is bounded by a slice of three hundredths of a percent of the reserve per epoch. after a long idle stretch the step is larger, up to the whole reserve at the limit, and so is the exposure; the mitigation is that anyone, including any holder, can call step at any time, so a long idle stretch is a choice the holders make collectively and can end with one transaction. the machine does not defend against this with a price check because a price check would need an oracle and an oracle would be a second mechanism. it defends by being small every epoch.

what cannot happen is quieter and matters more. the reserve cannot be withdrawn, because there is no function that sends the native coin anywhere except the market. λ cannot be changed, because it is an immutable. a burn cannot be undone, because the dead address has no key. a step cannot be replayed, because the last step block moves forward by exactly the epochs it closed. and no one, including the author of the contract, holds a key that changes any of this.

what remains

here is the complete list of what a holder of this token trusts. the contract, whose functions have no owner and no override. the pons market, which prices the buy. the robinhood chain block number, which is the only clock. and the rpc connection of their own choosing. the list of what they do not trust is longer and is the point: no server, no database, no schedule kept by a person, no operator's word about what was spent. every number this page will ever display is a read from public state that anyone can reproduce, forever.

the machine is small on purpose. four functions, four slots, seventeen rungs, one fraction, one fee of 4%, and a name that describes its own shape. everything else that could have been added, and was not, was left out so that this document could be complete.

state of the curve

read from the chain every four seconds. blank until the contract address is configured.

contract
token
market
chain id
current block
observed block interval
epoch
one minus λ
half life
half life, observed
reserve
steps
epochs closed
last step block
epochs owed
spend if stepped now
total spent
total burned
at the dead address
supply
burned share

the tape

every step, newest first. blank until the first step is written.

stepblockepochsspentburnedreserve aftertx