Introducing Native Crank for Ephemeral Rollups
Product Updates

Introducing Native Crank for Ephemeral Rollups

Andy (Developer Relations)
Andy (Developer Relations)
@fauxfire_

If you've ever built anything meaningful on Solana, you've probably faced this problem: there's no native way to schedule a transaction to happen. It’s basically impossible to do something even as simple as incrementing a counter every five minutes.

This isn't really an issue if you're just using the chain as a consumer. If someone wants to swap tokens or mint a NFT, they just sign a transaction, and the thing happens. 

But as a builder, what if you need game loops? Auction countdowns? Auto-compounding vaults? Subscription renewals?

You end up building janky offchain infrastructure like Heroku dynos running a script or a Lambda function on a timer. 

And even existing onchain crank solutions require paying transaction fees for every execution. That adds up fast when you're running thousands of operations.

There's a better way.

Cranks

Cranks are automated, scheduled tasks that execute onchain instructions at predetermined intervals without requiring anyone to manually trigger them. This allows you to create custom automations for your apps directly onchain.

We built this natively into our Ephemeral Rollups, which means you get:

- 50ms execution 
- No transaction fees
- Full SVM cryptographic guarantees

All you need to schedule a task is to tell our program to "run this instruction every N milliseconds." After that, we handle all the scheduling and execution.

Technical Implementation

I'm going to walk through a simple crank that increments a counter automatically.

Setup

We begin with just a simple counter struct, holding a number.

Next, we have a simple increment instruction that bumps the count by one. 

It’s important that this instruction is permissionless. 

When the crank calls a transaction, it's signed for by the validator. You can also use this property to set up your transactions to ONLY be called by a crank by adding a signer check.


Crank Initialization

Here's where the magic happens:

The three parameters you care about:

- `task_id` - A unique identifier for this scheduled task. This is mainly used to cancel this crank later.

- `execution_interval_millis` -  milliseconds between executions

- `iterations` - Total number of executions before stopping, no real max to this

Note that your accounts need to be delegated, as these cranks are only native to our Ephemeral Rollups. Read more about delegation here.

Client Example

On the TypeScript side, you're juggling two connections - one to base Solana, one to the Ephemeral Rollup. To handle this automatically, you can also use the Magic Router:

Then the flow goes:

1. Initialize on base layer:

2. Delegate to Ephemeral Rollup:

3. Schedule the crank (on the ER):

4. Wait for it to run, then undelegate:

After undelegation, your counter account is back on base Solana with `count = 3`.

Common Issues

In the example repo, notice how `ScheduleIncrement` uses `AccountInfo<'info>` instead of `Account<'info, Counter>` for the counter:

This is intentional. After you do a CPI, Anchor would normally try to re-serialize the account state - but since the account was modified by the CPI, you'd get stale data. Using raw `AccountInfo` avoids this footgun.

Next Steps

The counter example is obviously trivial, but the pattern unlocks some interesting use cases:

- Game loops — NPCs that move, resources that regenerate, time-based events

- Periodic settlements — Clearing houses, batch processing, escrow releases

- Auto-compounding — DeFi strategies that reinvest automatically

- Timed auctions — Countdowns that actually count down onchain

- Subscription systems — Recurring payments without offchain infrastructure

Basically anything that needs "do X every Y seconds" without trusting some offchain service to stay online.

Wrapping Up

Cranks are one of those primitives that seem simple but change what's possible. The ability to schedule onchain execution trustlessly opens up design space that was previously awkward or impossible.


If you want to try it yourself, here's the full example
And here are the docs for the crank