-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #424 from FastLane-Labs/l2-gas-calc
feat: base L2 gas calculator contract
- Loading branch information
Showing
7 changed files
with
130 additions
and
5 deletions.
There are no files selected for viewing
Submodule forge-std
updated
28 files
+6 −12 | .github/workflows/ci.yml | |
+3 −1 | .github/workflows/sync.yml | |
+2 −2 | foundry.toml | |
+1 −1 | package.json | |
+1 −1 | src/StdAssertions.sol | |
+21 −8 | src/StdChains.sol | |
+2 −2 | src/StdCheats.sol | |
+18 −3 | src/StdInvariant.sol | |
+104 −0 | src/StdJson.sol | |
+1 −1 | src/StdStorage.sol | |
+104 −0 | src/StdToml.sol | |
+1 −1 | src/StdUtils.sol | |
+321 −51 | src/Vm.sol | |
+401 −382 | src/console.sol | |
+1 −1,555 | src/console2.sol | |
+1 −5 | src/mocks/MockERC721.sol | |
+693 −4 | src/safeconsole.sol | |
+1 −1 | test/StdAssertions.t.sol | |
+26 −19 | test/StdChains.t.sol | |
+11 −11 | test/StdCheats.t.sol | |
+12 −12 | test/StdError.t.sol | |
+1 −1 | test/StdJson.t.sol | |
+4 −14 | test/StdMath.t.sol | |
+13 −5 | test/StdStorage.t.sol | |
+1 −1 | test/StdStyle.t.sol | |
+1 −1 | test/StdToml.t.sol | |
+12 −12 | test/StdUtils.t.sol | |
+2 −2 | test/Vm.t.sol |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
// SPDX-License-Identifier: UNLICENSED | ||
pragma solidity 0.8.25; | ||
|
||
import "forge-std/Test.sol"; | ||
|
||
import { DeployBaseScript } from "script/base/deploy-base.s.sol"; | ||
import { BaseGasCalculator } from "src/contracts/gasCalculator/BaseGasCalculator.sol"; | ||
|
||
contract DeployGasCalculatorScript is DeployBaseScript { | ||
// NOTE: Adjust the constructor parameters as needed here: | ||
// - BASE_GAS_PRICE_ORACLE: The address of the gas price oracle contract | ||
// - BASE_CALLDATA_LENGTH_OFFSET: The offset to be applied to the calldata length (can be negative or positive) | ||
// ----------------------------------------------------------------------------------------------- | ||
address constant BASE_GAS_PRICE_ORACLE = address(0x420000000000000000000000000000000000000F); | ||
int256 constant BASE_CALLDATA_LENGTH_OFFSET = 0; // can be negative or positive | ||
// ----------------------------------------------------------------------------------------------- | ||
|
||
function run() external { | ||
console.log("\n=== DEPLOYING GasCalculator ===\n"); | ||
|
||
console.log("Deploying to chain: \t\t", _getDeployChain()); | ||
|
||
uint256 deployerPrivateKey = vm.envUint("GOV_PRIVATE_KEY"); | ||
address deployer = vm.addr(deployerPrivateKey); | ||
|
||
console.log("Deployer address: \t\t", deployer); | ||
|
||
uint256 chainId = block.chainid; | ||
address deploymentAddr; | ||
|
||
vm.startBroadcast(deployerPrivateKey); | ||
|
||
if (chainId == 8453 || chainId == 84_532) { | ||
// Base or Base Sepolia | ||
BaseGasCalculator gasCalculator = new BaseGasCalculator({ | ||
gasPriceOracle: BASE_GAS_PRICE_ORACLE, | ||
calldataLenOffset: BASE_CALLDATA_LENGTH_OFFSET | ||
}); | ||
deploymentAddr = address(gasCalculator); | ||
} else { | ||
revert("Error: Chain ID not supported"); | ||
} | ||
|
||
vm.stopBroadcast(); | ||
|
||
_writeAddressToDeploymentsJson("L2_GAS_CALCULATOR", deploymentAddr); | ||
|
||
console.log("\n"); | ||
console.log("-------------------------------------------------------------------------------"); | ||
console.log("| Contract | Address |"); | ||
console.log("-------------------------------------------------------------------------------"); | ||
console.log("| L2_GAS_CALCULATOR (Base) | ", address(deploymentAddr), " |"); | ||
console.log("-------------------------------------------------------------------------------"); | ||
console.log("\n"); | ||
console.log("You can find a list of contract addresses from the latest deployment in deployments.json"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
//SPDX-License-Identifier: BUSL-1.1 | ||
pragma solidity 0.8.25; | ||
|
||
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; | ||
import { IL2GasCalculator } from "src/contracts/interfaces/IL2GasCalculator.sol"; | ||
|
||
/// @notice Implementation: | ||
/// https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/L2/GasPriceOracle.sol | ||
/// @notice Deployment on Base: https://basescan.org/address/0x420000000000000000000000000000000000000f | ||
interface IGasPriceOracle { | ||
function getL1FeeUpperBound(uint256 _unsignedTxSize) external view returns (uint256); | ||
} | ||
|
||
contract BaseGasCalculator is IL2GasCalculator, Ownable { | ||
uint256 internal constant _CALLDATA_LENGTH_PREMIUM = 16; | ||
uint256 internal constant _BASE_TRANSACTION_GAS_USED = 21_000; | ||
|
||
address public immutable GAS_PRICE_ORACLE; | ||
int256 public calldataLengthOffset; | ||
|
||
constructor(address gasPriceOracle, int256 calldataLenOffset) Ownable(msg.sender) { | ||
GAS_PRICE_ORACLE = gasPriceOracle; | ||
calldataLengthOffset = calldataLenOffset; | ||
} | ||
|
||
/// @notice Calculate the cost of calldata in ETH on a L2 with a different fee structure than mainnet | ||
/// @param calldataLength The length of the calldata in bytes | ||
/// @return calldataCost The cost of the calldata in ETH | ||
function getCalldataCost(uint256 calldataLength) external view override returns (uint256 calldataCost) { | ||
// `getL1FeeUpperBound` returns the upper bound of the L1 fee in wei. It expects an unsigned transaction size in | ||
// bytes, *not calldata length only*, which makes this function a rough estimate. | ||
|
||
// Base execution cost. | ||
calldataCost = calldataLength * _CALLDATA_LENGTH_PREMIUM * tx.gasprice; | ||
|
||
// L1 data cost. | ||
// `getL1FeeUpperBound` adds 68 to the size because it expects an unsigned transaction size. | ||
// Remove 68 to the length to account for this. | ||
if (calldataLength < 68) { | ||
calldataLength = 0; | ||
} else { | ||
calldataLength -= 68; | ||
} | ||
|
||
int256 _calldataLenOffset = calldataLengthOffset; | ||
|
||
if (_calldataLenOffset < 0 && calldataLength < uint256(-_calldataLenOffset)) { | ||
return calldataCost; | ||
} | ||
|
||
calldataLength += uint256(_calldataLenOffset); | ||
calldataCost += IGasPriceOracle(GAS_PRICE_ORACLE).getL1FeeUpperBound(calldataLength); | ||
} | ||
|
||
/// @notice Gets the cost of initial gas used for a transaction with a different calldata fee than mainnet | ||
/// @param calldataLength The length of the calldata in bytes | ||
function initialGasUsed(uint256 calldataLength) external pure override returns (uint256 gasUsed) { | ||
return _BASE_TRANSACTION_GAS_USED + (calldataLength * _CALLDATA_LENGTH_PREMIUM); | ||
} | ||
|
||
/// @notice Sets the calldata length offset | ||
/// @param calldataLenOffset The new calldata length offset | ||
function setCalldataLengthOffset(int256 calldataLenOffset) external onlyOwner { | ||
calldataLengthOffset = calldataLenOffset; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters