# Chi Gas Tokens: How the Old Refund Strategy Worked

Author: Markus Waas

Published: 2021-03-13T21:02:45.000Z

Updated: 2026-09-13T14:25:30.000Z

Source: [https://soliditydeveloper.com/chi-gas](<https://soliditydeveloper.com/chi-gas>)

## Compatibility and review

Before you start

Historical pre-London gas-token tutorial. EIP-3529 removed SELFDESTRUCT refunds and reduced storage refunds, ending the Ethereum gas-refund economics described here. Kovan is retired. Do not follow the mint/approve/deploy walkthrough as a current gas-saving technique.

[Official reference](<https://eips.ethereum.org/EIPS/eip-3529>)

![Gas Prices Meme](<https://cdn0.scrvt.com/b095ee27d37b3d7b6b150adba9ac6ec8/b2485e5c7cbcc984/fe21342f05e6/v/48a1b3199438/gas-prices-meme.png>)

Gas prices have been occasionally above 1000 Gwei in the past in peak times. Given an ETH price of over 1000 USD, this can lead to insane real transaction costs. In particular this can be a pain when using onchain DEX's like Uniswap, resulting in hundreds of dollars transaction fees for a single trade.

People have been using gas tokens to combat this issue. Let's explore what those are, how to use them and how you would integrate them to trade on Uniswap.

## What are Gas Tokens?

Gas tokens are an Ethereum ERC-20 token that allows users to tokenize gas on the Ethereum network, storing [gas](<https://ethereum.stackexchange.com/questions/3/what-is-meant-by-the-term-gas>) when it is cheap and using / deploying this gas when it is expensive.

Using GasToken is particularly useful for scenarios of arbitraging decentralized exchanges or buying into ICOs early. They further allow users to buy and sell gas directly, enabling long-term "banking" of gas that can help shield users from rising gas prices.

The gas tokens work due to the refund mechanism of the Ethereum network. Whenever you release storage, Ethereum will refund you some gas for it, because you are reducing the size of the blockchain. Zero-ing a 32 bytes storage variable releases 15000 gas, while the setting to 0 operation costs 5000, effectively giving you a 3x gas return. Alternatively one can self-destruct a contract. This would cost 700 for the the call to the contract + 5000 for the selfdestruct operation, but refunds quite a bit more: 24000 gas.

And this is what gas tokens are using. You can mint them and they will store data in the contract. Then you can burn the tokens inside a transaction which will release gas. Refunds can only give up to half of the gas used by the transaction.

There are currently three versions available:

1. GST1
2. GST2
3. Chi-Gas

**Historical figures:** The 15,000/24,000 refunds and 50% cap above describe pre-London rules. [EIP-3529](<https://eips.ethereum.org/EIPS/eip-3529>) removed the SELFDESTRUCT refund, reduced eligible storage-clearing refunds to 4,800 and capped total refunds at 20% of gas used. These tokens no longer provide the described Ethereum gas savings.

GST1 is using the mechanism of storage variables which is more efficient when the gas prices between minting and burning is less than 3.71x different. In our current times of crazy gas fluctuations you are probably better off going with the other alternative. GST2 relies on the contract self-destruct mechanism, as well as the Chi-Gas.

## What are Chi Gas Tokens?

Chi Gas added three ways to improve the efficiency of GST2:

- Reducing the contract address size by mining a private key with [Profanity address generator](<https://github.com/johguse/profanity>), which allowed to decrease size of the sub contracts by 1 byte.
- Using `CREATE2` instruction to deploy sub smart contracts for their efficient address discovery during burning process.
- Fixing ERC20 incompatibilities of GST2.

The original Profanity tool was later found to generate insecure keys. Its mention here documents Chi’s history; do not use it to generate wallet keys.

![Chi vs Gas Tokens](<https://cdn0.scrvt.com/b095ee27d37b3d7b6b150adba9ac6ec8/a7240d453cdf94fd/00f65bcd9fc8/v/94fab377ead5/chi-vs-gas-tokens.jpeg>)

You can use the the Chi-Gas in your contracts using the modifier on the right. A short explanation of the constant values:

- `21000` = initial cost of a transaction
- `16 * msg.data.length` = calldata cost (see [EIP-2028](<https://eips.ethereum.org/EIPS/eip-2028>))
- `gasStart - gasleft()` = the actual gas used by your code
- `14154` = freeFromUpTo costs
- 41947 = refund per burnt gas token \* 2 (times two due to max refund of half of all gas costs)

```solidity
modifier discountCHI {
  uint256 gasStart = gasleft();

  _;

  uint256 initialGas = 21000 + 16 * msg.data.length;
  uint256 gasSpent = initialGas + gasStart - gasleft();
  uint256 freeUpValue = (gasSpent + 14154) / 41947;

  chi.freeFromUpTo(msg.sender, freeUpValue);
}
```

Now all you need to to do is add the ChiToken interface with the address:

```solidity
interface ChiToken {
    function freeFromUpTo(address from, uint256 value) external;
}

ChiToken constant public chi = ChiToken(0x0000000000004946c0e9F43F4Dee607b0eF1fA1c);
```

and your modifier will be working. When you want to use it, make sure to mint and approve Chi tokens to your contract beforehand. Oh and you can also deploy new contracts using Chi-gas using [deployer.eth](<https://etherscan.io/address/deployer.eth>).

## Example: Adding Chi tokens into UniSwap v2 integration

We will be building on top of my [previous Uniswap v2 integration](<https://soliditydeveloper.com/uniswap2>). As a reminder it is build on top for the Kovan test network using DAI. All we need to no is add the `discountCHI` modifier and add a new function with this modifier.

```solidity
function convertEthToDaiWithGasRefund(uint daiAmount) external payable discountCHI {
    _convertEthToDai(daiAmount);
}
```

Congratulations, our Unicorn is now releasing its gas!

![Unicorn releasing gas](<https://cdn0.scrvt.com/b095ee27d37b3d7b6b150adba9ac6ec8/f64cd7be81ff5542/2975858071e4/v/38dab0aca635/uni-gas.png>)

## Historical Remix example and compatibility limits

This is the original Solidity 0.8.1 illustration. Its retired testnet addresses, obsolete refund mechanism and demonstration-only asset handling make it unsuitable for current deployment. The figures below are historical comparisons.

```solidity
// SPDX-License-Identifier: MIT
pragma solidity 0.8.1;

import "https://github.com/Uniswap/uniswap-v2-periphery/blob/master/contracts/interfaces/IUniswapV2Router02.sol";

interface ChiToken {
    function freeFromUpTo(address from, uint256 value) external;
}

contract UniswapExample {
  ChiToken constant public chi = ChiToken(0x0000000000004946c0e9F43F4Dee607b0eF1fA1c);
  IUniswapV2Router02 constant public uniRouter = IUniswapV2Router02(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D);
  address constant public multiDaiKovan = 0x4F96Fe3b7A6Cf9725f59d353F723c1bDb64CA6Aa;

  modifier discountCHI {
    uint256 gasStart = gasleft();

    _;

    uint256 gasSpent = 21000 + gasStart - gasleft() + 16 * msg.data.length;
    chi.freeFromUpTo(msg.sender, (gasSpent + 14154) / 41947);
  }
  
  function convertEthToDai(uint daiAmount) external payable {
    _convertEthToDai(daiAmount);
  }

  function convertEthToDaiWithGasRefund(uint daiAmount) external payable discountCHI {
    _convertEthToDai(daiAmount);
  }
  
  function getEstimatedETHforDAI(uint daiAmount) external view returns (uint256[] memory) {
    return uniRouter.getAmountsIn(daiAmount, _getPathForETHtoDAI());
  }

  function _getPathForETHtoDAI() private pure returns (address[] memory) {
    address[] memory path = new address[](2);
    path[0] = uniRouter.WETH();
    path[1] = multiDaiKovan;
    
    return path;
  }
  
  function _convertEthToDai(uint daiAmount) private {
    // using 'now' for convenience in Remix, for mainnet pass deadline from frontend!
    uint deadline = block.timestamp + 15;

    uniRouter.swapETHForExactTokens{ value: msg.value }(
      daiAmount,
      _getPathForETHtoDAI(),
      address(this),
      deadline
    );
    
    // refund leftover ETH to user
    (bool success,) = msg.sender.call{ value: address(this).balance }("");
    require(success, "refund failed");
  }
  
  // important to receive ETH
  receive() payable external {}
}
```

## Uniswap Example Walkthrough

The original walkthrough minted and approved Chi on Kovan, then compared two Uniswap calls in Remix. Kovan is retired and London removed the refund mechanism these savings relied on. The screenshot below is preserved as the historical result; do not repeat this as a current gas optimization.

![Regular Uniswap Trade](<https://cdn0.scrvt.com/b095ee27d37b3d7b6b150adba9ac6ec8/3535ce10db203d00/b0804bee4556/v/b1e686e36d84/regular-uni-trade.png>)

![Uniswap Trade with ChiGas](<https://cdn0.scrvt.com/b095ee27d37b3d7b6b150adba9ac6ec8/a043c89cd5015f5c/7d0a96ad0263/v/040ada431195/gas-uni-trade.png>)

Quite a bit saved assuming we minted the Chi-gas during periods of lower gas prices.

## Gas tokens won't exist in the future

Vitalik just recently posted a new [EIP-3298](<https://eips.ethereum.org/EIPS/eip-3298>) which proposes to remove the refund mechanism. I let him explain it:

> Gas refunds for SSTORE and SELFDESTRUCT were originally introduced to motivate application developers to write applications that practice “good state hygiene”, clearing storage slots and contracts that are no longer needed. However, they are not widely used for this, and poor state hygiene continues to be the norm. It is now widely accepted that the only solution to state growth is some form of statelessness or state expiry, and if such a solution is implemented, then disused storage slots and contracts would start to be ignored automatically.
>
>
>
> Vitalik Buterin

The early proposal discussed above was followed by [EIP-3529](<https://eips.ethereum.org/EIPS/eip-3529>) in London in 2021. SELFDESTRUCT refunds were removed and storage refunds reduced. This is an implemented change, not a distant possibility.
