Gas optimization
Learn how to optimize gas costs when using the Moromoro SDK.
Understanding Gas Costs
Gas costs for swaps consist of:
Base transaction cost (~21,000 gas)
Router contract execution (~50,000–150,000 gas)
DEX interaction costs (varies by DEX type)
Token transfers (~50,000 gas per transfer)
Split trade overhead (if using multiple paths)
Gas-Aware Quote Selection
The SDK automatically considers gas costs when calculating the best rate.
const { MoroBestRate } = require('@moromoro/moro-sdk')
const { ethers } = require('ethers')
async function gasAwareSwap() {
const provider = new ethers.providers.JsonRpcProvider(
'https://rpc.hyperliquid.xyz/evm'
)
const moroClient = new MoroBestRate(provider, 'hyperevm')
const HYPE = '0x5555555555555555555555555555555555555555'
const USDT = '0xb8ce59fc3717ada4c02eadf9682a9e934f625ebb'
const amountIn = ethers.utils.parseUnits('10', 18)
// Provide accurate gas price for better rate calculation
const gasPrice = await provider.getGasPrice()
console.log('Current gas price:', ethers.utils.formatUnits(gasPrice, 'gwei'), 'gwei')
// SDK considers gas costs in the amountOut calculation
const quote = await moroClient.getQuote(
HYPE,
USDT,
amountIn,
gasPrice,
{ enableSplit: true }
)
console.log('Gas fees:', quote.gasFees)
console.log('Net amount out (after gas):', quote.amountOut)
}
gasAwareSwap()Optimizing for L2 Chains
L2 chains like Optimism and Arbitrum have different gas models.
async function optimizeL2Gas() {
const provider = new ethers.providers.JsonRpcProvider(
'https://mainnet.optimism.io'
)
const moroClient = new MoroBestRate(provider, 'optimism')
const ETH = '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee'
const OP = '0x4200000000000000000000000000000000000042'
const amountIn = ethers.utils.parseUnits('1', 18)
// L2 chains need both L1 and L2 gas prices
const l1GasPrice = ethers.utils.parseUnits('20', 'gwei')
const l2GasPrice = await provider.getGasPrice()
console.log('L2 gas price:', ethers.utils.formatUnits(l2GasPrice, 'gwei'), 'gwei')
const quote = await moroClient.getQuote(
ETH,
OP,
amountIn,
l1GasPrice,
{
enableSplit: true,
gasPriceL2: l2GasPrice
}
)
console.log('L2 is cheaper due to lower gas costs!')
}
optimizeL2Gas()Batch Approvals
Approve once for unlimited use to save gas on future swaps.
async function unlimitedApproval() {
const provider = new ethers.providers.JsonRpcProvider(
'https://rpc.hyperliquid.xyz/evm'
)
const signer = new ethers.Wallet(process.env.PRIVATE_KEY, provider)
const moroClient = new MoroBestRate(provider, 'hyperevm')
const USDT = '0xb8ce59fc3717ada4c02eadf9682a9e934f625ebb'
// Approve unlimited (MaxUint256) - only need to do this once
console.log('Approving unlimited USDT...')
const approveTx = await moroClient.approve(
signer,
USDT,
ethers.constants.MaxUint256 // Unlimited approval
)
if (approveTx) {
await approveTx.wait()
console.log('✓ Unlimited approval granted')
console.log('Future swaps will not require approval')
}
}
unlimitedApproval()Minimizing Split Paths
Control the number of paths to balance rate improvement vs gas cost.
async function optimizeSplitPaths() {
const provider = new ethers.providers.JsonRpcProvider(
'https://rpc.hyperliquid.xyz/evm'
)
// Limit candidate paths to reduce gas costs
const moroClient = new MoroBestRate(provider, 'hyperevm', {
maxCandidatePathsCount: 10 // Lower = less gas, but potentially worse rate
})
const HYPE = '0x5555555555555555555555555555555555555555'
const USDT = '0xb8ce59fc3717ada4c02eadf9682a9e934f625ebb'
const amountIn = ethers.utils.parseUnits('100', 18)
const gasPrice = ethers.BigNumber.from('5000000000')
const quote = await moroClient.getQuote(
HYPE,
USDT,
amountIn,
gasPrice,
{ enableSplit: true }
)
if (quote.type === 'split') {
console.log('Number of paths:', quote.paths.length)
console.log('This will use less gas than many paths')
}
}
optimizeSplitPaths()Dynamic Gas Pricing
Adjust gas price based on network conditions.
async function dynamicGasPricing() {
const provider = new ethers.providers.JsonRpcProvider(
'https://rpc.hyperliquid.xyz/evm'
)
const moroClient = new MoroBestRate(provider, 'hyperevm')
// Get current gas price
const currentGasPrice = await provider.getGasPrice()
// Add 10% buffer for faster confirmation
const gasPrice = currentGasPrice.mul(110).div(100)
console.log('Base gas price:', ethers.utils.formatUnits(currentGasPrice, 'gwei'), 'gwei')
console.log('Using gas price:', ethers.utils.formatUnits(gasPrice, 'gwei'), 'gwei')
const HYPE = '0x5555555555555555555555555555555555555555'
const USDT = '0xb8ce59fc3717ada4c02eadf9682a9e934f625ebb'
const amountIn = ethers.utils.parseUnits('10', 18)
const quote = await moroClient.getQuote(HYPE, USDT, amountIn, gasPrice)
// Quote calculation includes the higher gas price
console.log('Amount out (accounting for gas):', quote.amountOut)
}
dynamicGasPricing()Estimating Gas Costs
Estimate total gas cost before executing.
async function estimateGasCost() {
const provider = new ethers.providers.JsonRpcProvider(
'https://rpc.hyperliquid.xyz/evm'
)
const signer = new ethers.Wallet(process.env.PRIVATE_KEY, provider)
const moroClient = new MoroBestRate(provider, 'hyperevm')
const HYPE = '0x5555555555555555555555555555555555555555'
const USDT = '0xb8ce59fc3717ada4c02eadf9682a9e934f625ebb'
const amountIn = ethers.utils.parseUnits('10', 18)
const gasPrice = await provider.getGasPrice()
const quote = await moroClient.getQuote(HYPE, USDT, amountIn, gasPrice)
// Estimate gas
const minOut = ethers.BigNumber.from(quote.amountOut).mul(99).div(100)
try {
const estimatedGas = await moroClient.swap(
signer,
HYPE,
USDT,
amountIn,
minOut,
quote
).then(tx => tx.estimateGas())
const totalGasCost = estimatedGas.mul(gasPrice)
console.log('Estimated gas:', estimatedGas.toString())
console.log('Total gas cost:', ethers.utils.formatEther(totalGasCost), 'HYPE')
} catch (error) {
console.log('Could not estimate:', error.message)
}
}
estimateGasCost()Comparing Gas Costs
Compare gas costs between single and split trades.
async function compareGasCosts() {
const provider = new ethers.providers.JsonRpcProvider(
'https://rpc.hyperliquid.xyz/evm'
)
const moroClient = new MoroBestRate(provider, 'hyperevm')
const HYPE = '0x5555555555555555555555555555555555555555'
const USDT = '0xb8ce59fc3717ada4c02eadf9682a9e934f625ebb'
const amountIn = ethers.utils.parseUnits('100', 18)
const gasPrice = ethers.BigNumber.from('5000000000')
// Single path
const singleQuote = await moroClient.getQuote(
HYPE,
USDT,
amountIn,
gasPrice,
{ enableSplit: false }
)
// Split path
const splitQuote = await moroClient.getQuote(
HYPE,
USDT,
amountIn,
gasPrice,
{ enableSplit: true }
)
console.log('Single Path:')
console.log('- Amount out:', ethers.utils.formatUnits(singleQuote.amountOut, 6))
console.log('- Gas fees:', singleQuote.gasFees)
console.log('\nSplit Path:')
console.log('- Amount out:', ethers.utils.formatUnits(splitQuote.amountOut, 6))
console.log('- Gas fees:', splitQuote.gasFees)
// Determine if split is worth it
const singleNet = parseFloat(ethers.utils.formatUnits(singleQuote.amountOut, 6))
const splitNet = parseFloat(ethers.utils.formatUnits(splitQuote.amountOut, 6))
console.log('\nNet benefit of split:', (splitNet - singleNet).toFixed(6), 'USDT')
}
compareGasCosts()Zero Gas Options Helper
Use the built-in helper for testing without gas considerations.
const { MoroBestRate, zeroGasOptions } = require('@moromoro/moro-sdk')
const { ethers } = require('ethers')
async function testWithoutGas() {
const provider = new ethers.providers.JsonRpcProvider(
'https://rpc.hyperliquid.xyz/evm'
)
const moroClient = new MoroBestRate(provider, 'hyperevm')
const HYPE = '0x5555555555555555555555555555555555555555'
const USDT = '0xb8ce59fc3717ada4c02eadf9682a9e934f625ebb'
const amountIn = ethers.utils.parseUnits('10', 18)
// Use zero gas for pure rate comparison
const gasPrice = zeroGasOptions()
const quote = await moroClient.getQuote(HYPE, USDT, amountIn, gasPrice)
console.log('Pure output (no gas deduction):', quote.amountOut)
console.log('This is useful for comparing DEX rates without gas overhead')
}
testWithoutGas()Gas Optimization Checklist
✅ Use unlimited approvals for frequently traded tokens
✅ Provide accurate gas prices to SDK for better routing
✅ Consider L2 chains for high-frequency trading
✅ Limit split paths for small trades
✅ Batch multiple swaps when possible
✅ Monitor gas prices and swap during low-cost periods
✅ Use native tokens when possible (no approval needed)
Advanced: Custom Gas Limit
Set custom gas limits for specific scenarios.
async function customGasLimit() {
const provider = new ethers.providers.JsonRpcProvider(
'https://rpc.hyperliquid.xyz/evm'
)
const signer = new ethers.Wallet(process.env.PRIVATE_KEY, provider)
const moroClient = new MoroBestRate(provider, 'hyperevm')
const HYPE = '0x5555555555555555555555555555555555555555'
const USDT = '0xb8ce59fc3717ada4c02eadf9682a9e934f625ebb'
const amountIn = ethers.utils.parseUnits('10', 18)
const gasPrice = ethers.BigNumber.from('5000000000')
const quote = await moroClient.getQuote(HYPE, USDT, amountIn, gasPrice)
const minOut = ethers.BigNumber.from(quote.amountOut).mul(99).div(100)
// Set custom gas limit
const tx = await moroClient.swap(
signer,
HYPE,
USDT,
amountIn,
minOut,
quote,
0,
0,
ethers.constants.AddressZero,
{
gasLimit: 300000, // Custom limit
gasPrice: gasPrice // Custom price
}
)
const receipt = await tx.wait()
console.log('Actual gas used:', receipt.gasUsed.toString())
console.log('Gas limit:', '300000')
console.log('Efficiency:', (receipt.gasUsed.toNumber() / 300000 * 100).toFixed(2) + '%')
}
customGasLimit()