How it works
Beginner-friendly deep dive into how Octane signs gasless transactions

Initial state

Let's say Alice wants to transfer 5 USDC to Bob.
10 USDC, 0 SOL
20 USDC, 0 SOL
Octane fee payer
For each transaction on Solana network, someone has to pay transaction fees. The fees are extremely low (less than a cent), but have to be paid in SOL. When Alice has 0 SOL, the transfer isn't possible.
Can someone else pay for Alice's transaction fees? Yes, Octane node owner for an equivalent payment from Alice in USDC.

Some Solana specifics

Before we move on to the Octane transaction flow, we'd like to highlight some important Solana properties that Octane leverages.
Fee payer is a transaction property
When transaction is submitted, the client can specify who fill pay transaction fees. Solana validates just that fee payer was one of the signers of the transaction.
const transaction = new Transaction();
transaction.feePayer = // ...
Multiple signers within one transaction
Surprisingly for many people coming from the EVM ecosystem, Solana uses signatures, not signature. Signatures should cover all of the writable activities within the transaction, including fee payment process: if some public key is listed as fee payer, there should be a signature from that public key in the signatures rarray.
export class Transaction {
* Signatures for the transaction. Typically created by invoking the
* `sign()` method
signatures: Array<SignaturePubkeyPair>;
get signature(): Buffer | null;
feePayer?: PublicKey;
instructions: Array<TransactionInstruction>;
recentBlockhash?: Blockhash;
// [...]
Atomic execution
Another notable difference from the EVM is that transaction can contain multiple, atomically-executed instructions. Each instruction could be any program interaction, for example, token transfers. When someone signs a transaction, they sign all of its instructions atomically.

Octane flow

Back to Alice, Bob and Octane!
  1. 1.
    Octane node owner sets up a API server and a wallet with some SOL. The node owner sets in configuration they would like to pay 0.000005 SOL transaction fee for 0.01 USDC.
  2. 2.
    Alice creates a transaction with two instructions:
    1. 1.
      Send 0.01 USDC to Octane
    2. 2.
      Send 5 USDC to Bob
  3. 3.
    Alice sets the fee payer property of the transaction to Octane
  4. 4.
    Alice signs the transaction
  5. 5.
    Alice sends the serialized transaction to Octane API server
  6. 6.
    Octane makes a few checks on the transaction:
    1. 1.
      Was Octane sent 0.01 USDC in this transaction? If no, abort.
    2. 2.
      Does the transaction try to perform something writable on Octane account, other that fee payment process? If yes, abort.
  7. 7.
    Octane signs the transaction and returns signature to Alice.
  8. 8.
    Alice adds Octane's signature to transaction and submits it to the network.
  9. 9.
    Solana gladly accepts the transaction, since both the fee payer and Alice signed it. Octane is happy to pay for the transaction fee, since it knows that it gets 0.01 USDC in this transaction.
The final state will look like this:
4.99 USDC, 0 SOL 10 USDC, 0 SOL
25 USDC, 0 SOL 0 USDC, 0 SOL
Octane fee payer
0.01 USDC, 0.999995 SOL 0 USDC, 1 SOL
Even though we used Alice-to-Bob transfer as a "payload instruction", it could've been any other instruction — for example, NFT mint or a swap.

Creating accounts

In this case, Bob already had 20 USDC. It means that associated token account was already created. However, if Bob never held USDC previously, Alice has to create new account for Bob.
When creating a new account, Solana requires to top it this account with some SOL — "a rent-exemption minimum". Alice might not have any SOL, so Octane has a special endpoint to create associated token account, paying for it with an SPL token.
This endpoint has to be called before forming the main transfer transaction. Similar to the main transaction flow, Alice would have to create a transaction with two instructions: transferring some USDC to Octane and creating a new associated token account. Octane would sign the transaction and then, when it's sent and confirmed on the network, Alice would be able to start the main transaction flow.