remix + viem + userop 谈 gasfees
不同交易类型,计算方式不同
- EIP-1559 交易
- Legacy 交易
- userOp 交易
remix 源码中 gasEstimationForceSend

tx.type
这段代码涉及到以太坊交易的 gas 估算和发送过程。以下是对这段代码的详细解释:
代码解释
gasEstimationForceSend(null, () => {
/*
* gasLimit 是一个可以在 UI 中设置的值,用于限制交易中可以使用的最大 gas 数量。
* 例如,如果 gas 估算值高于 gasLimit,则会提示用户提高 gas 限制。
*/
if (gasLimit !== '0x0' && gasEstimation > gasLimit) {
return callback(`estimated gas for this transaction (${gasEstimation}) is higher than gasLimit set in the configuration (${gasLimit}). Please raise the gas limit.`)
}
if (gasLimit === '0x0') {
tx['gas'] = gasEstimation; // 如果 gasLimit 为 '0x0',则使用估算的 gas 值
} else {
tx['gas'] = gasLimit; // 否则,使用设置的 gasLimit
}
// 检查是否配置了不显示交易确认的选项
if (this._api.config.getUnpersistedProperty('doNotShowTransactionConfirmationAgain')) {
return this._executeTx(tx, network, null, this._api, promptCb, callback); // 直接执行交易
}
// 否则,显示交易确认界面
confirmCb(network, tx, tx['gas'], (txFee) => {
return this._executeTx(tx, network, txFee, this._api, promptCb, callback); // 用户确认后执行交易
}, (error) => {
callback(error); // 处理确认过程中产生的错误
});
}, callback);
详细步骤
-
Gas 估算:
- 调用
gasEstimationForceSend函数来估算交易所需的 gas。 gasEstimationForceSend是一个异步函数,完成后会执行回调函数。
- 调用
-
检查 Gas 估算值:
- 如果
gasLimit不为'0x0'且gasEstimation大于gasLimit,则调用回调函数并返回错误信息,提示用户提高 gas 限制。 - 如果
gasLimit为'0x0',则将交易的gas字段设置为估算的 gas 值。 - 否则,将交易的
gas字段设置为gasLimit。
- 如果
-
检查是否跳过交易确认:
- 调用
this._api.config.getUnpersistedProperty('doNotShowTransactionConfirmationAgain')检查配置是否设置了跳过交易确认。 - 如果设置了跳过交易确认,则直接调用
_executeTx函数执行交易。
- 调用
-
显示交易确认界面:
- 如果没有设置跳过交易确认,则调用
confirmCb函数显示交易确认界面。 confirmCb函数接收network、tx和gas作为参数,并在用户确认后调用回调函数。- 在用户确认后,回调函数会调用
_executeTx函数执行交易。 - 如果确认过程中发生错误,则调用回调函数并传递错误信息。
- 如果没有设置跳过交易确认,则调用
总结
这段代码的主要功能是估算交易的 gas 并根据用户配置和确认情况决定是否执行交易。它首先估算交易所需的 gas,然后根据配置和用户输入设置交易的 gas 字段,最后根据是否跳过确认来决定是否直接执行交易或显示确认界面。
viem
https://viem.sh/docs/actions/public/estimateFeesPerGas
Returns an estimate for the fees per gas (in wei) for a transaction to be likely included in the next block.
If chain.fees.estimateFeesPerGas is set on the Client Chain or override Chain, it will use the returned value.
Otherwise, for EIP-1559 Transactions, viem will estimate the fees using a combination of the block's base fee per gas (to derive maxFeePerGas) + the estimateMaxPriorityFeePerGas Action (to derive maxPriorityFeePerGas). For Legacy Transactions, viem will estimate the fee based on the gas price (via the getGasPrice Action).
这段文字描述了如何估算以太坊交易的费用,具体分为两种情况:EIP-1559 交易和传统(Legacy)交易。以下是详细解释:
1. 使用 chain.fees.estimateFeesPerGas
如果在客户端链(Client Chain)或覆盖链(Override Chain)上设置了 chain.fees.estimateFeesPerGas,则会使用该设置的返回值作为交易费用的估算值。这意味着你可以通过配置链上的参数来直接控制交易费用的估算。
2. EIP-1559 交易
对于 EIP-1559 交易,费用估算是基于以下两部分:
- Base Fee Per Gas:这是当前区块链网络的基础费用,由区块的
baseFeePerGas字段提供。这个基础费用是所有交易必须支付的最低费用。 - Max Priority Fee Per Gas:这是用户愿意支付给矿工的小费,以便优先处理他们的交易。这个值通过
estimateMaxPriorityFeePerGas动作来估算。
结合这两部分,EIP-1559 交易的费用估算公式如下:
- Max Fee Per Gas = Base Fee Per Gas + Max Priority Fee Per Gas
3. Legacy 交易
对于传统(Legacy)交易,费用估算是基于 gasPrice,这个值可以通过 getGasPrice 动作来获取。传统交易不使用 EIP-1559 的费用机制,而是直接使用 gasPrice 字段来指定 交易费用。
具体流程
-
检查
chain.fees.estimateFeesPerGas:- 如果设置了
chain.fees.estimateFeesPerGas,则直接使用该返回值作为交易费用的估算值。
- 如果设置了
-
EIP-1559 交易:
- 获取当前区块的
baseFeePerGas。 - 使用
estimateMaxPriorityFeePerGas动作来估算maxPriorityFeePerGas。 - 计算
maxFeePerGas=baseFeePerGas+maxPriorityFeePerGas。
- 获取当前区块的
-
Legacy 交易:
- 使用
getGasPrice动作来估算gasPrice。
- 使用
代码示例
假设你在编写一个以太坊客户端,这段代码展示了如何根据上述逻辑来估算交易费用:
async function estimateFees(tx, chain) {
let fees;
// 检查是否设置了 chain.fees.estimateFeesPerGas
if (chain.fees && chain.fees.estimateFeesPerGas) {
fees = await chain.fees.estimateFeesPerGas();
} else {
// 判断交易类型
if (tx.type === '0x2') { // EIP-1559 交易
const baseFeePerGas = await getBaseFeePerGas();
const maxPriorityFeePerGas = await estimateMaxPriorityFeePerGas();
fees = {
maxFeePerGas: baseFeePerGas + maxPriorityFeePerGas,
maxPriorityFeePerGas: maxPriorityFeePerGas
};
} else { // Legacy 交易
const gasPrice = await getGasPrice();
fees = { gasPrice: gasPrice };
}
}
return fees;
}
总结
这段文字解释了如何估算以太坊交易的费用,分别针对 EIP-1559 交易和传统交易提供了不同的估算方法。通过设置 chain.fees.estimateFeesPerGas,可以直接控制费用的估算值;否则,将根据区块的基础费用和用户愿意支付的小费来估算 EIP-1559 交易的费用,或通过 gasPrice 来估算传统交易的费用。
userop gas fee
对于一个eip4337 userOp交易是否是eip-1559还是 Legacy 交易 ?
EIP-4337(Account Abstraction via Entry Point Contract)引入了一种新的交易类型,称为 User Operation(UserOp)。这种交易类型与传统的 EIP-1559 和 Legacy 交易有所不同,因为它旨在实现账户抽象,即将账户逻辑从以太坊协议中抽象出来,允许更灵活的账户管理和交易处理。
EIP-4337 UserOp 交易的特点
- Account Abstraction:EIP-4337 通过引入 Entry Point 合约来实现账户抽象,允许用户使用智能合约来管理账户和签名交易。
- User Operation:UserOp 是一种新的交易格式,与传统的 EIP-1559 和 Legacy 交易不同。它包含了更多的字段,用于描述用户操作的详细信息。
EIP-4337 UserOp 与 EIP-1559 和 Legacy 交易的区别
- EIP-1559 交易:这些交易使用了新的费用市场机制,包括
maxFeePerGas和maxPriorityFeePerGas字段,以提高费用估算的稳定性和效率。 - Legacy 交易:这些是传统的以太坊交易,使用
gasPrice字段来指定交易费用。 - EIP-4337 UserOp 交易:这些交易通过 Entry Point 合约来处理,不直接使用 EIP-1559 或 Legacy 交易的费用机制。相反,UserOp 包含了一个新的费用计算方法,通常由 Entry Point 合约来管理和处理。
具体实现
在 EIP-4337 中,UserOp 交易的费用估算和支付方式是由 Entry Point 合约和用户合约共同决定的。以下是一个简化的示例,展示了如何处理 UserOp 交易:
// Entry Point 合约示例
contract EntryPoint {
function handleOps(UserOperation[] calldata ops) external {
for (uint i = 0; i < ops.length; i++) {
UserOperation memory op = ops[i];
// 处理 UserOp 交易,包括费用计算和支付
// 具体实现取决于合约逻辑
}
}
}
// UserOperation 结构示例
struct UserOperation {
address sender;
uint256 nonce;
bytes callData;
uint256 maxFeePerGas;
uint256 maxPriorityFeePerGas;
// 其他字段
}
总结
EIP-4337 UserOp 交易是一种新的交易类型,与 EIP-1559 和 Legacy 交易不同。它通过 Entry Point 合约实现账户抽象,允许更灵活的账户管理和交易处理。UserOp 交易不直接使用 EIP-1559 或 Legacy 交易的费用机制,而是通过 Entry Point 合约来管理和处理费用估算和支付。因此,EIP-4337 UserOp 交易既不是 EIP-1559 交易,也不是 Legacy 交易,而是一种独立的交易类型。
但是 为什么 UserOperation 参数 需要 maxFeePerGas, maxPriorityFeePerGas 这个是根据 EIP-1559 交易 计算还是根据 Legacy 交易 ?
EIP-4337 的 UserOperation(UserOp)虽然是一种新的交易类型,但它仍然需要处理以太坊网络的交易费用。为了与现有的费用机制兼容,UserOp 引入了 maxFeePerGas 和 maxPriorityFeePerGas 这两个参数,这些参数的计算方式与 EIP-1559 交易类似。
为什么 UserOperation 需要 maxFeePerGas 和 maxPriorityFeePerGas
- 兼容性:以太坊网络已经广泛采用了 EIP-1559 的费用机制。通过使用
maxFeePerGas和maxPriorityFeePerGas,UserOp 可以更好地与当前网络的费用市场机制兼容。 - 费用估算:这些参数可以帮助估算交易费用,使得用户可以更好地控制他们愿意支付的最大费用和优先费用。