尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证正在加载完整 README。 以下为已保存的摘录。
→ VIDEO SHOWING HOW IT WORKS END TO END ←
A pension you build one trade at a time.
Every buy and every sell puts a slice into a vault only you can open — and that slice buys real tokenized stock.
No deposit. No decision to save. Trade where you already trade.
A trade fills. A slice is put aside. The vault buys real tokenized stock — and only your key can open it.
People who trade every day rarely save. Not because they can't — because saving is a separate decision, made on a separate day, with money that already feels spent.查看完整 README ↗Every buy and every sell puts a slice into a vault only you can open — and that slice buys real tokenized stock. No deposit. No decision to save. Trade where you already trade.
A trade fills. A slice is put aside. The vault buys real tokenized stock — and only your key can open it.
People who trade every day rarely save. Not because they can't — because saving is a separate decision, made on a separate day, with money that already feels spent.
SaverFi removes the decision. You link the wallet you already trade with. After each trade, a slice — a share of the profit, or a share of the volume — is moved into a vault that only your pension key can open, and when enough has piled up, the vault buys the tokenized assets you chose.
You keep trading wherever you like. GMGN, Axiom, your own router — it makes no difference, because nothing sits in your execution path.
Not a testnet, not a simulation. Real trades, measured, settled and invested by this code. Every line below is a link you can open right now.
| Step | What happened | Proof |
|---|---|---|
| 1. Vault created | The owner's pension key signed the vault into existence | 5EMtg7aY… |
| 2. Trading wallet linked | A wallet bound to that vault, with its rate | 55oN6Nxu… |
| 3. The slice was taken | settle_v2 moved 0.036634582 SOL into the vault — exactly 20 % of the 0.183172913 SOL that trading session made | 2tE3BMTa… |
| 4. The slice bought stock | The vault wrapped, converted, and swapped through Raydium CLMM into SPYx | 2YdLAtx… |
| 5. Then it bought again, through an aggregator | On 2026-09-22 the owner re-signed the vault's policy onto Jupiter v6, and the vault wrapped, converted and bought SPYx through it — invest CPI'ing Jupiter, Jupiter routing Orca Whirlpool, Token-2022 settling the transfer | 2KGe82ER… |
| 6. Then a basket of two | The owner signed SPYx + ANTHROPIC, and the next deposit bought both legs, each through Jupiter on its own venue — the first PreStocks leg this vault has held | 2w5Uwo6X… · 43S4uAxY… |
| 7. And it saved again | On 2026-09-23 a second trading session was settled: settle_v2 moved 0.028372759 SOL into the vault, at the 25 % rate the owner had signed from the live page that morning | 5nGb2hqz… |
| 8. Then it switched to volume | On 2026-09-25 the owner's pension key signed set_policy_v2, moving the vault from 25 % of profit to 1 % of every buy and every sell | 4iyqFNcx… |
| 9. And saved on volume | Minutes later, three settle_v2 in volume mode moved 0.043755651 SOL into the vault — 1 % of the 4.375565225 SOL the owner's next five trades bought and sold — and the vault converted it to USDC | 5JYcviq5… · 3NwEBhhy… · 2u5bR3CL… |
| 10. And the volume savings bought stock | A fourth volume settle_v2 moved 0.02215709 SOL in; converted, it took the vault's USDC past the basket's $10, and the keeper bought SPYx with 5.34 USDC | 4LunSyrb… · 3Cs1H6SH… |
| 11. Then back to profit, and a full basket | The owner's pension key moved the vault back to 20 % of profit; two profit settlements followed, and with 6 USDC the owner sent in, the keeper bought both legs, SPYx and ANTHROPIC, 6.35 USDC each | 67MZSaEr… · 4Tsc7BXQ… · 63AQuFBU… |
| 12. And it is still there | On 2026-09-26 the vault holds 0.0443 SPYx and 0.0172 ANTHROPIC (PreStocks) — positions paid for by trading profit, trading volume and the owner's own test deposits — plus 2.69 USDC waiting for the next buy | vault EFXK995P… |
| 13. And it comes back out | On 2026-10-06 the owner's pension key took 0.004312315 ANTHROPIC out of the vault with withdraw_token — the first time money has left a SaverFi vault, signed by the only key that can make it leave | 5GMPTgTg… |
The keepers that do it are running right now and say so in public. A scheduler marks which vaults are due and workers settle and invest them; a vault still served by the keepers from before the scheduler counts as legacy. The scheduler's /status shows the whole fleet, read from the database they all share:
curl -s https://sip-solana-scheduler-production.up.railway.app/status | jq '{role, dispatch, vaults: .fleet.queue.bySystem, due: .fleet.queue.due, workers: [.fleet.workers[]? | select(.stoppedAt == null) | {kind, heartbeatAgeMs}], alerts: .alerts.firing}'
flowchart LR
T["🧑 You, trading anywhere"]
K["⚙️ Keeper, measuring from the chain"]
P["📜 sip_vault program"]
V[("🏦 Your vault")]
R["🔁 Jupiter v6, routing the venues"]
S["📈 SPYx, tokenized stock"]
O["🔑 Your pension key"]
T -. "on-chain history, never the trade path" .-> K
K -- "Ed25519 attestation + settle_v2" --> P
P -- "moves the slice" --> V
V -- "invest, under a policy you signed" --> R
R --> S
S --> V
O == "the only key that can withdraw" ==> V
Nothing is in your execution path — on purpose. A Privy policy can allow or deny a transaction, but it cannot add an instruction to one, and a router of ours would only ever see our own trades. So the slice is measured after the fact, from the chain itself, and collected by a signed settlement. That is what lets you trade anywhere and still save.
The measurement is attested, not trusted. The keeper signs an Ed25519 attestation of what it measured; the program verifies that signature against the attester named in its own on-chain config, checks a nonce and a frontier slot so no window is replayed or run backwards, clamps the result to the vault's maximum contribution, and refuses outright if the settlement would push the trading wallet below the reserve its owner set.
The venue is yours, and it is pinned. invest will only CPI the program named in the policy you signed, byte for byte. The keeper cannot route anywhere else, and the day it learns a new venue, the only way that venue reaches your vault is you signing for it.
Linking a wallet takes a third signature. Not just the owner's and the wallet's on the transaction — the wallet also signs a separate 140-byte consent naming this program, this wallet, this vault and this owner, which the program verifies before it will bind anything. It matters because a Privy policy for a custom program can only match the program id: a seat allowed to sign settle_v2 is also allowed to sign link_wallet, and could otherwise bind a fresh wallet to a stranger's vault. What that seat cannot do is sign a message. The consent starts with the byte 0xFF, which no Solana transaction can begin with, so those bytes can never be replayed as one.
The keeper is dry by default. A dry run never even reads a signing secret. Moving money takes an explicit arming variable and a byte-exact confirmation sentence and the on-chain config naming the keeper's key — a conjunction it re-asks on every single sweep.
The sip_vault program — 6kA9H9zQT6PW5xWkXoAFCS3NotxarzaYqj66mjMf9w4J — is 17 instructions, 4 account types and 39 named errors.
The bytes running on mainnet are the bytes this repository tests. Not "built from this source" — the same file. Check it yourself:
solana program dump 6kA9H9zQT6PW5xWkXoAFCS3NotxarzaYqj66mjMf9w4J /tmp/sip_vault.so -u mainnet-beta
shasum -a 256 /tmp/sip_vault.so
# 60e94348d7cf841ac4542b356ed1719047c33256a96894e3a12bdf32c63de823
# …identical to packages/solana-program/target/deploy/sip_vault.so, and to the
# hash the keeper's local-validator tests pin their run against.
| Setting up | init_config · create_vault_v2 · link_wallet · unlink_wallet |
| Saving | settle_v2 — the attested slice, the only way value enters a vault |
| Investing | wrap_sol · convert · invest — SOL → wSOL → USDC → the assets in your policy |
| Your controls | set_policy_v2 · set_invest_policy · withdraw · withdraw_token |
| Protocol | set_attester · set_keeper · set_protocol_paused · transfer_authority · accept_authority |
Authority transfer is two-step — an offer, then an acceptance — so a mistyped address cannot orphan the protocol.
Both have been offered since 2026-09-25. A vault moves between them with one set_policy_v2 signed by the pension key, from Vault settings (the gear on the Savings rule card); a new vault can start on Volume from the vault card, while the first-run setup still starts every vault on Profit. Each mode is settled by its own keeper service.
A transaction counts as volume when the trading wallet signed it, it succeeded, it is not a plain transfer or one of SaverFi's own settlements, and the wallet's SOL (wrapped SOL included) moved one way while another token moved the other. Its size is how far the wallet's SOL moved, not counting the network fee or the rent of the wallet's token accounts opened or closed. Wrapping, unwrapping, transfers and failed swaps never count. Only SOL is measured, so a swap with no SOL leg, such as USDC into a token, counts just the SOL the wallet pays beside it, such as a tip — a gap that can only charge less, never more. A volume slice settles once it owes 0.001 SOL, or an hour after its oldest trade. Trades made before a switch to Volume, or before a change of its rate, are forgiven rather than charged at the new rule.
Connect a Solana wallet and every number is read from mainnet through the app's own routes: your vault, your policy, live pool prices, what the vault holds and what it has saved. Login is external wallets only — Phantom, Backpack, Solflare — with no embedded wallet and no custody.
The newest day of the changelog, copied here each morning. Every earlier day is in the full file.
Landing
A new landing, built overnight at the owner's request, one step after another; all of it is in
production at /welcome.
c9194fd. The green build of the S from the launch film
plays, then the S flies into the navigation bar and the page enters in pieces — headline line
by line, buttons one after another, the frame from below. It can be skipped with a click or a
key, and with reduced motion it is a still frame. It only counts as seen if it really was: a
slow or failed start no longer uses it up 7de9942. At first it played once per browser tab;
by the morning it was remembered for five minutes per browser instead, so a quick reload is
fast and a later visit, or a return from the app, sees it again 0ad9718.9f23adf. The background used to be a third
party's clip, another brand's card, served from that party's CDN. It is now the grid the S is
built on, drawn in code; the owner picked it over an aurora after seeing both on the real
page. Every video the site plays is now its own, and the content security policy allows media
from the site alone.7de9942 ecc8670. The owner asked for
activity on the grid while there are no users yet: cards of example savings and buys appear
beside the frame, fed by a line from the Axiom, GMGN and Photon terminals, with a large faint
S and floating SPYx, ANTHROPIC, SOL and USDC logos behind. At the owner's request the cards no
longer say "Example" and carry no address or time — they say what a trade does, not who made
it — while the frame still reads "Example — nobody's pension". Only at 1024 px and wider, never
with reduced motion.ecc8670. The owner asked for a summary that is easier to read: "Trade as
usual and grow your own onchain pension", and a shorter beta line that still says the team
can update the SaverFi program, because it is true.7160b30. Connect connects and, once the login succeeds,
goes straight into the app — the pension, or the setup if there is no vault yet; before, it
stayed on the landing. A visitor already connected sees "Open my pension". "See the app" and
scrolling open the sample; Leaderboard and Dashboard are plain links, and the bar reads
"Leaderboard · See the app · Dashboard │ Connect". A deployment without the login provider's
configuration no longer breaks the landing. The full login-then-pension path is tested only
against the development stand-in for Privy; on production, Connect was checked as far as
opening the real wallet dialog.Wallet import
981d427 a79be6e. The owner asked for it at
03:10, from the roadmap; by 05:32 "Import a wallet I already use" sat under Create on the
trading-wallets card and in the live panel's next step. The private key is pasted into a
masked field that never enters the page's state and is cleared on every refusal; the page
derives the address from the key itself and refuses a damaged one. Before the key goes
anywhere, the server reads the address on chain and refuses a key that owns a vault, holds a
role in the protocol, or is linked to another vault. Privy then imports it with the keeper's
seat and policy in the same call, the page reads back that the seat is there, and links it to
the vault the usual way. Imported rows can have SaverFi's permission removed again.dXz3F1L3…),
and the keeper reports all four wallets signable through its Privy seat. Nothing has been
settled from it yet. It showed that Privy numbers an imported wallet 0, like the first created
one, so the two were both called "Trading wallet 1"; imported wallets are now named and
ordered on their own, and Create explains why it is disabled on an account whose only Privy
wallets are imported ada9339.01f1a6f 0fbbaa7: a multi-agent review confirmed 14
findings, none critical or high. The largest: the import check would read any address's whole
token list into memory, so a wallet with thousands of accounts could swell the server; the
list now has its own capped read and names at most eight holdings. The panel now also says
plainly that SOL coming back by anything other than a plain transfer — an unstake, a lending
or perps exit — counts as profit, and that once imported the wallet can also be used and
exported from the SaverFi account. One finding is left to the owner, since fixing it means
touching the keeper: a SOL deposit whose transaction also calls another program, such as an
exchange withdrawal with a memo, counts as profit for every wallet.b27f48f. A chain read that came back
without a result used to look like a vault that does not exist, so the page could offer to
create a vault that may already be there. The same fix covers links, policies and balances.Keeper
sip_vault deployed on Solana mainnet — 17 instructions, Ed25519-attested settlement, replay-proof nonces and frontier slot/health and /status, which also report what each sweep costs: duration p50/p90, skipped sweeps, per-phase timings and which RPC endpoint is answering/wallets vault screens, the all-pensions /dashboard, Solana routes/statusA hackathon README that overclaims is worse than one that claims less, so:
lifetime_saved: five times at profit (2026-09-19, 2026-09-23 and three on 2026-09-25) and four times at volume on 2026-09-25, between 17:45 and 19:38 UTC. The investing half has filled several times, including through Jupiter and into a two-stock basket on 2026-09-22 and again on 2026-09-25, with USDC that included the volume savings. Most of what the vault has received came from the owner's own test deposits (0.164 SOL and 14.1 USDC), not from settlement. It is real, and it is one wallet: on 2026-10-02 the program holds three vaults, but the other two — created by two other pension keys on 2026-09-30 and 2026-10-02, each with one trading wallet linked and no investment policy signed — have not had anything settled into them yet — and since the owner moved it back to profit at 19:41 UTC on 2026-09-25, no vault saves on volume.main redeploys the profit keeper but not the volume keeper: on 2026-10-07 the volume keeper was still the process started on 2026-09-25, running that day's code. Faster RPC raises it only as far as the provider plan's requests per second allow, and nothing outside the process polls /health yet, so a stalled keeper would not page anyone. Each sweep finds its wallets with one unpaginated getProgramAccounts call; on 2026-09-27 the RPC provider refused it as overloaded, the keeper's own Telegram alert fired, and the sweeps recovered by themselves, but that call will need paginating as the program grows.Node 22.14.0 and pnpm 10. On Node 20 the test suites fail to load before they run a single case.
pnpm install
pnpm dev # the site on http://localhost:3002 (localhost, not 127.0.0.1)
pnpm typecheck # solana-log, solana-core, solana-keeper and the web
pnpm test # the same four packages
pnpm test:keeper # the keeper alone
pnpm build # the web's production build; prebuild runs check:csp and check:idl
The landing and the sample dashboard need no environment and no keys. Connecting, /wallets and the Solana routes read the variables in packages/website-oficial/.env.example.
The program has its own toolchain: pnpm --dir packages/solana-program test runs anchor test against a local validator, deliberately outside pnpm test.
A green run is not by itself evidence. Two bugs here passed the whole suite for weeks, both for the same reason — a fixture that randomised the very field in dispute: docs/TESTING_TRAPS.md.
packages/solana-program Anchor workspace: the sip-vault program and its IDL, plus toy-venue,
the venue its invest guards are tested against
packages/solana-core the IDL codec the browser may load, and the server-only relay,
verifier and builders behind the web's Solana routes
packages/solana-keeper discovers links, settles and invests; dry run by default
packages/solana-log the redacting logger every service prints through
packages/website-oficial the landing, the sample dashboard, the vault screens, the Solana routes
tools/landing-shot regenerates the landing's screenshot of the dashboard
archive/evm retired EVM code: not installed, built, tested or deployed
docs/runbooks/RAILWAY_SOLANA.md — deploying the keeper: every variable, which are secret, and a phased rolloutdocs/runbooks/VERCEL_WEB.md — deploying the web, and the Privy domaindocs/runbooks/PRIVY_SOLANA.md — the signer seat, the policy that bounds it, and what that policy does not preventdocs/runbooks/SECRETS.md — which keys exist, where each lives, and how they stay out of chats and logsThe runbooks are written in Spanish.
The product is SaverFi. The code name is SIP: package names, environment variables, the sip-vault program and its signed domains all keep it. To find every remaining mention:
git grep -n -I -w SIP
-w is what makes it a word search, and it is the only form to use here.
Never git grep -n -I -E '\bSIP\b': git's regex engine has no \b, so that pattern matches nothing whatsoever and hands back a silent all-clear on a repository full of the word. A test in the web package runs both forms against the real checkout and fails if the broken one is ever written down anywhere but here.
Open the app · Leaderboard · @SaverFi · The program on Solscan · Keeper status
Built on Solana. Beta — the program is upgradeable and the vault holds real value.
609d701. The owner's decision: a visitor with no
wallet who asks for Live — /?mode=live, /activity, the Live button on the sample, or
Disconnect — lands on the landing at /, and the "Connect your pension key" card is gone.
With a wallet connected, Live goes straight into the pension and never passes through the
landing, even when the "already connected" cookie has expired. /?mode=mock is still the
sample, and /welcome never moves. Checked on production as a visitor; the connected path is
tested only against the development stand-in for Privy. At first the Disconnect inside the
wallets modal only signed out and left a visitor on the sample; at the owner's request it now
lands on the landing too 0e0bc48.convert and invest both CPI Jupiter, which routed Orca Whirlpool into SPYx. The routes need address lookup tables to fit a packet at all, so the keeper compiles a v0 transaction when there are tables and the legacy one when there are notset_policy_v2 for how the vault saves, set_invest_policy for what it buys. Proven on mainnet 2026-09-23, when the owner's vault went from 20 % to 25 % of profit from the rule cardsettle_v2 in volume mode saved 0.043755651 SOL from five real trades, and a fourth that evening took the vault's USDC past its basket's threshold and into a SPYx buy. Live on the site, checked in the production build. So far one vault and one wallet, which went back to profit the same evening, so no vault saves on volume todaywithdraw_token, signed by the pension key alone, took 0.004312315 ANTHROPIC out of the owner's vault on mainnet on 2026-10-06 (5GMPTgTg…). The plain SOL withdraw has not been used on mainnet yetstats block (live, it matched the leaderboard to the lamport). A labelled sample in Mock; in Live, anything it could not read shows as "—", never as 0. Today its numbers are one vault's, since the other two have not saved yetdXz3F1L3…), and the keeper reports it signable. Nothing has been settled from an imported wallet yet/prices answers JSON and /prices/view is the page for a reader: the SOL pool beside Pyth's on-chain account and beside Pyth's Hermes service, with the drift between the two; SPYx beside Pyth's own feed; ANTHROPIC beside PreStocks' own API, with the fee in force. Every figure carries its age or source. Checked live on 2026-09-26withdraw_token was exercised on mainnet for the first time on 2026-10-06, when the owner took 0.004312315 ANTHROPIC out of the vault (5GMPTgTg…). The plain SOL withdraw is implemented and tested, but has not yet been exercised on mainnet.