How-to Guide
This guide provides practical instructions for working with the Dynamic Fees module, including governance operations and integration patterns.
Understanding the Module
The Dynamic Fees module enables multi-asset fee payments by maintaining NTRN-denominated prices for supported assets. It works in conjunction with the fee market module to convert between different denominations.
Governance Operations
Governance-Only Access: All parameter updates in the Dynamic Fees module require governance approval. Individual users cannot directly modify asset prices.
Updating Asset Prices
Step 1: Prepare the Governance Proposal
Create a governance proposal to update asset prices:
{
"title": "Update Dynamic Fees Asset Prices",
"description": "Update NTRN-denominated prices for supported assets based on current market conditions",
"messages": [
{
"@type": "/neutron.dynamicfees.v1.MsgUpdateParams",
"authority": "neutron10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn", // governance authority
"params": {
"ntrn_prices": [
{
"denom": "uatom",
"amount": "0.150000000000000000"
},
{
"denom": "uosmo",
"amount": "0.080000000000000000"
},
{
"denom": "ujuno",
"amount": "0.025000000000000000"
}
]
}
}
]
}
Step 2: Submit the Proposal
Using the CLI:
neutrond tx gov submit-proposal proposal.json \
--from your-key \
--gas auto \
--gas-adjustment 1.3 \
--fees 5000untrn
Step 3: Vote on the Proposal
Once submitted, the community can vote:
# Vote yes on proposal ID 123
neutrond tx gov vote 123 yes \
--from your-key \
--fees 5000untrn
Adding New Assets
To add support for a new asset:
{
"title": "Add Support for New Asset",
"description": "Add JUNO token support to Dynamic Fees module",
"messages": [
{
"@type": "/neutron.dynamicfees.v1.MsgUpdateParams",
"authority": "neutron10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn",
"params": {
"ntrn_prices": [
{
"denom": "uatom",
"amount": "0.150000000000000000"
},
{
"denom": "uosmo",
"amount": "0.080000000000000000"
},
{
"denom": "ujuno",
"amount": "0.025000000000000000"
}
]
}
}
]
}
Removing Asset Support
To remove an asset, simply exclude it from the ntrn_prices
array:
{
"ntrn_prices": [
{
"denom": "uatom",
"amount": "0.150000000000000000"
}
// ujuno removed - no longer supported
]
}
Query Current Parameters
# Query current asset prices
neutrond query dynamicfees params
Expected Output:
params:
ntrn_prices:
- amount: "0.150000000000000000"
denom: uatom
- amount: "0.080000000000000000"
denom: uosmo
Using gRPC
grpcurl -plaintext localhost:9090 neutron.dynamicfees.Query/Params
Using REST API
curl http://localhost:1317/neutron/dynamicfees/params
Integration Patterns
Fee Market Integration
The Dynamic Fees module automatically integrates with the fee market module. Users can pay fees in any supported asset:
# Pay fees in ATOM instead of NTRN
neutrond tx bank send sender recipient 1000untrn \
--gas-prices 0.01uatom \
--from your-key
Smart Contract Integration
CosmWasm contracts can query supported denominations:
use cosmwasm_std::{Deps, StdResult, QueryRequest, Custom};
// Query supported denominations
pub fn query_supported_denoms(deps: Deps) -> StdResult<Vec<String>> {
let query = QueryRequest::Custom(NeutronQuery::DynamicFeesParams {});
let response: DynamicFeesParamsResponse = deps.querier.query(&query)?;
let denoms: Vec<String> = response.params.ntrn_prices
.iter()
.map(|coin| coin.denom.clone())
.collect();
Ok(denoms)
}
Application Development
When building applications that interact with fees:
// Check if asset is supported for fee payment
async function isFeeAssetSupported(denom: string): Promise<boolean> {
const client = await getQueryClient();
const params = await client.dynamicfees.params();
return params.params.ntrnPrices.some(price => price.denom === denom);
}
// Get current price for an asset
async function getAssetPrice(denom: string): Promise<string | null> {
const client = await getQueryClient();
const params = await client.dynamicfees.params();
const priceEntry = params.params.ntrnPrices.find(price => price.denom === denom);
return priceEntry ? priceEntry.amount : null;
}
Price Calculation Examples
Converting Asset to NTRN
To calculate how much NTRN an asset amount represents:
Formula: asset_amount * ntrn_price = ntrn_equivalent
Example:
- Asset: 100 ATOM
- NTRN Price: 0.15 (1 ATOM = 0.15 NTRN)
- Calculation: 100 * 0.15 = 15 NTRN
Converting NTRN to Asset
To calculate how much of an asset equals a NTRN amount:
Formula: ntrn_amount / ntrn_price = asset_equivalent
Example:
- NTRN Amount: 15 NTRN
- NTRN Price: 0.15 (1 ATOM = 0.15 NTRN)
- Calculation: 15 / 0.15 = 100 ATOM
Best Practices
Price Setting Guidelines
- Market Research: Base prices on current market conditions
- Conservative Updates: Avoid dramatic price changes
- Regular Reviews: Update prices periodically to maintain accuracy
- Community Input: Seek community feedback before major changes
Governance Proposals
- Clear Rationale: Explain why price updates are needed
- Market Data: Include supporting market data
- Impact Analysis: Describe effects on users and applications
- Gradual Changes: Implement changes gradually when possible
Integration Considerations
- Error Handling: Handle unsupported denominations gracefully
- Price Volatility: Account for price changes in applications
- Fallback Mechanisms: Implement NTRN fallback for unsupported assets
- Testing: Test with various asset combinations
Troubleshooting
Common Issues
Asset Not Supported for Fees
Problem: Transaction fails with unsupported denomination error
Solution:
- Check if asset is in the supported list
- Use NTRN for fees instead
- Submit governance proposal to add asset support
Price Conversion Errors
Problem: Unexpected fee calculations
Solution:
- Verify current asset prices with
neutrond query dynamicfees params
- Check for recent governance updates
- Ensure using correct denomination format
Governance Proposal Failures
Problem: Parameter update proposal fails
Solution:
- Verify authority address matches governance authority
- Ensure all required parameters are included
- Check proposal format and syntax
Debugging Commands
# Check current parameters
neutrond query dynamicfees params
# Verify governance authority
neutrond query auth account neutron10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn
# Check proposal status
neutrond query gov proposal [proposal-id]
# View proposal details
neutrond query gov proposal [proposal-id] --output json
Advanced Usage
Automated Price Updates
For applications that need to track price changes:
// Monitor for parameter change events
async function monitorPriceChanges() {
const client = await getWebSocketClient();
client.subscribe({
query: "tm.event='Tx' AND message.action='/neutron.dynamicfees.v1.MsgUpdateParams'"
}, (event) => {
console.log('Dynamic Fees parameters updated:', event);
// Handle price change
updateLocalPriceCache();
});
}
Multi-Asset Fee Estimation
// Estimate fees in different assets
async function estimateFeesInAssets(gasUsed: number): Promise<Map<string, string>> {
const params = await client.dynamicfees.params();
const feeEstimates = new Map<string, string>();
// Base fee in NTRN
const baseFeeNtrn = gasUsed * 0.025; // Example gas price
// Convert to other assets
for (const price of params.params.ntrnPrices) {
const assetFee = baseFeeNtrn / parseFloat(price.amount);
feeEstimates.set(price.denom, assetFee.toString());
}
return feeEstimates;
}
Governance Automation
#!/bin/bash
# Script to submit price update proposals
PROPOSAL_FILE="price_update.json"
KEY_NAME="governance-key"
# Create proposal
cat > $PROPOSAL_FILE << EOF
{
"title": "Monthly Dynamic Fees Price Update",
"description": "Update asset prices based on 30-day average market data",
"messages": [
{
"@type": "/neutron.dynamicfees.v1.MsgUpdateParams",
"authority": "neutron10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn",
"params": {
"ntrn_prices": [
{
"denom": "uatom",
"amount": "$(curl -s 'https://api.example.com/ntrn-atom-price')"
}
]
}
}
]
}
EOF
# Submit proposal
neutrond tx gov submit-proposal $PROPOSAL_FILE \
--from $KEY_NAME \
--gas auto \
--gas-adjustment 1.3 \
--fees 5000untrn
This guide covers the essential operations for working with the Dynamic Fees module, from basic queries to advanced integration patterns and governance operations.