- Alex's Accounts
- Posts
- Let's wrap up 2025
Let's wrap up 2025
A lot of things happened this year. I'll try to extract some lessons from it all here.
I’ve grown to like this table of contents stuff and BeeHiiv automates it, so here you go.
Table of Contents
Life is a perpetual multi-armed bandit problem
Imagine a gambler at a row of slot machines with unknown win rates. You want to win as much as possible, but to begin with you have no idea how much each machine will give you.
So you start an exploration phase, you try each slot machine (also called “bandit” sometimes) a number of times until you get a feel for how much you’d win at each.
There is some science behind how much you should play at each machine to figure out a win rate number you can be confident in, but the key thing for our purpose here is that you do need a decent sample size otherwise you can be affected by statistical variance.
After you feel confident in your estimate of the win rate for each machine you can now decide on which to play to maximize your wins.
Enter the exploitation phase. You play with more volume at the slot machine that you’ve identified has the best win rate to rake in as much cash as possible.
All of that sounds a whole lot like real life in my opinion.
A lot of us spent our teens & early 20s exploring ideas, businesses, careers and eventually by our late 20s or early 30s we figured out what works for us and doubled down there.
Now, what I’m here to do is tell you that in life the slot machines are not fixed. The odds of any given slot machine change all the time and sometimes new slot machines get added and old ones get removed.
I’ve played this “game” multiple times in my life, but I’ll try to give you a compressed personal anecdote. In December 2024 I was recently laid off. At that point I had already given up on my auditing aspirations.
I was good with Go & TypeScript and initially thought I’d keep focusing on my blockchain indexing skills since that’s what I had worked on for almost 2 years at that point.
But after some interviewing in that area I had a feeling crypto might be dead-ish and tried to pivot into AI. I built a RAG solution, met various people in that world and soon learned that they’re not as open to global remote as the crypto industry is.
Solana wasn’t even on the map for me, but someone asked me to help with a prediction market PoC and being that my savings were running out I said yes. As soon as that happened and I could say I have worked on Solana my inbox blew up with job offers and consulting offers (even though I was the one eyed man leading the blind tbh).
I ended up doing more Solana work which eventually got me an offer from Guardian to do Solana audits for them. Even tho I was not a professional auditor yet, my Solana expertise was useful. I have by now been involved in 4 private audits and there’s more to come.
This is all thanks to perpetual exploration. I can’t tell you what to explore or with what cadence, but I can tell you that: even once you find a game you like playing and you’ve entered the exploitation phase, I still believe it’s really powerful to take some time here and there for some exploration.
Often you’ll find your game is still better, but every once in a while you might find a better game that you can exploit.
Lessons from my most recent private audits
Recently I’ve had awesome opportunities to do 3 audits through Guardian for companies like Jupiter and M0 and also did a short solo review for Onyx.
I audited a stablecoin minting protocol (users provide USDC/USDT/etc and get a wrapper token; you need to look out for the oracle integrations mainly), a cross-chain order book and a program for on-chain SAFEs.
I’ve learned a few important things from these audits:
1. Always ask what the trust assumptions are
I’ve realized that how much you want to trust that the admins is a big, important question to ask from the protocol when you begin an audit.
Some protocols trust the admins (or other permissioned roles) absolutely and some not at all which is how you can get situations where a fee-on-transfer bug is a High in one report and invalid in another.
My personal opinion is that you should trust the admins as little as possible. History has thought us that both bad opsec and honest mistakes when using admin-only functions are real problems and often a matter of when, not if.
That said, the client pays for a service and if they so choose to fully trust the admin, that’s up to them.
Side note: Let me quickly go over FoT (fee-on-transfer) bugs. Some protocols allow both classic SPL tokens and token2022 tokens. The latter can (but not always will) have various add-ons including fee-on-transfer mechanisms.
If you allow these FoT tokens in and also do not account for potential fees when doing token transfers… it can result in the system thinking it has received $100 when in reality it has $98. The easy fix is to just disallow FoT tokens (or potentially token2022 entirely) from the system.
2. There’s one more way to fuck up under/over-flows
I’ve talked about this class of bugs before here. One thing I took care to mention was that in dev release your code would still panic if it under/over-flows but that would not be the same in prod release.
Well, I’ve learned you can modify your profile.release to have this:
overflow-checks = true
Aaand now it will panic. It’s better to panic instead of using completely erroneous data, but that can still be bad.
If you’d have used the checked_* family of functions like I usually suggest, that returns None if it under/over-flows as explained here. It does not panic and it allows you to decide what to do with that None value. Also, the compiler forces you to handle it in some way. You can still use .unwrap() and panic if you so desire, but it’s more explicit.
Why is explicit better? A simple example is that a panic could, in theory, result in a DoS and it’d be easier imho to spot a potential issue like that if you saw .unwrap() rather than x - z.
On top of that, you have the ability to return a defined named error rather than use .unwrap() which might make frontend people hate you less.
This (using the profile.release vs checked_*) isn’t in and of itself an issue though, it’s just a thing to look out for.
I’m sure there are other interesting things you can set in profile.release as well, but I haven’t researched that a lot yet. Maybe a future article.
3. Short pre-audit reviews can be great value
The review I did for Onyx was short, just 1 day. I couldn’t make it through the whole codebase that quickly, but nonetheless I found a few bugs for them and gave them a few leads to explore further.
These sort of short solo reviews can (and do) get the easy bugs out of the way early so that when time comes for a full audit the auditors can focus more on finding the deeper creative bugs and vulnerabilities (if they exist at all). I believe that is great value.
I’d even go as far as to recommend that more protocols first do a short 1-2 day consultation with an auditor in the architectural phase before they write any code. This should tell them if the architecture makes sense and where problematic points or flows might exist.
More importantly, I want you to think of security like a series of nets. The first nets are cheaper and have bigger holes but they’ll still catch the majority of things. The latter nets are more expensive and more granular.
This way you’ll end up with more bang for your buck in my humble opinion.
4. I really really love this shit
Recently I tweeted about almost finding my first critical in an audit. After some more time spend thinking on it and also doing a PoC, I’ve realized that the protocol was saved (by a thread if I may say so).
Researching that specific lead was a rollercoaster tho. Had a few small details been different the vulnerability would have had the ability to be exploited such that it would’ve resulted in cheap DOS or even stealing of funds without having a permissioned role.
I still reported the “bug”, but as a best practice where I recommended a defensive measure, just to be safe. I strongly believe auditors should recommend such measures and devs should take info/low reports seriously even if they can’t result in damage now.
Ultimately tho I realized that I loved that rollercoaster. It was just exhilarating. I want more of this which has led me to set some bold goals for 2026.
Coming soon: a short primer on Solana validation bugs
I’m not sure if I ever told you, but my article on Solana CPIs (external calls) made it to the “awesome-solana-security” list from 0xMacro which makes me very proud since I’ve previously used this list to learn myself.
In that spirit, I feel motivated to write a similar article but on access control and validation in the context of Anchor and Solana.
I unfortunately got sick during the holidays and couldn’t deliver this year, but I promise this is the very next article I write. It will be a fun way to kick off 2026.
Plans for 2026
More audits, more Solana work, I want to explore Pinocchio (a low-level Solana framework). I want to write more articles about Solana.
In fact, my biggest boldest goal for 2026 is that I want to become one of the top guys when it comes to Solana programs. I want to be up there with the best of them. Wish me luck!