-
Notifications
You must be signed in to change notification settings - Fork 6
feat: transact gas limits #56
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,12 @@ pragma solidity ^0.8.24; | |
import {Passage} from "./Passage.sol"; | ||
|
||
contract Zenith { | ||
/// @notice Each `transact` call cannot use more than 1/5 of the global `transact` gasLimit for the block. | ||
uint256 public constant PER_TRANSACT_GAS_LIMIT = 5; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. still need to align on parameterization of this constant There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. MAX_TRANSACTS_PER_BLOCK There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. well, it wouldn't be max transacts per block right if this is set at 5, you could still have 10 transacts in the block if they use less than the limit (which i think we expect) but yeah.. we should rename this var There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. when I said "need to align on parameterization" above I meant what should we set this as - 5? 3? 2? i think not more than 5. |
||
|
||
/// @notice The chainId of rollup that Ether will be sent to by default when entering the rollup via fallback() or receive(). | ||
uint256 public immutable defaultRollupChainId; | ||
|
||
/// @notice The address that is allowed to set/remove sequencers. | ||
address public immutable sequencerAdmin; | ||
|
||
|
@@ -27,9 +33,18 @@ contract Zenith { | |
} | ||
|
||
/// @notice The host block number that a block was last submitted at for a given rollup chainId. | ||
/// rollupChainId => host blockNumber that block was last submitted at | ||
/// rollupChainId => host blockNumber the last block was submitted at. | ||
mapping(uint256 => uint256) public lastSubmittedAtBlock; | ||
|
||
/// @notice The gasLimit of the last submitted block for a given rollup chainId. | ||
/// @dev NOTE that this can change mid-block, causing some `transact` to have a different limit than others. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. starting at this WIP code to figure the best way to fix this (or if it's necessary) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. consider the following set of host chain transactions within a single block:
The first two i wonder if this could cause any weird or unexpected behavior? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. that's not necessarily the case, you'd just have to store the last block's limit the first time a transact occurs. bears more discussion tho |
||
/// rollupChainId => gasLimit of the previous block. | ||
mapping(uint256 => uint256) public currentGasLimit; | ||
|
||
/// @notice The total gasLimit used by `transact` so far in this block. | ||
/// rollupChainId => block number => `transasct` gasLimit used so far. | ||
mapping(uint256 => mapping(uint256 => uint256)) public transactGasUsed; | ||
|
||
/// @notice Registry of permissioned sequencers. | ||
/// address => TRUE if it's a permissioned sequencer | ||
mapping(address => bool) public isSequencer; | ||
|
@@ -45,6 +60,12 @@ contract Zenith { | |
/// @notice Thrown when attempting to submit more than one rollup block per host block | ||
error OneRollupBlockPerHostBlock(); | ||
|
||
/// @notice Thrown when attempting to use more then the current global `transact` gasLimit for the block. | ||
error GlobalTransactGasLimitReached(uint256 globalTransactLimit); | ||
|
||
/// @notice Thrown when attempting to use too much gas per single `transact` call. | ||
error PerTransactGasLimitReached(uint256 perTransactLimit); | ||
|
||
/// @notice Thrown when attempting to modify sequencer roles if not sequencerAdmin. | ||
error OnlySequencerAdmin(); | ||
|
||
|
@@ -63,10 +84,22 @@ contract Zenith { | |
bytes32 blockDataHash | ||
); | ||
|
||
/// @notice Emitted to send a special transaction to the rollup. | ||
event Transact( | ||
uint256 indexed rollupChainId, | ||
address indexed sender, | ||
address indexed to, | ||
bytes data, | ||
uint256 value, | ||
uint256 gas, | ||
uint256 maxFeePerGas | ||
); | ||
|
||
/// @notice Emitted when a sequencer is added or removed. | ||
event SequencerSet(address indexed sequencer, bool indexed permissioned); | ||
|
||
constructor(address _sequencerAdmin) { | ||
constructor(uint256 _defaultRollupChainId, address _sequencerAdmin) { | ||
defaultRollupChainId = _defaultRollupChainId; | ||
sequencerAdmin = _sequencerAdmin; | ||
deployBlockNumber = block.number; | ||
} | ||
|
@@ -118,13 +151,50 @@ contract Zenith { | |
// assert this is the first rollup block submitted for this host block | ||
if (lastSubmittedAtBlock[header.rollupChainId] == block.number) revert OneRollupBlockPerHostBlock(); | ||
lastSubmittedAtBlock[header.rollupChainId] = block.number; | ||
currentGasLimit[header.rollupChainId] = header.gasLimit; | ||
|
||
// emit event | ||
emit BlockSubmitted( | ||
sequencer, header.rollupChainId, header.gasLimit, header.rewardAddress, header.blockDataHash | ||
); | ||
} | ||
|
||
/// @dev See `transact` for docs. | ||
function transact(address to, bytes calldata data, uint256 value, uint256 gas, uint256 maxFeePerGas) external { | ||
transact(defaultRollupChainId, to, data, value, gas, maxFeePerGas); | ||
} | ||
|
||
/// @notice Send a special transaction to be sent to the rollup with sender == L1 msg.sender. | ||
/// @dev Transact is processed after normal rollup block execution. | ||
/// @param rollupChainId - The rollup chain to send the transaction to. | ||
/// @param to - The address to call on the rollup. | ||
/// @param data - The data to send to the rollup. | ||
/// @param value - The amount of Ether to send on the rollup. | ||
/// @param gas - The gas limit for the transaction. | ||
/// @param maxFeePerGas - The maximum fee per gas for the transaction (per EIP-1559). | ||
/// @custom:emits Transact indicating the transaction to mine on the rollup. | ||
function transact( | ||
uint256 rollupChainId, | ||
address to, | ||
bytes calldata data, | ||
uint256 value, | ||
uint256 gas, | ||
uint256 maxFeePerGas | ||
) public { | ||
// ensure per-transact gas limit is respected | ||
uint256 globalLimit = currentGasLimit[rollupChainId]; | ||
uint256 perTransactLimit = globalLimit / PER_TRANSACT_GAS_LIMIT; | ||
if (gas > perTransactLimit) revert PerTransactGasLimitReached(perTransactLimit); | ||
|
||
// ensure global transact gas limit is respected | ||
uint256 gasUsed = transactGasUsed[rollupChainId][block.number]; | ||
if (gasUsed + gas > globalLimit) revert GlobalTransactGasLimitReached(globalLimit); | ||
transactGasUsed[rollupChainId][block.number] = gasUsed + gas; | ||
|
||
// emit Transact event | ||
emit Transact(rollupChainId, msg.sender, to, data, value, gas, maxFeePerGas); | ||
} | ||
|
||
/// @notice Construct hash of block details that the sequencer signs. | ||
/// @param header - the header information for the rollup block. | ||
/// @return commit - the hash of the encoded block details. | ||
|
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note: moving
transact
to Zenith && splitting Passage from Zenith means that EOAs can no longer atomicallyenter
+transact
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this seems bad
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the only ways around this would be
Passage.enter
as an external contract (i find this to be undesirable but it could be done)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
seems fine