Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[KIP-247] Gasless Transaction #47

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
200 changes: 200 additions & 0 deletions KIPs/kip-247.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
---
kip: 247
title: Gasless Transaction
author: Ian (@ian0371), Ollie (@blukat29)
discussions-to: TBU
status: Draft
type: Core
created: 2025-02-18
requires: 245
---

## Abstract

This KIP introduces Gasless Transaction (GaslessTx) where users can swap whitelisted fungible tokens into KAIA without possessing any KAIA.

## Motivation

For users who have onboarded onto KAIA from another blockchain via a bridge, it is possible that they do not possess any KAIA tokens and hold only fungible tokens from the bridged assets.
These users will be unable to perform any on-chain actions unless they acquire KAIA through alternative channels.
This limitation effectively restricts their ability to engage with decentralized applications, execute transactions, or participate in any protocol activities within the KAIA ecosystem.

To enhance the user experience for those, this KIP introduces a concept of gasless transaction (GaslessTx) where transactions with a specific pattern is recognized as the GaslessTx.
Upon detection of GaslessTx, the block proposer may lend the user KAIA to facilitate the GaslessTx execution.
A gasless swap from Token to KAIA shall pay back the lent amount.

## Specification

### Definition of GaslessTx

There are two types of GaslessTx: GaslessApproveTx, and GaslessSwapTx.

#### GaslessApproveTx

A GaslessApproveTx must meet all the following conditions to be inserted to `txpool.queue`:

- A1: `GaslessApproveTx.to` is a whitelisted ERC-20 token.
- A2: `GaslessApproveTx.data` is `approve(spender, amount)`.
- A3: `spender` is a whitelisted `GaslessSwapRouter`.
- A4: `amount` is a nonzero.

(Note that above statements can be verified solely through a static validation of a transaction.)

A GaslessApproveTx must meet all the following conditions to be promoted to `txpool.pending`:

- AP1: GaslessApproveTx is followed by a GaslessSwapTx of the same sender and the `GaslessSwapTx` can be promoted to `txpool.pending`.

#### GaslessSwapTx

A `GaslessSwapTx` must meet all the following conditions to be inserted to `txpool.queue`:

- S1: `GaslessSwapTx.to` is a whitelisted `GaslessSwapRouter`.
- S2: `GaslessSwapTx.data` is `swapForGas(token, amountIn, amountOut, amountRepay)`.
- S3. `token` is a whitelisted ERC20 token.

(Note that above statements can be verified solely through a static validation of a transaction.)

A `GaslessSwapTx` must meet all the following conditions to be promoted to `txpool.pending`:

- SP1: (If GaslessApproveTx exists in `txpool.queue`) `GaslessApproveTx.to=token`.
- SP2: (If GaslessApproveTx exists in `txpool.queue`) `GaslessApproveTx.data.amount>=amountIn`.
- SP3: `amountRepay` is the correct value.
- (If GaslessApproveTx exists in `txpool.queue`) `amountRepay = CalcRepayAmount(GaslessApproveTx, GaslessSwapTx)`.
- (otherwise) `amountRepay = amountRepay(GaslessSwapTx)`.
- `amountRepay(GaslessApproveTx, GaslessSwapTx) = V1 + V2 + V3` and `amountRepay(GaslessSwapTx) = V1 + V3` where
- `V1 = LendTx.Fee() = SwapTx.GasPrice() * 21000`
- `V2 = ApproveTx.Fee()` (if exists)
- `V3 = SwapTx.Fee()`

While GaslessApproveTx must be followed by with GaslessSwapTx in order to be promoted, GaslessSwapTx can exist by itself.

### Definition of LendTx

Upon detection of a GaslessTx (either GaslessApproveTx or GaslessSwapTx), the block proposer shall inject a transaction, denoted by LendTx, which transfers KAIA to the GaslessTx sender. LendTx must meet all the following requirements:

- L1: `LendTx.type` is 0x7802, a Ethereum dynamic fee transaction type.
- L2: `LendTx.from` is the proposer itself.
- L3: `LendTx.to` is `GaslessSwapTx.from`
- L4: `LendTx.value` is `amountLend`
- `amountLend` is `V2 + V3` (from aforementioned `amountRepay` definition).

### GaslessSwapRouter

GaslessSwapRouter is a smart contract responsible for token swap and repayment. It supports only single-hop swaps through a predetermined DEX contract. It must support the following interface:

```
interface IKIP247 {
function swapForGas(address token, uint256 amountIn, uint256 minAmountOut, uint256 amountRepay) external;
function addToken(address token, address dex) external;
function removeToken(address token) external;

function claimCommission() external;
function updateCommissionRate(uint256 _commissionRate) external;

// view functions
function dexAddress(address token) external view returns (address dex);
function getAmountIn(address token, uint amountOut) external view returns (uint amountIn);
}
```

`swapForGas()` must ensure that all the following conditions are satisfied:

- R1: Sender has enough tokens. That is, `token.balanceOf(msg.sender) >= amountIn`.
- R2: Token is whitelisted and has a corresponding DEX address other than zero.
- R3: `amountReceived >= minAmountOut >= amountRepay` where `amountReceived` is the swap output.

`swapForGas()` must distribute the swap output (`amountReceived`) as follows:

- The block proposer (`block.coinbase`) receives `amountRepay`.
- User receives `(amountReceived - amountRepay) * (1 - commissionRate)`.
- The commission `(amountReceived - amountRepay) * commissionRate` is stored in the contract for later claim.

### TxPool Policy Updates

#### GaslessTx Validation (validateTx)

To prevent GaslessTx to be discarded, the validation logic at `txpool.queue` insertion needs to detect GaslessTx and skip the account balance check.

```
// txpool.validateTx()
if ...
else: // if tx is NOT feeDelegatedTx
if senderBalance.Cmp(tx.Cost()) < 0:
if tx is GaslessTx:
validation ok
else:
insufficientFund error
```

#### Promoting GaslessTx (promoteExecutables)

GaslessApproveTx cannot be executed unless the corresponding GaslessSwapTx from the same sender is already in the transaction pool.
Conversely, if the token has not been approved, GaslessSwapTx cannot be executed before GaslessApproveTx.
In such cases, both transactions need to be promoted simultaneously.

```
// txpool.promoteExecutables()
if tx is GaslessApproveTx:
assert tx.nonce == getNonce(tx.from)
if GaslessSwapTx is in queue:
assert GaslessSwapTx.nonce == getNonce(tx.from) + 1
promote tx and GaslessSwapTx to pending
else:
push tx to queue

if tx is GaslessSwapTx:
if tx is GaslessApproveTx is in queue:
assert GaslessApproveTx.nonce == getNonce(tx.from)
promote tx and GaslessApproveTx to pending
else if tx.nonce == getNonce(tx.from):
promote tx to pending
else if tx.nonce == getNonce(tx.from) + 1:
push tx to queue
```

#### Transaction Bundling

This KIP implements `TxBundlingModule` specified in [KIP-245](https://kips.kaia.io/KIPs/kip-245). These are the possible bundles:

- LendTx - GaslessApproveTx - GaslessSwapTx
- LendTx - GaslessSwapTx

```
ExtractTxBundles(txs, prevBundles):
if GaslessTx is disabled:
return nothing

filter ApproveTx, SwapTx from txs
move ApproveTx (if exists) before SwapTx
inject LendTx before ApproveTx if exists, otherwise before SwapTx
```

## Rationale

### Stateless transaction validations

The existing validation logics in transaction pool (`validateTx()`) ensures that the transaction sender has sufficient KAIA to cover the gas fee.
However, this KIP does not propose a comparable validation mechanism for GaslessTxs such as ERC-20 token balance checks.
Instead, it suggests stateless transaction validation logics, specifically A{1-4}, AP1, S{1-3}, SP{1-3}.

While the computational overhead of performing stateful validations via EVM calls may not be significant, such validations inherently lack reliability. They may become obsolete and ineffective since the state database can change between transaction validation and execution.
To address this, this KIP relies on [KIP-245](https://kips.kaia.io/KIPs/kip-245) where all transactions including LendTx will be excluded from the block when GaslessTx reverts.
Thus, this KIP proposes the most basic format checks of GaslessTx in transaction pool.

### Disabling GaslessTx

If many consensus nodes disabled GaslessTx feature, users may experience increased transaction latency.
However, as long as there are still nodes supporting GaslessTx, the transactions will eventually be executed.
Also, because this feature is enabled by default, few consensus nodes are expected to disable it.

## Backward Compatibility

This does not affect the backward compatibility because this does not involve hardfork.

## References

- [KIP-245](https://kips.kaia.io/KIPs/kip-245)

## Copyright

Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
Loading