链间燃料费支付
为了deliver a message,目标链上必须包含一个事务,该事务使用编码的消息和ISM元数据调用邮箱的 process
函数。
为了方便起见,relayer监视已分发的消息,如果消息发送者在原始链上收到足够的付款,则代表消息发送者提交进程事务。我们称之为链间燃料费支付。
因为消息可以触发任意代码执行,所以中继器必须用gasLimit
测量handle
call ,以便在消息分发时适当收费。
Post Dispatch
在发送后钩子期间,如果付款不足以支付中继器的“预期”成本,则 InterchainGasPaymaster
合同将回滚。中继器将尊重dispatch
时间的报价。
Gas Limit
当没有指定时,用于计量handle
调用的 gasLimit
使用静态默认值50_000
。
我们建议开发人员在单元测试中对他们的handle
implementations 进行基准测试,以确定要使用的合理gasLimit
。
如果你希望 handle
函数消耗超过这个默认值,你应该覆盖default gasLimit
in metadata。
退款
如果消息发送方支付的金额超过钩子报价,合同将退还差额。如果没有指定,退款地址将默认为消息发送方。这允许发送方跳过显式的quoteDispatch
调用。
退款可能存在reentrancy。应特别注意确保安全,防止再入漏洞。
只有在付款金额大于报价的情况下才会退款。如果发送所需的燃料费比已支付的燃料费少,则不会退款。如果退款不成功,payForGas
调用将回滚。要指定不同的退款地址,请覆盖default refundAddress
in metadata。
元数据
这个钩子需要StandardHookMetadata
的打包编码的元数据。关于如何传递元数据覆盖,请参阅邮箱Mailboxdispatch overloads 。
- Solidity
struct StandardHookMetadata {
uint16 variant;
uint256 msgValue;
uint256 gasLimit;
address refundAddress;
}
示例
bytes memory metadata = abi.encodePacked(
StandardHookMetadata({
variant: 1, // only variant supported by this hook
msgValue: 0, // unused by this hook
gasLimit: 100000, // override default gas limit
refundAddress: msg.sender // override default refund address
})
);
Gas Oracles
链间燃料费支付需求是使用支持的始发链和目的地链之间的整体燃料价格和汇率来计算的。
汇率和天然气价格由中继器决定。 可能会收取差价,以计入漂没和运营成本。
- Solidity
function getExchangeRateAndGasPrice(
uint32 _destinationDomain
)
public
view
override
returns (uint128 tokenExchangeRate, uint128 gasPrice)
{
IGasOracle _gasOracle = destinationGasConfigs[_destinationDomain]
.gasOracle;
require(
address(_gasOracle) != address(0),
string.concat(
"Configured IGP doesn't support domain ",
Strings.toString(_destinationDomain)
)
);
return _gasOracle.getExchangeRateAndGasPrice(_destinationDomain);
}
参数
destinationDomain
: 消息的目的域
返回
tokenExchangeRate
: 起源链和目的地链的gas代币之间的汇率gasPrice
: 目的地链的燃料价格
quoteGasPayment
函数计算中继器预期成本的费用。
- Solidity
function quoteGasPayment(
uint32 _destinationDomain,
uint256 _gasLimit
) public view virtual override returns (uint256) {
// Get the gas data for the destination domain.
(
uint128 _tokenExchangeRate,
uint128 _gasPrice
) = getExchangeRateAndGasPrice(_destinationDomain);
// The total cost quoted in destination chain's native token.
uint256 _destinationGasCost = _gasLimit * uint256(_gasPrice);
// Convert to the local native token.
return
(_destinationGasCost * _tokenExchangeRate) /
TOKEN_EXCHANGE_RATE_SCALE;
}
参数
destinationDomain
: 消息的目的域gasLimit
: 测量handle
调用的燃料制
返回
fee
:postDispatch
成功所需的付款
重试
如果handle
调用消耗的燃料费超过报价,中继器将不会提交进程事务。在这种情况下,可以使用payForGas
功能支付额外的gas。
- Solidity
function payForGas(
bytes32 _messageId,
uint32 _destinationDomain,
uint256 _gasAmount,
address _refundAddress
) external payable;
参数
messageId
: 从dispatch
调用返回的消息标识符destinationDomain
: 消息的目的域gasAmount
: 额外的燃料费用refundAddress
: 退还超额款项的地址