Docs menu

04 · 5 min read

Fees and guarantees

A gift that arrives smaller than it was sent is a broken promise. This page is the arithmetic behind the one guarantee YieldLinks makes, and every figure in it was measured on Hedera testnet.

01The rule#

The sender pays every cost; the recipient gets at least the gift. Send 5 SAUCE and the recipient receives at least 5 SAUCE, plus yield if the policy gives it to them.

Two mechanisms make that true, and the tests hold them to it:

CostPaid byHow
Rounding in share and pool mathsSenderA 10-unit rounding reserve on top of the gift
Submitting the claimSenderThe prepaid network fee, sent with createLink
Creating the recipient's accountSenderThe same prepaid fee

test/Guarantees.t.sol fuzzes it: RecipientReceivesAtLeastTheAmountTest tries random amounts and checks the recipient never ends up below the gift.

02The rounding reserve#

Shares round down when minted and the Infinity Pool rounds on enter and leave, so a link can come out a unit or two short of what went in. createLink therefore takes amount + ROUNDING_DUST, where ROUNDING_DUST = 10:

Output
gift      5.000000 SAUCE
reserve   0.000010 SAUCE   (10 base units, 6 decimals)
approved  5.000010 SAUCE

Two other guards back it up. A link's value is capped at what the pool actually holds, so a claim never asks for more than exists, and the source tolerates a shortfall of at most 2 units when one link pays twice (recipient, then yield). Fuzzing found both cases before testnet did.

03The prepaid network fee#

The sender attaches 1.5 HBAR to createLink. The contract stores it with the link and hands it over when the link closes:

OutcomeThe fee goes to
ClaimedWhoever submitted the claim, normally the relayer
Cancelled or expiredBack to the sender, with the tokens

The relayer refuses any link that prepaid less than MIN_PREPAID_FEE_TINYBAR = 1.35 HBAR, before it spends anything, with HTTP 402 FeeNotPrepaid. So a link that cannot reimburse it never costs it HBAR.

04What a claim costs#

Measured on testnet on 3 October 2026, at about $0.105 per HBAR:

StepHBARPaid from
Create the recipient's account (generated wallet)0.58Relayer, includes the 0.1 HBAR welcome balance
Submit the claim0.74Relayer
Total1.32Reimbursed from the 1.5 HBAR prepaid

A claim to an existing wallet or a pasted address skips the account step and costs only the claim. The sender also pays for their own approve and createLink transactions, from their wallet, like any transaction.

Who pays the HIP-904 account-creation fee has changed between network versions: on 1 October the sending contract paid it, on 2 October the transaction payer did. The source keeps a small HBAR reserve as a margin. Re-check on the network you deploy to.

05Tinybar and weibar#

The same HBAR has two units depending on where you read it:

WhereUnitDecimals1.5 HBAR is
Inside the EVM: msg.value, the stored feetinybar8150_000_000
Over JSON-RPC: ethers, viem, walletsweibar181_500_000_000_000_000_000
TypeScript
// Sending: weibar goes in, the relay divides by 1e10.
await writeLinks({ functionName: "createLink", args, value: parseEther("1.5") });

// Reading it back from the contract: tinybar comes out.
const link = await links.read.links([linkKey]);
const feeHbar = Number(link[8]) / 1e8; // 1.5

06When a fee cannot be paid#

The fee is sent with a low-level call. If the recipient of the fee cannot accept HBAR (a contract with no receive), the claim or refund still goes through and the fee is credited to the link's sender in pendingFees.

Solidity
links.withdrawPendingFees(payable(to)); // any address the sender chooses

Nothing gets stuck, and a hostile submitter cannot block a claim by refusing its own fee.

Next · 6 minArchitecture