Skip to content

Commit

Permalink
devsvcs-168: fix chain module l1 fee calculation (#14150)
Browse files Browse the repository at this point in the history
* devsvcs-168: fix chain module l1 fee calculation

* Update gethwrappers

* go gen

---------

Co-authored-by: app-token-issuer-infra-releng[bot] <120227048+app-token-issuer-infra-releng[bot]@users.noreply.github.com>
  • Loading branch information
1 parent ec183b5 commit 831d006
Show file tree
Hide file tree
Showing 19 changed files with 624 additions and 69 deletions.
2 changes: 1 addition & 1 deletion contracts/src/v0.8/automation/chains/ArbitrumModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ contract ArbitrumModule is ChainModuleBase {
return ARB_SYS.arbBlockNumber();
}

function getCurrentL1Fee() external view override returns (uint256) {
function getCurrentL1Fee(uint256) external view override returns (uint256) {
return ARB_GAS.getCurrentTxL1GasFees();
}

Expand Down
2 changes: 1 addition & 1 deletion contracts/src/v0.8/automation/chains/ChainModuleBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ contract ChainModuleBase is IChainModule {
return blockhash(n);
}

function getCurrentL1Fee() external view virtual returns (uint256) {
function getCurrentL1Fee(uint256) external view virtual returns (uint256) {
return 0;
}

Expand Down
10 changes: 8 additions & 2 deletions contracts/src/v0.8/automation/chains/OptimismModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,19 @@ contract OptimismModule is ChainModuleBase {
uint256 private constant FIXED_GAS_OVERHEAD = 60_000;
uint256 private constant PER_CALLDATA_BYTE_GAS_OVERHEAD = 270;

function getCurrentL1Fee() external view override returns (uint256) {
return OVM_GASPRICEORACLE.getL1Fee(bytes.concat(msg.data, OP_L1_DATA_FEE_PADDING));
// @dev This will be updated to use the new function introduced by OP team
function getCurrentL1Fee(uint256 dataSize) external view override returns (uint256) {
return _getL1Fee(dataSize);
}

function getMaxL1Fee(uint256 dataSize) external view override returns (uint256) {
return _getL1Fee(dataSize);
}

function _getL1Fee(uint256 dataSize) internal view returns (uint256) {
// fee is 4 per 0 byte, 16 per non-zero byte. Worst case we can have all non zero-bytes.
// Instead of setting bytes to non-zero, we initialize 'new bytes' of length 4*dataSize to cover for zero bytes.
// this is the same as OP.
bytes memory txCallData = new bytes(4 * dataSize);
return OVM_GASPRICEORACLE.getL1Fee(bytes.concat(txCallData, OP_L1_DATA_FEE_PADDING));
}
Expand Down
28 changes: 25 additions & 3 deletions contracts/src/v0.8/automation/chains/ScrollModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@ pragma solidity 0.8.19;

import {IScrollL1GasPriceOracle} from "../../vendor/@scroll-tech/contracts/src/L2/predeploys/IScrollL1GasPriceOracle.sol";
import {ChainModuleBase} from "./ChainModuleBase.sol";
import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol";

contract ScrollModule is ChainModuleBase, ConfirmedOwner {
error InvalidL1FeeCoefficient(uint8 coefficient);
event L1FeeCoefficientSet(uint8 coefficient);

contract ScrollModule is ChainModuleBase {
/// @dev SCROLL_L1_FEE_DATA_PADDING includes 140 bytes for L1 data padding for Scroll
/// @dev according to testing, this padding allows automation registry to properly estimates L1 data fee with 3-5% buffer
/// @dev this MAY NOT work for a different product and this may get out of date if transmit function is changed
Expand All @@ -15,14 +19,22 @@ contract ScrollModule is ChainModuleBase {
address private constant SCROLL_ORACLE_ADDR = 0x5300000000000000000000000000000000000002;
IScrollL1GasPriceOracle private constant SCROLL_ORACLE = IScrollL1GasPriceOracle(SCROLL_ORACLE_ADDR);

/// @dev L1 fee coefficient can be applied to reduce possibly inflated gas cost
uint8 public s_l1FeeCoefficient = 100;
uint256 private constant FIXED_GAS_OVERHEAD = 45_000;
uint256 private constant PER_CALLDATA_BYTE_GAS_OVERHEAD = 170;

function getCurrentL1Fee() external view override returns (uint256) {
return SCROLL_ORACLE.getL1Fee(bytes.concat(msg.data, SCROLL_L1_FEE_DATA_PADDING));
constructor() ConfirmedOwner(msg.sender) {}

function getCurrentL1Fee(uint256 dataSize) external view override returns (uint256) {
return (s_l1FeeCoefficient * _getL1Fee(dataSize)) / 100;
}

function getMaxL1Fee(uint256 dataSize) external view override returns (uint256) {
return _getL1Fee(dataSize);
}

function _getL1Fee(uint256 dataSize) internal view returns (uint256) {
// fee is 4 per 0 byte, 16 per non-zero byte. Worst case we can have all non zero-bytes.
// Instead of setting bytes to non-zero, we initialize 'new bytes' of length 4*dataSize to cover for zero bytes.
// this is the same as OP.
Expand All @@ -38,4 +50,14 @@ contract ScrollModule is ChainModuleBase {
{
return (FIXED_GAS_OVERHEAD, PER_CALLDATA_BYTE_GAS_OVERHEAD);
}

function setL1FeeCalculation(uint8 coefficient) external onlyOwner {
if (coefficient > 100) {
revert InvalidL1FeeCoefficient(coefficient);
}

s_l1FeeCoefficient = coefficient;

emit L1FeeCoefficientSet(coefficient);
}
}
2 changes: 1 addition & 1 deletion contracts/src/v0.8/automation/interfaces/IChainModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ interface IChainModule {
// retrieve the L1 data fee for a L2 transaction. it should return 0 for L1 chains and
// L2 chains which don't have L1 fee component. it uses msg.data to estimate L1 data so
// it must be used with a transaction. Return value in wei.
function getCurrentL1Fee() external view returns (uint256);
function getCurrentL1Fee(uint256 dataSize) external view returns (uint256);

// retrieve the L1 data fee for a L2 simulation. it should return 0 for L1 chains and
// L2 chains which don't have L1 fee component. Return value in wei.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ contract AutomationRegistry2_2 is AutomationRegistryBase2_2, OCR2Abstract, Chain
});

uint256 blocknumber = hotVars.chainModule.blockNumber();
uint256 l1Fee = hotVars.chainModule.getCurrentL1Fee();
uint256 l1Fee = hotVars.chainModule.getCurrentL1Fee(msg.data.length);

for (uint256 i = 0; i < report.upkeepIds.length; i++) {
upkeepTransmitInfo[i].upkeep = s_upkeep[report.upkeepIds[i]];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ contract AutomationRegistry2_3 is AutomationRegistryBase2_3, OCR2Abstract, Chain
});

uint256 blocknumber = hotVars.chainModule.blockNumber();
uint256 l1Fee = hotVars.chainModule.getCurrentL1Fee();
uint256 l1Fee = hotVars.chainModule.getCurrentL1Fee(msg.data.length);

for (uint256 i = 0; i < report.upkeepIds.length; i++) {
upkeepTransmitInfo[i].upkeep = s_upkeep[report.upkeepIds[i]];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ abstract contract AutomationRegistryBase2_3 is ConfirmedOwner {
// These values are calibrated using hardhat tests which simulate various cases and verify that
// the variables result in accurate estimation
uint256 internal constant REGISTRY_CONDITIONAL_OVERHEAD = 98_200; // Fixed gas overhead for conditional upkeeps
uint256 internal constant REGISTRY_LOG_OVERHEAD = 122_500; // Fixed gas overhead for log upkeeps
uint256 internal constant REGISTRY_LOG_OVERHEAD = 123_500; // Fixed gas overhead for log upkeeps
uint256 internal constant REGISTRY_PER_SIGNER_GAS_OVERHEAD = 5_600; // Value scales with f
uint256 internal constant REGISTRY_PER_PERFORM_BYTE_GAS_OVERHEAD = 24; // Per perform data byte overhead

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ contract ZKSyncAutomationRegistry2_3 is ZKSyncAutomationRegistryBase2_3, OCR2Abs
});

uint256 blocknumber = hotVars.chainModule.blockNumber();
uint256 l1Fee = hotVars.chainModule.getCurrentL1Fee();
uint256 l1Fee = hotVars.chainModule.getCurrentL1Fee(msg.data.length); // this will be updated

for (uint256 i = 0; i < report.upkeepIds.length; i++) {
upkeepTransmitInfo[i].upkeep = s_upkeep[report.upkeepIds[i]];
Expand Down
18 changes: 9 additions & 9 deletions core/gethwrappers/generated/arbitrum_module/arbitrum_module.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Loading

0 comments on commit 831d006

Please sign in to comment.