03 · 8 min read
Contract reference
Every function on YieldLinks.sol and on the source behind it, what it does, and the details that will surprise you. YieldLinks is EIP712("YieldLinks", "1") and ReentrancyGuard. It has no owner and nothing to upgrade.
01Constants#
None of these have setters. Immutables are fixed in the constructor.
| Name | Value | Why |
|---|---|---|
CLAIM_TYPEHASH | Claim(address linkKey,address recipient) | The EIP-712 type a claim signs |
VIRTUAL | 1e3 | Virtual shares and assets that blunt the first-depositor inflation attack |
MAX_DURATION | 365 days | The longest expiry a link may have |
ROUNDING_DUST | 10 base units | Taken from the sender on top of the gift so rounding never leaves the recipient short |
SOURCE | immutable | The IYieldSource that holds every escrowed token |
CHARITY | immutable | Receives yield on Charity links. Zero disables that policy. |
02createLink#
function createLink(address linkKey, address token, uint256 amount, uint64 expiry, YieldPolicy policy)
external payable returns (uint256 shares);Escrows amount + ROUNDING_DUST of token against linkKey and mints the link its shares of that token's pool. msg.value is the prepaid network fee, stored in tinybar.
- Approve the source for
amount + 10first. The source pulls the tokens withtransferFrom. - Reverts with
InvalidLinkKeyfor the zero address,LinkExistsif the key was ever used,InvalidAmountfor zero (or an amount that would mint zero shares),InvalidExpiryoutside(now, now + 365 days], andNoCharityfor a Charity link when no charity is set.
03claim#
function claim(address linkKey, address recipient, bytes calldata signature) external;Pays the link out to recipient. Anyone may submit it; normally the relayer does. The signature is the link key's EIP-712 signature over (linkKey, recipient), bound to this chain and contract.
- Checks: the link is
Open(LinkNotOpen), not expired (LinkExpired), the recipient is not zero (InvalidRecipient), and the signer islinkKey(InvalidSignature). - Settles: prices the shares, burns them, zeroes the fee, marks the link
Claimed. - Pays the recipient, then any yield to the sender or charity, through the source.
- Pays the prepaid fee to
msg.sender, the submitter.
Claimed and reverts, and nonReentrant stops it earlier anyway.04refund#
function refund(address linkKey) external;Returns everything, principal plus yield plus the prepaid fee, to the sender. The sender may call it at any time; after expiry anyone may. Reverts with NotRefundable when a stranger calls before expiry.
05Views and fees#
| Function | Returns |
|---|---|
claimable(linkKey) | (assets, principal): the link's value now and what it started with. Zero once closed. |
links(linkKey) | The stored Link: sender, expiry, status, policy, token, createdAt, principal, shares, fee |
totalShares(token) | Shares outstanding in a token's pool |
pendingFees(sender) | Fees that could not be delivered, credited to the link's sender |
withdrawPendingFees(to) | Sends the caller's pending fees to any address |
claimable is what the claim page polls to show the gift growing. Between reads the UI ticks an estimate, labelled as one.
06Events#
event LinkCreated(address indexed linkKey, address indexed sender, address token,
uint256 amount, uint64 expiry, YieldPolicy policy, uint256 fee);
event LinkClaimed(address indexed linkKey, address indexed recipient, uint256 toRecipient,
address yieldTo, uint256 yieldAmount);
event LinkRefunded(address indexed linkKey, address indexed sender, uint256 amount);
event FeePaid(address indexed linkKey, address indexed to, uint256 amount);
event FeeWithdrawn(address indexed sender, address indexed to, uint256 amount);LinkClaimed splits the payout: toRecipient and, for Sender or Charity links, yieldAmount sent to yieldTo.
07Errors#
error InvalidLinkKey(); error InvalidAmount(); error InvalidExpiry();
error InvalidRecipient(); error InvalidSignature(); error LinkExists();
error LinkNotOpen(); error LinkExpired(); error NotRefundable();
error NoCharity(); error NothingToWithdraw(); error WithdrawFailed();08The source#
A source implements IYieldSource and inherits ControlledSource. It is the only contract that holds tokens.
| Function | Who may call it | What it does |
|---|---|---|
totalAssets(token) | Anyone | Value held, including yield |
deposit(token, from, amount) | The controller | Pulls from from and puts it to work |
withdraw(token, amount, to) | The controller | Unwinds and pays to, by HIP-904 airdrop on Hedera |
setController(address) | The deployer, once | Binds the source to one YieldLinks, forever |
withdrawHbar(to, amount) | The deployer | Takes back the HBAR fee reserve. Cannot touch tokens. |
SauceStakingSource accepts only SAUCE (UnsupportedToken otherwise) and tolerates a rounding shortfall of at most 2 base units on a payout (InsufficientAssets beyond that). Writing your own is on Add a yield source.