Trust
Security model
What Upstream defends against, what it asks you to trust, and what a dishonest party can do.
What you are asked to trust
- The platforms to show the right text on the right account and to let only the owner edit it.
- The attesters: at least
thresholdof them must be honest and must read the page they say they read. - The vault program (once it exists) to implement the rules in The vault. It would have no admin key.
Threats and answers
| Threat | Answer |
|---|---|
| Someone copies a posted code and asks to be paid | The code is bound to a wallet. For another wallet the attesters do not find their code. Tested. |
| Someone claims a handle they do not own | They cannot put text on the account. Without the code on the page no attester signs. |
| A handle is renamed or sold | The vault is bound to the platform's stable id. The new owner of the name has a different id. Tested. |
| One attester lies or is hacked | One signature is below the default threshold of 2 of 3. Tested. |
| The same attester signs twice to reach the threshold | Distinct keys only. Tested. |
| A key nobody trusts signs | Not in the trusted list, ignored. Tested. |
| An old signature is replayed | 15 minute freshness plus the epoch. Tested. |
| A hijacked account redirects the fees | Fresh proof, a two day delay, and a veto from the current wallet. |
| Fees sit unclaimed forever | Expiry sweeps them to the launcher or burns them. |
| A launcher takes most of the money | The streamer share cannot be under 50 percent. |
| Rounding loses money | Integer maths with the remainder to the streamer; the invariant is tested over 400 random operations. |
| The same attestations are replayed on another coin | They are bound to the mint. Refused by the engine and by the program. Tested. |
Someone makes two claims serialise to the same signed bytes by putting | in a field | Every field is validated before it is hashed or signed. A test checks that 336 different claims give 336 different messages. |
| Someone occupies another launcher's vault address | The address includes the launcher, who must sign. Tested on chain. |
| Someone passes their own account as the launcher or the incinerator to redirect a payout | Accounts are checked against the vault's own fields. Tested on chain. |
| A tampered signature | Solana's Ed25519 precompile fails the whole transaction before the program runs. Tested. |
| An attester endpoint is used to fetch arbitrary addresses | It only builds requests for the four platforms from validated handles. A test checks that bad input causes no outgoing request. |
| A page injects text through a profile field | The site writes platform data with textContent and never as HTML. |
What a dishonest attester can and cannot do
Can: sign something false. A single one cannot move money alone. If two collude, they can bind a wallet of their choosing to an account that has not claimed yet, and take the waiting fees.
Cannot: change the split, the expiry or the threshold; pay anyone other than the wallet in a code that was signed; move fees that were already paid to a bound wallet; sign for a vault that does not trust them.
The defences are the threshold, public attester identities, and, once a wallet is bound, the rotation delay and veto.
No admin key
There is no owner, no pause, no upgrade and no fee in the rules. The launcher chooses parameters at creation and cannot change them later, and pump.fun's own routing is one-way once set. Nobody can freeze or redirect a vault by decision. On chain this is only true once the program's upgrade authority has been removed (solana program set-upgrade-authority --final); until then the program's deployer can change it, which is why that step comes after an audit.
Privacy
Everything is public: the coin, the target account, the code, the attestations, the payouts. The proof reveals that a wallet controls a handle. This is not a privacy tool.
The website
The site has no backend and stores nothing. Reads go straight from your browser to the platforms. The demo wallet in the app is generated in your tab and never leaves it. Config keys that appear in config.js (such as a YouTube key) are public by nature: restrict them to your domain.