Automated Rebase Farming on OHM Forks

Since this opportunity has dried up and I don’t see it coming back in the near future, I’m going to share my journey in farming OHM forks with high rebase percentages.

Genesis of the Idea

I don’t pretend to be an expert on OHM. In fact, I’d say I know very little about the protocol other than the flow of the staking/unstaking contracts, and that the supply grows or rebases by a certain percentage every ~8 hours. As OHM became popular, forks started sprouting up all over the place. Many of these protocols offered massive APYs and extremely high rebase percentages as a form of marketing. A lot of these turned out to be scams, soft rugs, cash grabs, etc. The price graph usually looks something like this due to the heavy dilution or eventual rug pull/manipulation:

Example Price Chart for OHM Fork (Real Example)
Example Price Chart for OHM Fork (Real Example)

Some rebase percentages were as high as 5-6% every 8 hours. That means, if I have X tokens staked in the protocol at time t, when the rebase happens at t+1, I will now have X * 1.05 tokens. The key is that it doesn’t matter how long the tokens are staked. I could stake 1 second/block before the rebase and still receive the entire benefit of the rebase. A typical spread on a Uniswap V2 trade is 0.6% (0.3% LP fee on each side). My idea was to keep my bankroll in a stable coin and:

  1. Swap to the protocol token and stake right before or very close to the rebase (<1 minute).
  2. Wait for the rebase.
  3. Unstake and swap back to the stable coin.

Farm the rebases without the risk of the token price dilution. The primary risks were :

1.) The price action in the period of time between swapping in and swapping out

2.) Any coding errors I made along the way that resulted in failed transactions.

If the rebase was high enough and the price action wasn’t crazy within that brief window, I could beat the LP and gas fees and make a profit.

The profit would be:

Stable Amount After (includes lp fees from both swaps) - Stable Amount Before - Tx Fees

The Game Plan

This idea seemed very basic and I wasn’t the only person to run it, but it didn’t seem very crowded to me. Monitoring Dexscreener around the rebase times and glancing at the block explorer I only ever saw one other participant consistently run the strategy I’m outlining here (more on this later). Many defi wizards were likely spending their time on adventures with higher notional dollar amounts at stake. Whatever the reason, I was happy with my small piece of the pie.

  • Focus on chains with cheap transaction fees and lots of forks. Avalanche was where I spent the majority of my time with brief stints on Binance. Polygon was on my radar but no forks ever popped up that presented high value opportunities.
  • Find forks with very high (3%+) rebase percentages, enough liquidity for my position size, and 0 warmup period. The warmup period is a feature in the OHM contracts that locks your rebase rewards for a certain amount of rebase periods. I needed to target protocols with 0 warmup period or the strategy wouldn’t work as I wouldn’t be able to swap in and out while receiving the rebase. A lot of forks launched with a 2 or 3 base warmup period, or added it after the fact to prevent the strategy I’m outlining. (My personal opinion is that it does nothing to prevent the price dilution in the long run. It just benefits early entrants since they are able to dump on later entrants down the line).
  • Automate the following process:
    • Swap from stables to the protocol token
    • Stake the protocol token
    • Wait for the rebase
    • Unstake the protocol token and swap back to stables

This meant becoming familiar with the UniswapV2/Trader Joe contracts, Uniswap/Trader Joe SDK (for scripting), and the Olympus contracts and its forks.

Version One

Version one did not utilize any custom smart contracts, and was just a node script that I manually launched from my terminal when the rebase period was approaching. I would just use a basic provider listener with ethers, check if some conditions were met, swap from the Trader Joe SDK and Router, and then stake into the protocol.

When I originally read the Olympus contracts, I thought the rebase had to be triggered by the next person to stake or unstake after the rebase was valid. So I was using an event listener that listened for the rebase and then unstaked and swapped back. Depending on how much action was happening on the protocol, sometimes my script would be stuck in limbo waiting for the rebase to fire.

My breakthrough came when I was reading the contracts again to solidify my understanding of how they worked. Originally, I had thought the rebase HAD to be triggered by a stake or an unstake. I realized that the rebase function could be triggered by anyone externally as long as the timing condition was valid. It was simply an external function. This would allow a trigger of the rebase and then I could unstake and swap all in the same transaction with a custom smart contract.

Flaws in V1: Waited for the rebase event, exacerbating exposure to token price action. Slow to sell. Gas inefficient. Vulnerable to transaction failures since trading parameters were calculated off chain for the sell after the rebase.

Version Two

Once I understood that the rebase can be triggered externally on its own I switched to using custom smart contracts to package my transactions under a single transaction (swap and stake, rebase, unstake and swap, etc.).

The methods looked like the below:

Version 2 Custom Contract Methods
Version 2 Custom Contract Methods

V2 was better, but still inefficient with timing because it hadn’t implemented a feature to revert if the rebase wasn’t ready. I was trying to time the rebase exactly with my script but I was all over the place due to inconsistent latency. I also ran a risk of being too early, which means I would gain nothing from the rebase and just lose to Gas and LP fees. This led to me being late to trigger my calls, and sometimes losing money to price action after the rebase to another participant running a similar strategy.

Enter Player 2

I noticed one other participant, who I will name Player 2, was running the same strategy with more sophistication and better timing than I had. They bought very close to the rebase (within 5 seconds usually), and had impeccable timing to always be the first to sell after the rebase. I was still profitable if the rebase percentage was high enough and if I was second to sell. However, they were still eating into my profits. Depending on the liquidity available, rebase percentage, and other random price action prior to the rebase, their dump would sometimes make my trades unprofitable. I needed to be faster.

I started sleuthing Player 2’s address and contracts linked to their address on chain to find opportunities about new launches, etc. They were usually playing large positions relative to the liquidity pool (5-10% of outstanding liquidity), so when they did their initial swap into the protocol, the price rose significantly. I noticed their contracts had many failed transactions which tipped me off to the fact they were probably trying many transactions to get the timing right and reverting if it didn’t meet a certain criteria. My new goal was to design a system where I could buy and stake before this participant (since they were buying last second), then be faster to sell after the rebase. This would give me both the benefit of price increase and the rebase.

Flaws in V2: Extremely hard to time as being early meant losing money, and being late was vulnerable to sell pressure after the rebase.

Final Version

I realized that I could simply store the timestamp I needed in my custom smart contract and revert the transaction if the block timestamp was not ready for rebasing. I could store the endTime/endBlock from the Staking contract when I first swapped in and staked.

Abstract Contract for the Staking Protocol -- Getting the Epoch End Time
Abstract Contract for the Staking Protocol -- Getting the Epoch End Time
Storing the endTime While Swapping and Staking
Storing the endTime While Swapping and Staking
Final Version of Unstake and Swap -- Reverting If Not Ready
Final Version of Unstake and Swap -- Reverting If Not Ready

Note: I didn’t actually need to store the timestamp -- it was for debugging purposes.

I also needed a way to guarantee my transaction would be included in the first rebase eligible block.

I designed a sloppy script that used setInterval and would send a tx attempt every 200ms or so (to account for latency) within a certain timeframe of the rebase. I was a bit fuzzy on how the details worked behind the scenes with the listeners and intervals, but I was making successful trades and that’s all that mattered to me at the time.

My strategy was likely inefficient from a gas and failed transaction fee standpoint because I had a tons of failed transactions after my successful one, but it (nearly) guaranteed first out as long as my gas bid was high enough. I think the contract could be improved by checking the balance of the protocol token prior to calling the swap router and revert if it was 0, instead of reverting within the router and using extra gas.

My shining moment was being able to beat Player 2 by swapping and staking before them, and then being first to sell on other side of the rebase. Capturing both the rebase percentage and the price appreciation from their buy.

The following screenshots tell the story. To respect their privacy and protect mine, I’ve blacked out values that make it easy to find the addresses involved, but I’m sure some experienced readers could still track these transactions down quite easily.

My Entry -- Swapping 3025.91 MIM for 22.86 Protocol Token
My Entry -- Swapping 3025.91 MIM for 22.86 Protocol Token
Player 2's Entry -- Swapping 4509.57 MIM for 27.57 Protocol Token
Player 2's Entry -- Swapping 4509.57 MIM for 27.57 Protocol Token

To exit, I was able to get a transaction through using my script and I bid a significantly higher gas price than Player 2. I was first to sell. Our transactions were actually mined in the same exact block, with mine being first and theirs being second.

Transactions For Unstake Block -- My Tx Circled in Red, Player 2 in Green
Transactions For Unstake Block -- My Tx Circled in Red, Player 2 in Green
My Exit -- Swapping 24.28 Protocol Token for 4004.44 MIM
My Exit -- Swapping 24.28 Protocol Token for 4004.44 MIM
Player 2 Exit -- Swapping 29.29 Protocol Token for 3866 MIM
Player 2 Exit -- Swapping 29.29 Protocol Token for 3866 MIM

If you do the math, I used 3025.91 MIM to buy 22.86 tokens for a price of 132.37 MIM per token. I then sold 24.28 tokens for 4004.44 MIM at a price of 164.93 MIM per token. This a rebase of 6.2% (24.28/22.86) and a price appreciation of 24.5% over the course of 16 seconds! After gas fees I profited close to 950 MIM.

Player 2 used 4509.57 MIM to purchase 27.57 tokens for a price of 163.57 MIM per token. They ended up selling 29.29 tokens for 3866 MIM at a price of 131.99 MIM per token. This a loss of 643.57 MIM before gas fees. My selling before them had tanked the price. Ouch.

After my shining moment, I had some profitable trades on other protocols for a small while, but opportunity quickly dried up as protocols lowered their rebase rewards and the market got cold. Eventually I woke up one day and nothing looked attractive and it has been that way since.

Side Note: I thought about trying to pair up with a miner to privately mine my tx and tip them (similar to flashbots on Ethereum). I couldn’t find anything for Avax (initial research indicates something like flashbots doesn’t exist). My strategy was working decently, and I didn’t know how sustainable these forks were so I didn’t pursue it further. I had very little experience with flashbots and didn’t want to dive into something when I wasn’t 100% sure what I was doing. I’d love to know more about how this would be possible on both Avax/Eth and what the differences are.

Areas That Still Needed Improvement

  • Find the most gas efficient way to revert the transaction once the rebase period had triggered, but I already had a successful swap out.
  • More optimization around latency and the interval for the timer. It was still mostly a “spray and pray” method that spammed the network with transactions and hoped one landed in the first eligible rebase block.
  • Optimizing when to enter based on latency and other participants and their strategies. Minimizing any price exposure is key. People do irrational things and sometimes people would sell large quantities right before the rebase even if it made no sense. This pushed the profitability of my strategy down or made it outright unprofitable. Finding the right entry timing seemed more of an art than a science.
  • Finding a way to fully automate with cloud servers, CRON jobs, reconnecting on dropped RPC connections, retrying failed swaps. The last 2% of automation is always the hardest. I was just setting alarms on my phone and firing my scripts manually.

Concluding Thoughts

As the crypto market started to “crash”, and Olympus/Wonderland along with it, less forks started to launch and these opportunities have become nonexistent. It’s been nearly a month with no plays for this strategy. I don’t think it’s coming back anytime soon, so I thought sharing this would be fun and a nice reflection on my first live foray into automated trading, arbitrage, or whatever else you want to label it.

At the end, I was getting very good at being able to spin up a bot from a shell in ~20 minutes based on a brief look at the deployed smart contracts of a protocol. I would edit the variables, run a test on a local fork of AVAX Mainnet to make sure nothing was incorrect in terms of addresses or approvals, then launch it live and take it for a spin.

I didn’t get rich, but I made some money in the process, and learned A LOT about a variety of different topics. If you’re interested in hearing more or want to collab about other small opportunities that may be lurking in defi, feel free to DM me on twitter. Thanks for reading.

Subscribe to Derked
Receive the latest updates directly to your inbox.
This entry has been permanently stored onchain and signed by its creator.