I’m currently writing a post summarizing my thoughts on launching tokens, but this info kept getting in the way. I decided to break it out to keep the other post more concise.
Launching via a custom token
Historically, if a deployer wants to customize their launch (perhaps attempting to dissuade snipers) they put custom code into their ERC-20.
ERC-20 is a standard; all ‘tokens’ created on an EVM follow it religiously (lets ignore rugs for now), to ensure that their token can be used by things like DEXs, wallets, and explorers without any issue.
As a developer, there are a few places that you can hook custom behaviors into a token. The most common one is the ‘transfer’ method. Here’s a famous example from $coq that limits each wallet to have only max 1% during the launch phase.
People have gotten more inventive over the years and created various types of anti-sniper features, but you’re still very limited by the information you have in this method, and there’s really no way to require additional information and still have a vanilla DEX work.
Take my word for it that there are a lot of mechanics you can use to evade anti sniper checks in your token contract.
Some of these can be combated, but there’s really no mechanism to fight against a sniper submitting tx from 10 different wallets.
Additionally, the various different mechanisms occasionally have the unwanted side effect of causing red flags to pop up on Dexscreener, which can hurt a token in the long run. I’ve highlighted a few that commonly get flagged even by well-meaning tokens trying to do anti snipe.
Custom Initial Distribution
One possible way to solve this issue is to have a customized method for initial distribution of the token.
A presale is one example of that; people send money, and then they later receive tokens, typically (but not always) at the same price as everyone else in the presale.
After the presale is complete, trading from that point onwards takes place on a vanilla DEX.
Custom DEX
There are a lot of factors that go into launching a token, but let’s say that you’re in a position where even after the presale you expect that there will be a lot of demand for the token, and you want to ensure that the initial buys are ‘fair’, while allowing people who want to exit immediately to do that. What do you do?
One option is to do something so custom that there’s no way to prepare automated buys (snipes) for it, which is what we did for the $blub, $woof, and $lok launches.
In those launches, we created a temporary DEX + UI for users to buy and sell on prior to migrating the liquidity to their final home on Pharaoh/Trader Joe.
The temporary DEX had a few anti snipe mechanisms that aren’t possible to implement directly in a token.
How buying tokens works
This is basically the way that it works (thanks Claude). The router is what most users use to swap the tokens. Users just give the router the address of the tokens they want to swap, and it resolves them to the Pair that has the liquidity needed for the swap.
A ‘custom DEX’
It’s relatively simple to just deploy your own Router and Factory, and create a Pair for your token. It just won’t be one of the ‘official’ routers that are supported by tools like Dexscreener.
But, problematically, there are many sniper tools (e.g. Sigma TG bot) that use their own custom router for buying tokens (so they can tack on a fee). These routers will automatically interact directly with the Pair when they see liquidity added, regardless of the ‘officialness’ of the factory/router.
Basic custom anti snipe features
The most basic thing you can do to stop people is add a password to the swap method.
Not very imaginatively named, but it gets the job done. You have to also give the password to the pair as well, since remember that they can skip your router entirely.
And, importantly, remember to set a max buy limit. Would be silly to just let the first person buy 2000A of your token manually and call that anti sniping.
With that, you have the basics of a ‘hard to snipe’ LP. Yes, it’s snipable if you know that the LP has a password in advance. And yes, it’s possible to circumvent even with a bit of time to research.
But trying to knock that out on an unverified contract in 5 minutes will be a bit challenging for even a qualified dev. Once the first few minutes are up, are you even in ‘snipe’ territory?
Advanced anti snipe features
But that’s just the basics.
If you’re doing a launch like this you ALSO control the UI, and the UI sets quite a few additional parameters that you can interrogate in a custom DEX, unlike in a vanilla shared DEX.
The amountOutMin, deadline, gas limit, and gas price (caveats apply) are all set by the UI, and available to the router. You can make them specific values, make them relate to each other, make them relate to the user, track state in the contract etc. As long as your UI knows what the magic is, it can make sure the TX it generates complies.
Maybe it’s viable to have an LLM quickly scan the anti snipe mechanism in the UI and build a tool, but I really doubt that beats just pressing buttons as quickly as you can (for now).
Outcome
This has come up again recently, but I’m 99.9% confident that no one automated a purchase on $blub.
Slightly more likely that someone did on $woof, but I added additional anti snipe between for that one and you can even see where someone attempted to snipe and failed.
On $lok, one person did manage to snipe for a 400A profit. Sadly I had thought of a mechanism to prevent that type of snipe the morning of launch, but decided that it wasn’t worth risking the launch, and had my record ruined.
Downsides of a custom DEX
OK so obviously this is a good way to make sure only humans are buying and selling in the first few minutes. But that doesn’t necessarily make it a good plan.
Building and testing
It’s a fair amount of effort to go down this route and even get it working at all. And then you have to do an incredible amount of testing to convince yourself that you did it right. And even then, it might not work right at launch.
One suggestion I have is that you can use Anvil from the Forge project to fork mainnet and do all your testing locally. This eliminates any chance that someone will spot your preparations.
Someone spotted Wink’s anti snipe by catching a single mistakenly verified contract on testnet that had ‘wink’ in the folder name (not even in the token name).
Hosting
You also become responsible for hosting the UI. The Blub presale site and Ferdy Fish were both DDOS’d prior to launch, so be ready to handle that in a worst case scenario. Hell, I’ve seen people fumble website launches even under normal user human load.
One thing we did for these launches was create and publish two different websites, both protected by Cloudflare, but one with the hardcore anti-DDOS measures turned on.
Launching
Doing the actual launch is even more stressful than a standard launch, since there are more moving parts. And there are more things to fuck up. You only get one chance in web3.
Although it got easier over time, we had a 22 point checklist of items to execute for $blub, and I had a terrible migraine when the launch was complete.
Even though we tested extensively, we still had a few steps of the launch plan fail and had to scramble to fix.
Chart
One problem with this mechanism is that Dexscreener displays the history for a token per liquidity pool. And your LP is temporary, only available at launch, before it migrates to a permanent DEX.
This means that the ‘initial PA’ for your token gets chopped off. If you launch at 1M MC, then migrate at 10M MC, and dip to 5M MC after migration, it looks like your token is down-only even though actually it’s 5x up from launch.
Price action
As mentioned above, you do lose that initial PA, which can be very bad. On the other hand, it does basically eliminate what you might call the ‘$$AIGG price action’ where a sniper buys $50K the same block that LP is added and then you’re down only forever.
Conclusion
I think this mechanism does solve the problem it’s asked to, but I’m not sure it’s a good idea, regardless. I’ll talk more about alternatives in my post on how to launch tokens.