Fees & Slippage
Three different things move the number. The curve spread is a fixed 1% of the curve value, split between the community DAO and the affiliation system. Curve slippage is the cost of your own trade size, and depends on how big it is relative to the supply. Gas is the æternity network fee, and the smallest of the three by a wide margin.
1. The spread
The spread is not a line item deducted from your trade. It is the gap between two curves:
buy(x) = 0.001 · e^(0.00000001 · x) − 0.0009999
sell(x) = buy(x) · 0.995The sale contract mints against buy and redeems against sell. The 0.5% difference accrues to the
community's DAO treasury. On top of that, the sale contract charges a 0.5% affiliation fee on
buys, so the total spread between buy and sell price is 1%.
price() already includes the affiliation fee
On the sale contract:
entrypoint price(count : int) : int =
require(count > 0, "COUNT_NOT_POSITIVE")
let bonding_curve_price = state.bonding_curve.calculate_buy_price(state.token_contract.total_supply(), count)
let affiliation_amount = affiliation_amount(bonding_curve_price)
bonding_curve_price + affiliation_amount
function affiliation_amount(bonding_curve_price : int) =
let affiliation_percentage = state.affiliation_treasury.get_affiliation_fee_percentage()
(bonding_curve_price * affiliation_percentage) / state.affiliation_treasury.get_affiliation_fee_precision()| Call | What it returns |
|---|---|
BondingCurve.calculate_buy_price(supply, count) | The bare curve integral |
TokenSale.price(count) | The curve integral plus the 0.5% affiliation fee |
TokenSale.sell_return(count) | BondingCurve.calculate_sell_return(supply, count) verbatim, with no fee added or removed |
Attach exactly price(count) and you are fully covered. Do not multiply it by 1.005 again. The
web app applies the 1.005 to the curve figure it computes off-chain, not to price(); the CLI
sends price() plus a slippage buffer and nothing else. Neither double-charges.
The fee percentage is read live from the affiliation treasury on every call:
AffiliationTreasury.get_affiliation_fee_percentage() returns 500 and
get_affiliation_fee_precision() returns 10^5, so the fee is 500 / 100000 = 0.5%. 500 is the
sum of the per-level percentages [300, 125, 50, 25].
Surplus AE is refunded
buy requires Call.value >= total_price rather than equality, then returns the difference:
require(Call.value >= total_price, "AE_AMOUNT_NOT_SUFFICIENT")
...
let overpaid_refund = Call.value - total_price
if (overpaid_refund > 0) Chain.spend(Call.caller, overpaid_refund) else ()CommunityFactory.create_community does the same before it forwards the initial buy. A slippage
buffer costs you nothing when the price does not move: you get the unused portion back in the same
transaction. The only cost of a generous buffer is that the AE has to be in your wallet when you sign.
Where each AE goes
Buyer pays AE
├── 99.0% → Bonding Curve Reserve (redeemable by sellers)
├── 0.5% → Community DAO Treasury (governed by token holders)
└── 0.5% → Affiliation System
├── 0.300% → Level 1 Referrer
├── 0.125% → Level 2 Referrer
├── 0.050% → Level 3 Referrer
└── 0.025% → Level 4 Referrer
(if no referrer: burned)
Buyer also receives:
└── ProtocolDAO Tokens = 1,000 × AE valueThe four-level split is credited per level as the treasury walks up the affiliation tree.
AffiliationTreasury.record_sale_transaction(buyer, transaction_value) credits 300, then 125,
then 50, then 25 hundred-thousandths of the transaction value to successive inviters, and stops
as soon as an account has no inviter recorded. Levels with no inviter are not paid out; that share
is burned.
Credited rewards are withdrawable for the current and the previous 30-day payout period
(payout_period_interval = 2592000000 milliseconds) and expire after that. withdraw() also
requires the caller to have reached four unique invitees who each bought at least 10 AE
(unique_invitee_count_threshold = 4, unique_invitee_buy_amount_threshold = 10 * 10^18);
below that bar it aborts with MINIMUM_ACCOUNTS_THRESHOLD_NOT_REACHED. See
Affiliation rewards.
The live percentages are readable on-chain: fee_percentage() and fee_precision() on the
factory, and get_affiliation_fee_percentage(), get_affiliation_fee_precision() and
get_affiliation_fee_percentages() on the affiliation treasury.
The DAO's half, exactly
The 0.5% that reaches the community DAO is the residue after the reserve is set aside, in
buy_with_affiliation_inner:
let reserve = state.bonding_curve.calculate_sell_return(state.token_contract.total_supply(), count)
state.dao_contract.record_sale_transaction(
value = Call.value - overpaid_refund - affiliation_amount - reserve, protected = true,
Call.caller, total_price)total_supply() has already been incremented by the mint, so reserve is exactly
0.995 × bonding_curve_price, the AE that would be owed if the buyer immediately sold back. The
DAO gets bonding_curve_price − reserve, the remaining 0.5%, and the sale contract keeps the
reserve. The payout obligation is computed first and the treasury receives only what is left over,
which is why the reserve is always solvent.
Both external calls use protected = true, so a failing DAO or treasury call cannot block a trade;
the value stays in the sale contract instead of reverting the buy.
What 1% costs you in practice
Buy 1,000 tokens at a supply of 10,000,000 and immediately sell them back:
curve integral for the buy 0.105276443949 AE
× 1.005 affiliation fee 0.105802826168 AE ← what you pay
curve integral for the sell 0.105276443949 AE
× 0.995 sell factor 0.104750061729 AE ← what you get back
difference 0.001052764439 AEThat is 1% of the curve value, and 0.995% of the AE you handed over; the two differ because the fee is added on top of the curve price on the way in. Every position starts about 1% down. See Risks.
The spread is charged on value, not on trade count, so ten small round trips cost the same 1% each as one large one. There is no fixed component to amortise.
2. Curve slippage
Slippage on a bonding curve is arithmetic, not congestion. You pay the integral of a rising curve over the range you mint into, while the quoted spot price is only the value at the left edge of that range. The larger your trade relative to the supply, the further above spot your average fill lands.
Buying from a supply of 10,000,000, where spot is 1.052709e-4 AE:
| Tokens bought | Share of existing supply | Total cost (AE) | Average price (AE) | Premium to spot |
|---|---|---|---|---|
| 1,000 | 0.01% | 0.105276 | 1.05276e-4 | +0.005% |
| 100,000 | 1% | 10.582369 | 1.05824e-4 | +0.53% |
| 1,000,000 | 10% | 110.815238 | 1.10815e-4 | +5.27% |
| 10,000,000 | 100% | 1,624.184008 | 1.62418e-4 | +54.3% |
| 50,000,000 | 500% | 21,699.788231 | 4.33996e-4 | +312% |
Rule of thumb: your premium to spot is roughly half the percentage of the supply you are adding, up to about 10%, and worse than that beyond it.
Splitting the order does not help. The curve is path-independent: ten buys of 1,000,000 from a rising supply cost exactly the same total as one buy of 10,000,000, because the integral is the same area either way. The only levers are trade size and the supply you trade at.
Near supply zero the effect is far larger in relative terms, because the −0.0009999 offset has
cancelled almost all of the exponential: buying the first 1,000 tokens of a brand-new token costs
5% above spot. See Bonding Curves.
3. Slippage guards
A guard is not a fee. It is the tolerance you accept for what other people do between your quote and your fill.
| Surface | Default | Mechanism |
|---|---|---|
| Web app trade card | 1% | Stored per browser under the local-storage key tokenTrade:slippage; adjustable in the trade card |
superhero-token-swap.mjs buy | 3% | Attaches price(count) × 1.03 as the transaction amount |
superhero-token-swap.mjs sell | 3% | Passes sell_return(count) × 0.97 as minimal_return_required |
superhero-token-create.mjs create | 5% | Attaches calculate_buy_price(0, count) × 1.05, rounded up |
To change the CLI tolerance, edit SLIPPAGE_PERCENT at the top of the swap script. To set your own
precisely, call the contract directly, as shown in Buying & Selling.
The guards are asymmetric:
- On a buy, the guard is an upper bound on spend. You attach more AE than the quote; anything the trade does not need is refunded in the same transaction, and if the price moved further than your tolerance the call reverts with
AE_AMOUNT_NOT_SUFFICIENT. - On a sell, the guard is
minimal_return_required, a floor on the payout. Below it the call reverts withMINIMAL_RETURN_NOT_MEETand your tokens stay where they are.
Because surplus is refunded, a buy buffer is close to free and a sell floor is a real decision. Size the sell floor carefully; be generous with the buy buffer.
4. Gas
Every transaction pays an æternity network fee in AE, independent of everything above.
| Action | Transactions | Cost |
|---|---|---|
| Create a token | 1 contract call | About 0.001 AE |
| Buy | 1 contract call | Depends on contract execution |
| Sell | 2 contract calls: allowance, then sell | Depends on contract execution |
| Post | 1 contract call | Depends on contract execution |
Read the exact fee off any mined transaction in aeScan (opens in a new tab). Two things hold
regardless: a sell costs two transactions, not one, because of the allowance step; and the web
app never lets you spend your whole balance. Its "spendable" figure is
balance − balance × (slippage + 1) / 100 − 0.001 AE, so at the default 1% tolerance it holds back
2% of your balance plus a flat 0.001 AE for the fee.
For what the gas is paying for, see AE and gas.
Putting it together
For a buy of n tokens at supply S:
AE leaving your wallet
= ∫ from S to S+n of buy(x) dx ← the curve, including your own slippage
× 1.005 ← the affiliation fee; together, this is price(n)
+ network gas
( any buffer you attached above price(n) is refunded in the same transaction )And for the matching sell later, at whatever supply S' prevails then:
AE returning to your wallet
= ∫ from S'−n to S' of buy(x) dx
× 0.995 ← the sell factor, i.e. the DAO's cut
− network gas
( reverts entirely if below minimal_return_required )Nothing else is charged. There is no listing fee, no withdrawal fee, no maker or taker fee, and no fee for holding.
Related
- Bonding Curves: the integral behind every fee and slippage figure, worked out by hand
- Buying & Selling: how to set a guard yourself instead of taking the default
- Risks: what a 1% round-trip spread means for a position you intend to hold
- Affiliation rewards: where the 0.5% affiliation half of the spread ends up
- DAO treasury: what the community can do with its half