Auto-Earn / Standardized Yield (SY)
Auto-earn is implemented as a thin SY adapter on top of Blend (Stellar's primary lending protocol). When a user does Router.auto_deposit(user, asset, amount):
- The Router transfers the underlying asset from the user into the SY adapter.
- The SY adapter deposits into Blend, receiving yield-bearing Blend shares.
- The SY adapter mints SY tokens to the user proportional to the share value.
- Over time, Blend accrues interest → SY's
exchange_rate()grows.
Withdrawal is the inverse: auto_withdraw(user, asset, amount) burns SY, redeems from Blend, transfers the underlying back.
SY exchange rate
fn exchange_rate(env: Env) -> i128 {
// total_underlying_held_by_adapter * WAD / total_sy_supply
}
exchange_rate() is in WAD (1e18) and monotonically non-decreasing — every block, the underlying grows due to Blend yield while the SY supply stays constant.
A 1 USDC deposit at exchange rate 1.0 mints 1.0 SY. A year later when exchange rate is 1.10, that same 1.0 SY redeems for 1.10 USDC.
Why this matters
SY is a "yield-bearing" token. Holding SY = holding the underlying AND auto-compounding the interest. The mobile UI surfaces this as the Auto-Earn APY pill — the displayed rate is the realized growth rate of exchange_rate().
Auth model
The user signs the outer auto_deposit call. The Router pre-authorizes the inner sy.deposit(...) and token.transfer(...) sub-invocations using env.authorize_as_current_contract, so the smart wallet's signer policy only sees one outer auth entry.
env.authorize_as_current_contract(vec![
&env,
InvokerContractAuthEntry::Contract(SubContractInvocation {
context: ContractContext { contract: sy_id, fn_name: symbol!("deposit"), args: ... },
sub_invocations: vec![
&env,
InvokerContractAuthEntry::Contract(SubContractInvocation {
context: ContractContext { contract: asset_id, fn_name: symbol!("transfer"), args: ... },
sub_invocations: vec![&env],
}),
],
}),
]);
Without this pre-declaration, the nested token.transfer(from=Router, ...) would fail with Error(Auth, InvalidAction) because the user's signature only covers the outer call.
Contracts and SY tokens
| Asset | Underlying contract | SY contract |
|---|---|---|
| USDC | CC6K5SDGTDYPZDDHM6GV4OV3DAQPHKIMROIVE2LGLQN7PF4HEYSJWYYJ | CAACQ5OGFP7ZPS6U3XDO6T67SQMSXNRO4FABWFV3EMWEUUM6DU3XFREK |
| EURC | CCFU2STUWKUTHDNG2IS57BS2WAPGO75KG55H4JLPILSKISU5DHX26F4H | CBGE2IFCBCWPH4OJR4EZTVTMKV5ATL3WH4QGDYEIXP2LRGZBDP6UI7GB |
| XLM | (native) | CDXECW7NPIVDVOEV2D5EKTXPABBC4EJPACZ6LRLQSCC3F5KEHRABPO5C |