Sign in

Untrusted executor

Suggest an edit

Nothing on Solana runs by itself, so every background job in a protocol needs someone to send a transaction and pay for it. Instead of running that bot yourself, you can pay for the job and let anyone do it. This works only if the result is the same no matter who sends the transaction.

Someone has to send the transaction

Remember the first constraint from the constraints lecture. Nothing happens by itself. A program cannot start running on its own. Paying rewards, settling trades, liquidating a loan and executing a proposal after a vote all need someone to build a transaction, sign it and pay its fee. That someone is the executor.

The simplest approach is to be the executor yourself. You run a bot, also called a keeper, on your own server. It watches the protocol and sends the transactions when they are due. It works on day one, but now the protocol lives exactly as long as your server does. If the server goes down, the bot's key leaks, or its wallet runs out of SOL for fees, the job stops. If the team leaves, the protocol stops with it. That goes against the idea of decentralization, which is the initial core idea behind on-chain protocols.

Just make the job profitable

A better option is to utilize game theory. Suppose every call to the job pays the executor of the call a small reward. Users will find it out and start writing their own bots to call it to earn rewards. It's pretty reasonable to assume that users want to make extra money, so it's also reasonable to assume that many different users would run such bots, and the job would no longer depend on a single executor.

The reward could be small, as long as it covers what the bot owner spent on the transaction fees and hosting expenses. Bots race for the same reward, and the losers' transactions fail but usually still pay fees, so the reward has to take into calculation that risk too. If the reward is reasonable and considers all these points at minimum, the protocol will definitely get the independent executors. If bot A goes offline, bot B sends the transaction instead, and nobody has to organize this.

Your own bot versus a paid jobTwo boxes side by side. The left box shows a single team bot sending transactions to the protocol, which stops if the server goes down, the key leaks or the team leaves. The right box shows three independent bots competing to send the same transaction to a protocol that pays a reward, where the first valid transaction takes the reward and any bot can replace another that goes offline. Who keeps the job running Your own bot team bot protocol 1 server, 1 key, 1 fee wallet server down: job stops key leaks: job stops team leaves: protocol stops A paid job bot A bot B bot C protocol pays a reward reward > fee + cost of a bot first valid tx takes the reward bot A down, bot B sends it A team bot runs the job while one server runs. A paid job runs while anyone wants the reward.
Untrusted executorA job box holding a reward coin. Three anonymous bots and a question mark all have arrows to the job. One arrow leads out of the job to the same result for every caller. Untrusted executor bot A bot B bot C anyone job $ reward same result Pay for the job and let anyone do it. The result does not depend on who sends it.

Nobody runs a liquidation service

Liquidation is the best-known paid job on Solana. Drift, Marginfi and Kamino all rely on outside bots to liquidate positions. When a borrower's collateral no longer covers the loan with enough margin, someone has to close the position fast, or the protocol takes the loss. The liquidator gets a reward taken from the failed position, usually collateral at a discount. Because every liquidation pays, bots watch every position on these protocols, and the borrower whose position failed pays for the service.

The result must not depend on the caller

Paying strangers to run a job has one condition. Imagine a rogue claim instruction that sends the reward to whoever signs the transaction. The first bot to notice would take every user's rewards. So the instruction has to send the reward to the intended user no matter who signs. The executor could trigger the job and do only that. This is why the pattern is called untrusted executor. It's because the protocol does not trust the executors, it only lets them do the part of the job where it does not matter who they are. That's only true if the executor cannot change what the instructions do.

Interestingly: Helium, Monaco and governance programs don't even pay the executors at all.

Helium pays rewards to the owners of hotspots (the devices that provide its wireless network). A set of oracles then signs the total reward each device has earned so far, and the device's account stores how much was already paid out. Let's say the oracles sign 100 tokens of rewards for a device in total, and the account says 80 tokens have already been paid. The claim instruction would pay the difference, 20 tokens, to the owner, and record that 100 were paid in total. Paying the owner makes the caller irrelevant, and recording the total amounts eliminates the possibility of getting paid twice. Together, they make the claim safe for anyone to call, so a stranger who claims for you only gives you a gift by paying the fee for you.

Monaco, a prediction market, separates matching from paying out. Matching only marks the orders as filled. Paying out is a separate instruction that anyone can call later, and the money goes to the order owners. Governance works the same way. After a vote passes, anyone can send the transaction that executes the proposal. The vote decided what happens. The executor only decides when.

The executor cannot change what the instruction does, but it still chooses when to send the transaction and which accounts to pass. Timing matters when the result depends on a price or a clock, so the instruction has to be correct at any moment it can be called. The accounts matter because the client brings every account, so the instruction checks each one exactly as it would for any other caller. More about callers passing the accounts themselves in the root of trust lecture.

Let bots compete on the reward

A fixed reward has a problem. If it is too high, the protocol overpays every time. If it is too low, nobody runs the job. Symmetry V3 lets the bots compete instead of choosing a number.

A Symmetry index fund holds several tokens in target shares, for example 50% SOL, 30% JUP and 20% BONK. When prices move, the real shares drift away from the targets, and the fund has to trade to bring them back. This trade is called a rebalance.

Symmetry offers the rebalance as a Dutch auction. The offer starts unattractive and gets a little better every slot until someone takes it. The bot's reward is the difference between the offered price and the market price. At first the price is good for the fund and the reward is tiny. Every slot the price moves toward the bot, and the reward grows. Many bots watch every fund, and each one has its own minimum reward. The trade goes to the first bot whose minimum is reached, so the fund pays roughly the smallest reward any bot would accept.

The numbers in the diagram below are illustrative. They show the shape of the auction. Symmetry's real parameters differ.

A rebalance offered as a Dutch auctionA bar chart of the bot's reward over six slots, growing by 0.1 percent each slot. Bot A accepts only at 0.5 percent or more, bot B accepts at 0.3 percent or more. In slot 3 the reward reaches 0.3 percent, bot B takes the trade, and slots 4 to 6 are never reached. The fund pays 0.3 percent, the smallest reward any bot accepted. A rebalance offered as a Dutch auction reward for the bot 0.1% 0.2% 0.3% 0.4% 0.5% 0.6% bot A wants 0.5% bot B wants 0.3% bot B takes it slots 4 to 6 never reached slot 1 slot 2 slot 3 slot 4 slot 5 slot 6 The reward grows every slot until the cheapest bot accepts it, so the fund pays the smallest reward any bot is willing to take.

Scheduled tasks with a prepaid reward

Helium's tuktuk turns this pattern into a general scheduler. A task is an account that holds a reward, paid up front by whoever created the task, and a condition for when it may run, such as "not before 12:00 UTC". Once the condition is met, any bot can run the task, take the reward and close the account. What the task does is fixed by its creator, so the bot can run it but cannot change it. A repeating job creates its next task while it runs, so a daily job keeps scheduling itself with no team server behind it.

The same idea beyond background jobs

Rewards are a nice protocol design hack in general. If some actions in your protocol pay more than the other ones, users move toward those actions without being asked. Simple game theory in action. A liquidation reward makes users watch positions, a Dutch auction makes bots compete on price, and a prepaid task makes bots run your schedule. If you need users to do something, make that action pay.

Check every background job

When you design a protocol, list every action that has to happen without a user asking for it, such as paying rewards, settling trades, liquidations, expiring orders and rebalancing. For each one, answer three questions. Who is paid to call it, and can the reward cover the costs of the transaction? Could the result stay the same no matter who called the transaction? Based on these questions, you would figure whether the job could no longer depend on your server. Your own bot could still run, but just as one executor among many, with no special permissions.