
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 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:
- GST1
- GST2
- Chi-Gas
Historical figures: The 15,000/24,000 refunds and 50% cap above describe pre-London rules. 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, which allowed to decrease size of the sub contracts by 1 byte.
- Using
CREATE2instruction 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.

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 transaction16 * msg.data.length= calldata cost (see EIP-2028)gasStart - gasleft()= the actual gas used by your code14154= freeFromUpTo costs41947 = refund per burnt gas token * 2 (times two due to max refund of half of all gas costs)
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:
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.
Example: Adding Chi tokens into UniSwap v2 integration
We will be building on top of my previous Uniswap v2 integration. 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.
function convertEthToDaiWithGasRefund(uint daiAmount) external payable discountCHI {
_convertEthToDai(daiAmount);
}Congratulations, our Unicorn is now releasing its gas!

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.
// 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.


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 which proposes to remove the refund mechanism. I let him explain it:
The early proposal discussed above was followed by EIP-3529 in London in 2021. SELFDESTRUCT refunds were removed and storage refunds reduced. This is an implemented change, not a distant possibility.




Join the conversation
Comments are hosted by Disqus and load only when you choose to enable them.