Skip to content

Commit

Permalink
devsvcs-168: fix chain module l1 fee calculation
Browse files Browse the repository at this point in the history
  • Loading branch information
FelixFan1992 committed Aug 19, 2024
1 parent 0ceb9b5 commit bf026dc
Show file tree
Hide file tree
Showing 9 changed files with 40 additions and 12 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

0 comments on commit bf026dc

Please sign in to comment.