Monad fija el precio de una transacción en dos ejes independientes: un precio del gas de ejecución y un precio de datos (calldata) separado. Los métodos JSON-RPC de Ethereum eth_gasPrice y eth_estimateGas solo hablan de un eje cada uno, por lo que un cliente que multiplica gasUsed por un único precio sugerido malvalorará las llamadas con muchos datos. La estimación correcta lee el precio de ejecución sugerido, lee el precio de datos actual, estima el gas de ejecución, dimensiona el calldata y los combina con un buffer explícito. Este artículo explica el mecanismo, muestra estimadores ejecutables en Node.js y ofrece una tabla de resultados para que puedas medir contra tu propio endpoint en lugar de confiar en una constante codificada.
El modelo de precios de dos ejes de Monad en términos operativos
La documentación de Monad sobre precios del gas indica que la red cobra en dos ejes independientes: un precio del gas de ejecución y un precio de datos (calldata) separado. El gas de ejecución cubre el cómputo que consume una transacción; el precio de datos cubre los bytes que transporta la transacción. Por tanto, el coste efectivo de una transacción es función tanto del gas utilizado como del tamaño de su calldata, no un único producto gasUsed × gasPrice.
Este es el único hecho que rompe a un lector que llega con un modelo mental de Ethereum. En Ethereum L1 la comisión es esencialmente unidimensional: gasUsed × (baseFee + priorityFee). En Monad, un lector ingenuo que multiplica gasUsed por un único precio sugerido subestimará o sobreestimará según cuántos datos lleve la llamada. Una simple transferencia de valor y una llamada a contrato con calldata grande pueden consumir un gas de ejecución similar pero conllevar costes de datos muy distintos.
Operativamente, el modelo te dice qué parte de tu transacción penaliza cada eje. Si tu llamada está limitada por cómputo (bucles, escrituras en almacenamiento), domina el eje de ejecución. Si tu llamada está limitada por datos (argumentos grandes codificados en ABI, payloads por lotes, despliegues de contratos con mucho calldata), domina el eje de datos. Leer ambos ejes es lo que te permite razonar sobre cuál optimizar.
- Eje de ejecución: se cobra por unidad de gas de ejecución consumido.
- Eje de datos: se cobra por byte de calldata que transporta la transacción.
- Coste efectivo: una combinación de ambos, no un único producto gasUsed × gasPrice.
- Consecuencia práctica: las llamadas con muchos datos necesitan una estimación distinta a las de mucho cómputo.
Qué devuelve eth_gasPrice en Monad y qué omite
La especificación JSON-RPC de Ethereum define eth_gasPrice como el retorno de un precio de gas sugerido en wei. En Monad, trátalo como el precio del gas de ejecución sugerido, no como un coste total. Es una entrada de un cálculo de dos ejes, y los campos exactos de la respuesta están documentados / varían según la versión del nodo, así que verifícalos contra el payload actual en lugar de codificar suposiciones.
La omisión importa. Un cliente que usa eth_gasPrice como única entrada de comisión malvalorará cualquier transacción cuyo coste esté dominado por el calldata. El método no codifica el precio de datos y no sabe cuántos bytes transportará tu transacción. Responde a una pregunta más estrecha: qué precio de ejecución se sugiere actualmente.
Si te conectas a través de un endpoint gestionado, se aplica la misma semántica del método independientemente del proveedor; lo que varía es el valor sugerido que devuelve el nodo y cualquier caché del lado del proveedor. Para la selección de endpoints y el comportamiento específico del proveedor, consulta la guía de proveedores RPC de Monad y la página de la red Monad.
- Devuelve: un precio del gas de ejecución sugerido en wei.
- No devuelve: el precio de datos ni un coste total de transacción.
- Riesgo: usarlo como única entrada de comisión malvalora las llamadas con muchos datos.
- Verifica: los campos de respuesta están documentados / varían según la versión del nodo.
Por qué eth_estimateGas responde a la capacidad, no al coste
La especificación describe eth_estimateGas como el retorno de una estimación del gas que necesita una transacción para ejecutarse. Eso es un límite de gas, expresado en unidades de gas, y habla solo del eje de ejecución. No devuelve un precio y no tiene en cuenta el eje de datos.
Confundir el límite con el precio es un error común. Un desarrollador lee el número de eth_estimateGas, lo multiplica por el número de eth_gasPrice y cree que tiene un coste. Tiene una estimación del eje de ejecución. El eje de datos sigue sin precio, y en una transacción con mucho calldata esa brecha puede ser la mayor parte de la factura.
La lectura correcta es: eth_estimateGas te dice si la transacción cabrá dentro de un límite de gas y aproximadamente cuánta ejecución consume. Es una herramienta de dimensionamiento, no de fijación de precios. Combínala con una lectura de precio para cada eje antes de presentar un coste al usuario.
- eth_estimateGas devuelve un límite de gas (eje de ejecución), no un precio.
- Multiplicarlo por eth_gasPrice produce una estimación solo de ejecución.
- Las transacciones con muchos datos quedan sin precio con este par por sí solo.
- Úsalo para dimensionar y luego fija el precio de ambos ejes por separado.
Dónde encaja eth_feeHistory y por qué la baja actividad lo vuelve ruidoso
El método eth_feeHistory devuelve datos históricos de base fee y priority fee, a menudo con bandas percentiles. En Ethereum L1, donde la variabilidad de comisiones es alta, esas bandas percentiles son informativas. En una cadena con menos variabilidad de comisiones, las bandas pueden ser planas, y una banda plana aporta poca señal sobre qué pagar después.
Trata feeHistory como orientativo en Monad. Es útil para comprobar si el precio sugerido actual está en un rango normal, pero no debería ser el único motor de tu comisión. Prefiere el precio de ejecución sugerido actual del nodo más un buffer explícito, y lee el precio de datos por separado. Para un tratamiento más profundo de la semántica del método, consulta Historial de comisiones de Ethereum y estimación de priority fee y el estimador de percentil de priority fee con eth_feeHistory.
Un patrón práctico es usar feeHistory como barandilla: si el precio elegido queda muy fuera del rango reciente, regístralo y deja que quien llama decida. No recortes silenciosamente a un percentil histórico en una cadena de baja actividad, porque el percentil puede reflejar un periodo con casi ninguna presión de comisiones.
- feeHistory es orientativo en Monad, no autoritativo.
- Las bandas percentiles planas en cadenas de baja actividad aportan poca señal.
- Prefiere el precio sugerido actual más un buffer explícito.
- Usa feeHistory como barandilla de rango, no como recorte rígido.
Una receta práctica de estimador de dos ejes
La receta tiene cinco lecturas y una combinación. Primero, lee el precio de ejecución sugerido. Segundo, lee el precio de datos actual. Tercero, estima el gas de ejecución con eth_estimateGas. Cuarto, dimensiona el calldata en bytes. Quinto, combina los dos ejes en una única cifra de coste esperado y aplica un buffer configurable para que quien llama pueda intercambiar coste por confianza de inclusión.
La combinación es la parte que los lectores hacen mal. El coste esperado no es gasUsed × gasPrice. Es (executionGas × executionPrice) + (calldataBytes × dataPrice), con un buffer aplicado al total o a cada eje según tu preferencia de riesgo. Mantén los dos componentes separados en tu salida para que puedas ver qué eje domina en una transacción dada.
Como el precio de datos no es una constante que un cliente deba codificar, léelo en el momento de la estimación. Si tu nodo no expone un método dedicado de precio de datos, consulta la documentación actual de Monad y la lista de métodos de tu proveedor; el nombre exacto del método y la forma de la respuesta están documentados / varían según la versión del nodo. Las páginas de servicio de API y precios de RPC describen cómo se estructura el acceso gestionado si estás eligiendo un endpoint.
- Lee el precio de ejecución sugerido.
- Lee el precio de datos actual.
- Estima el gas de ejecución (eth_estimateGas).
- Dimensiona el calldata en bytes.
- Combina: (gas × execPrice) + (bytes × dataPrice) y luego aplica el buffer.
Estimador Node.js ejecutable contra un endpoint RPC de Monad
El script siguiente consulta a un endpoint RPC de Monad el precio de ejecución sugerido, estima el gas para una transacción de ejemplo, dimensiona el calldata e imprime ambos ejes más una cifra combinada. Usa solo llamadas JSON-RPC estándar y el fetch integrado de Node, por lo que se ejecuta sin dependencias adicionales en un runtime de Node moderno.
Sustituye la URL del endpoint y la transacción de ejemplo por las tuyas. La lectura del precio de datos se muestra como una llamada de marcador de posición porque el nombre exacto del método está documentado / varía según la versión del nodo; consulta la documentación actual de Monad y la lista de métodos de tu proveedor, y luego conecta el método correcto. El script imprime deliberadamente los dos ejes por separado para que puedas ver cuál domina.
// monad-estimator.js — run with: node monad-estimator.js
const RPC_URL = process.env.MONAD_RPC_URL || 'https://your-monad-endpoint';
const BUFFER = 1.15; // 15% buffer, settable
async function rpc(method, params = []) {
const res = await fetch(RPC_URL, {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({ jsonrpc: '2.0', id: 1, method, params })
});
const json = await res.json();
if (json.error) throw new Error(method + ': ' + JSON.stringify(json.error));
return json.result;
}
async function main() {
// 1. Suggested execution gas price (wei)
const execPriceHex = await rpc('eth_gasPrice');
const execPrice = BigInt(execPriceHex);
// 2. Current data price (wei per byte). Method name varies by node version.
// Check current Monad docs / provider method list and wire it here.
let dataPrice = 0n;
try {
const dataPriceHex = await rpc('eth_dataPrice'); // placeholder name
dataPrice = BigInt(dataPriceHex);
} catch (e) {
console.warn('data price method unavailable on this endpoint:', e.message);
}
// 3. Sample transaction
const tx = {
from: '0x0000000000000000000000000000000000000001',
to: '0x0000000000000000000000000000000000000002',
value: '0x0',
data: '0x' + 'ab'.repeat(200) // 200 bytes of calldata
};
// 4. Estimate execution gas
const gasHex = await rpc('eth_estimateGas', [tx]);
const gas = BigInt(gasHex);
// 5. Size calldata
const calldataBytes = BigInt((tx.data.length - 2) / 2);
// 6. Combine both axes
const execCost = gas * execPrice;
const dataCost = calldataBytes * dataPrice;
const total = execCost + dataCost;
const buffered = (total * BigInt(Math.round(BUFFER * 100))) / 100n;
console.log('execution gas :', gas.toString());
console.log('exec price (wei) :', execPrice.toString());
console.log('calldata bytes :', calldataBytes.toString());
console.log('data price (wei/B) :', dataPrice.toString());
console.log('exec cost (wei) :', execCost.toString());
console.log('data cost (wei) :', dataCost.toString());
console.log('total (wei) :', total.toString());
console.log('with buffer (wei) :', buffered.toString());
}
main().catch(e => { console.error(e); process.exit(1); });Leer los dos ejes por separado en tu propia salida
Un único número combinado oculta el mecanismo. Imprime el coste de ejecución y el coste de datos como campos separados para que, cuando un usuario pregunte por qué una transacción es cara, puedas señalar el eje responsable. Esto también hace que tu estimador sea depurable: si la cifra combinada parece incorrecta, puedes ver si la lectura de ejecución o la de datos es la atípica.
La misma separación ayuda con la optimización. Si domina el eje de datos, considera si tu calldata puede comprimirse, agruparse de otra forma o moverse fuera de la cadena. Si domina el eje de ejecución, examina la lógica del contrato. Sin la separación, estás adivinando.
Mantén el buffer explícito y configurable. Un buffer es una decisión de política, no una constante del protocolo; expónlo para que quienes llaman puedan intercambiar coste por confianza de inclusión. Documenta el valor por defecto que envías y por qué.
- Imprime el coste de ejecución y el coste de datos como campos separados.
- Usa la separación para diagnosticar qué eje es el atípico.
- Expón el buffer como política configurable, no como constante oculta.
- Registra las lecturas en bruto para que las estimaciones sean reproducibles.
// split-axes.js — print each pricing axis as its own field, then a combined total.
// Run with: node split-axes.js
const RPC_URL = process.env.MONAD_RPC_URL || 'https://your-monad-endpoint';
async function rpc(method, params = []) {
const res = await fetch(RPC_URL, {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({ jsonrpc: '2.0', id: 1, method, params })
});
const json = await res.json();
if (json.error) throw new Error(method + ': ' + JSON.stringify(json.error));
return json.result;
}
// Convert a wei value to a human-readable string without losing precision.
function wei(v) {
const s = v.toString().padStart(19, '0');
return s.slice(0, -18) + '.' + s.slice(-18);
}
async function report(tx) {
const execPrice = BigInt(await rpc('eth_gasPrice'));
const gas = BigInt(await rpc('eth_estimateGas', [tx]));
const calldataBytes = BigInt((tx.data.length - 2) / 2);
// The data axis is read separately; if the endpoint does not expose it,
// report the gap explicitly instead of assuming a zero price.
let dataPrice = null;
try { dataPrice = BigInt(await rpc('eth_dataPrice')); }
catch { console.warn('data-price method unavailable on this endpoint'); }
const execCost = gas * execPrice;
const dataCost = dataPrice === null ? null : calldataBytes * dataPrice;
console.log(JSON.stringify({
execution: { gas: gas.toString(), priceWei: execPrice.toString(), costWei: execCost.toString(), costMON: wei(execCost) },
data: { bytes: calldataBytes.toString(), priceWei: dataPrice === null ? null : dataPrice.toString(),
costWei: dataCost === null ? null : dataCost.toString() },
combinedWei: dataCost === null ? null : (execCost + dataCost).toString(),
note: dataCost === null ? 'data axis unavailable; execution-only estimate' : 'both axes priced'
}, null, 2));
}
report({
from: '0x0000000000000000000000000000000000000001',
to: '0x0000000000000000000000000000000000000002',
value: '0x0',
data: '0x' + 'ab'.repeat(200)
}).catch(e => { console.error(e.message); process.exit(1); });Tabla de resultados: medir contra tu propio endpoint
No confíes en una constante codificada ni en un número del endpoint de otra persona. Rellena la tabla siguiente contra tu propio endpoint RPC de Monad, usando el script estimador anterior o tu propio cliente. Ejecútalo a varias horas del día y para varias formas de transacción para que puedas ver cómo se mueven los dos ejes.
Registra el endpoint, la marca temporal, el precio de ejecución sugerido, el precio de datos, el gas estimado, el tamaño del calldata y la cifra combinada. Si tu endpoint no expone un método de precio de datos, registra eso como una brecha y consulta la documentación actual de Monad y la lista de métodos de tu proveedor antes de concluir que el eje es cero.
La tabla es un método de medición, no un benchmark. Produce valores específicos de tu endpoint y tus transacciones; trátalos como observaciones a verificar, no como cifras universales.
- Columnas: endpoint, marca temporal, precio de ejecución, precio de datos, gas, bytes de calldata, coste combinado, buffer aplicado.
- Filas: una por forma de transacción (transferencia de valor, llamada pequeña, llamada con calldata grande, despliegue).
- Repite: ejecuta a varias horas para ver el movimiento de los ejes.
- Anota brechas: registra cualquier método que tu endpoint no exponga.
Solución de problemas: cuando un modelo mental de un solo eje aparece como error
La consulta que la gente también busca 'por qué MetaMask dice gas insuficiente' es exactamente el síntoma de fijar el precio en un solo eje. Una cartera que estima el gas de ejecución y lo multiplica por un único precio sugerido puede malvalorar una transacción con muchos datos, y el déficit aparece como un error de fondos insuficientes o gas insuficiente en lugar de como un mensaje claro de precios.
La ruta de diagnóstico es separar los dos ejes. Lee el precio de ejecución sugerido, lee el precio de datos, estima el gas y dimensiona el calldata. Si la cifra combinada supera el saldo o el límite de comisión que aplicó la cartera, has encontrado la brecha. Si el endpoint no expone un método de precio de datos, esa ausencia es en sí misma un hallazgo: tu estimador está funcionando con un solo eje.
Otros síntomas comunes encajan con claridad. Una transacción que cabe bajo el límite de gas pero aun así falla por coste apunta al eje de datos. Una transacción que falla por el límite de gas apunta al eje de ejecución. Una transacción que tiene éxito pero cuesta más de lo esperado suele significar que el eje de datos no se incluyó en la estimación. Para síntomas de temporización de ejecución, consulta Ciclo de vida de transacciones en Monad y estado de recibo; para la semántica de saldo, consulta Saldo de reserva en Monad y eth_getBalance.
- Los errores de gas insuficiente a menudo significan que se omitió el eje de datos.
- Falla por el límite de gas → eje de ejecución.
- Falla por coste pero cabe en el límite → eje de datos.
- Tiene éxito pero cuesta más de lo esperado → eje de datos no estimado.
- Falta el método de precio de datos → el estimador funciona con un solo eje.
Limitaciones, compensaciones y lo que el estimador no puede prometer
Los parámetros de precios de Monad están definidos por el protocolo y pueden cambiar. El precio de datos no es una constante que un cliente deba codificar, y los nombres exactos de los métodos y los campos de respuesta están documentados / varían según la versión del nodo. Cualquier estimador que envíes debe leer los valores actuales en el momento de la estimación y degradarse con elegancia cuando un método no esté disponible.
Un estimador es una estimación, no una garantía. El gas de ejecución puede variar con el estado, y el precio sugerido puede moverse entre la estimación y la inclusión de la transacción. Un buffer reduce la probabilidad de déficit pero no la elimina. Trata la cifra combinada como un número de planificación, no como un contrato.
También hay una compensación entre precisión y complejidad. Una estimación de un solo eje es más simple y puede ser adecuada para llamadas limitadas por cómputo con calldata pequeño. Una estimación de dos ejes es más precisa para llamadas con muchos datos pero requiere leer un valor adicional y manejar su ausencia. Elige según las formas de transacción que tu aplicación envía realmente, y documenta la elección.
- Los parámetros de precios están definidos por el protocolo y pueden cambiar.
- El precio de datos no es una constante codificable.
- Los nombres de métodos y campos están documentados / varían según la versión del nodo.
- Las estimaciones son números de planificación, no garantías.
- La precisión de dos ejes cuesta una lectura extra y una ruta de respaldo.
Próximos pasos: integrar los precios duales en tu stack
Empieza ejecutando el estimador contra tu endpoint y rellenando la tabla de resultados para las formas de transacción que realmente envías. Eso te dirá si el eje de datos es relevante para tu carga de trabajo. Si lo es, integra la combinación de dos ejes en tu visualización de comisiones y en tus comprobaciones previas para que los usuarios vean un coste que refleje ambos ejes.
Luego decide cómo manejarás la lectura del precio de datos cuando no esté disponible. Un valor por defecto seguro es registrar la brecha y recurrir a un buffer conservador en el eje de ejecución, señalando que la estimación es de un solo eje. No asumas silenciosamente que el precio de datos es cero.
Para la selección de endpoints y el comportamiento específico del proveedor, revisa la guía de proveedores RPC de Monad, la página de la red Monad y la descripción general del servicio de API. Para más contexto sobre estimación de comisiones, el hub de aprendizaje de OnFinality recopila los artículos relacionados de Ethereum y Monad, y precios de RPC describe cómo se estructura el acceso gestionado.
- Ejecuta el estimador y rellena la tabla de resultados para tus formas de transacción.
- Integra la combinación de dos ejes en la visualización de comisiones y las comprobaciones previas.
- Define un respaldo para una lectura de precio de datos ausente; nunca asumas cero.
- Revisa las páginas de proveedor y red antes de elegir un endpoint.