Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 11 additions & 11 deletions .gas-snapshot
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
FeeVaultSplitterTest:testFuzz_balances_after_multiple_payments(uint8,uint256[9]) (runs: 256, μ: 4744057, ~: 3749281)
FeeVaultSplitterTest:testFuzz_balances_after_payment(uint8,uint256) (runs: 256, μ: 2848294, ~: 1764000)
FeeVaultSplitterTest:testFuzz_balances_after_multiple_payments(uint8,uint256[9]) (runs: 257, μ: 4633841, ~: 3278232)
FeeVaultSplitterTest:testFuzz_balances_after_payment(uint8,uint256) (runs: 257, μ: 2747347, ~: 1764012)
FeeVaultSplitterTest:test__codesize() (gas: 30307)
FeeVaultSplitterTest:test_balances_after_payment() (gas: 262015)
FeeVaultSplitterTest:test_distribute_clamps_end_to_payees_length() (gas: 247482)
Expand All @@ -24,20 +24,20 @@ FeeVaultSplitterTest:test_revert_release_account_has_no_shares() (gas: 11672)
FeeVaultSplitterTest:test_revert_release_account_not_due_payment() (gas: 20633)
FeeVaultSplitterTest:test_revert_release_failed_to_send_value() (gas: 1047207)
FeeVaultSplitterTest:test_revert_release_insufficient_balance() (gas: 36608)
GasbackTest:testConvertGasback() (gas: 52487)
GasbackTest:testConvertGasback(uint256,uint256) (runs: 256, μ: 416918, ~: 279220)
GasbackTest:testConvertGasbackCodelessBaseFeeVaultPassesThrough() (gas: 23689)
GasbackTest:testConvertGasbackMaxBaseFee() (gas: 22353)
GasbackTest:testConvertGasbackPullsFromDirectRecipientBaseFeeVault() (gas: 1220102)
GasbackTest:testConvertGasbackPullsFromSplitterRecipientBaseFeeVault() (gas: 2271856)
GasbackTest:testConvertGasbackRevertingBaseFeeVaultPassesThrough() (gas: 180145)
GasbackTest:testConvertGasbackRevertsInnerWithdrawWhenSplitterShareInsufficient() (gas: 1241543)
GasbackTest:testConvertGasback() (gas: 52505)
GasbackTest:testConvertGasback(uint256,uint256) (runs: 257, μ: 414672, ~: 315288)
GasbackTest:testConvertGasbackCodelessBaseFeeVaultPassesThrough() (gas: 23707)
GasbackTest:testConvertGasbackMaxBaseFee() (gas: 22371)
GasbackTest:testConvertGasbackPullsFromDirectRecipientBaseFeeVault() (gas: 1220120)
GasbackTest:testConvertGasbackPullsFromSplitterRecipientBaseFeeVault() (gas: 2271874)
GasbackTest:testConvertGasbackRevertingBaseFeeVaultPassesThrough() (gas: 180163)
GasbackTest:testConvertGasbackRevertsInnerWithdrawWhenSplitterShareInsufficient() (gas: 1241561)
GasbackTest:testSetGasbackRatioNumeratorAcceptsScriptValue() (gas: 15541)
GasbackTest:testSetGasbackRatioNumeratorRevertsWhenValueAboveDenominator() (gas: 9672)
GasbackTest:testTriggerBaseFeeVaultWithdrawRevertsWhenCallerIsNotSelf() (gas: 8751)
GasbackTest:testWithdrawRevertsWhenCallerUnauthorized() (gas: 9543)
GasbackTest:testWithdrawTransfersEthWhenCallerSelf() (gas: 45507)
GasbackTest:testWithdrawTransfersEthWhenCallerSystem() (gas: 45643)
GasbackTest:test__codesize() (gas: 20055)
GasbackTest:test__codesize() (gas: 20277)
SoladyTest:test__codesize() (gas: 4099)
TestPlus:test__codesize() (gas: 393)
8 changes: 8 additions & 0 deletions foundry.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"lib/forge-std": {
"rev": "77041d2ce690e692d6e03cc812b57d1ddaa4d505"
},
"lib/solady": {
"rev": "4363564a984779b7eec3bff00ab1de3a9db4e2d5"
}
}
1 change: 1 addition & 0 deletions remappings.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@openzeppelin-contracts-4.9.5/=dependencies/@openzeppelin-contracts-4.9.5/
14 changes: 8 additions & 6 deletions src/FeeVaultSplitter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,14 @@ contract FeeVaultSplitter is PaymentSplitter, ReentrancyGuard {
* https://solidity.readthedocs.io/en/latest/contracts.html#fallback-function[fallback
* functions].
*
* SECURITY / DoS NOTE (push-payment model): this function attempts to release to every payee in
* `externalPayees` in a single call. Its gas cost therefore scales with the payee count, and a payee whose
* `receive`/fallback consumes a large amount of gas (rather than cheaply reverting, which is caught and skipped)
* can push this call out of gas and make it revert. Because the OP base fee vault's `withdraw()` sends fees to
* this contract (triggering `receive`), such a revert would block that withdrawal and strand base fees in the
* vault until resolved. To bound this risk: keep the payee set small and trusted (it is fixed at deployment).
* SECURITY / DoS NOTE (push-payment model): this function attempts to release to every payee in `externalPayees`
* in a single call. Its gas cost therefore scales with the payee count, and a payee whose `receive`/fallback
* consumes a large amount of gas (rather than cheaply reverting, which is caught and skipped) can push this call
* out of gas and make it revert. Because the OP base fee vault's `withdraw()` sends fees to this contract
* (triggering `receive`), such a revert would block that withdrawal and strand base fees in the vault until resolved.
* Additionally, a malicious payee ordered after the Gasback contract in `payees_` can re-enter the Gasback contract
* during distribution and use up the ETH just released to it, leaving no ETH for the original caller so their call is skipped.
* To bound this risk: keep the payee set small and trusted (it is fixed at deployment).
* If a deposit's auto-distribution is ever blocked, funds are not lost — anyone can call {distribute} with a
* bounded `[start, end)` slice to release payees in chunks and recover.
*/
Expand Down
7 changes: 6 additions & 1 deletion src/Gasback.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ pragma solidity ^0.8.7;
/// @dev A contract that converts a portion of the gas burned into ETH.
/// This contract holds ETH deposited by the sequencer, which will be
/// redistributed to callers.
/// @dev Configuration notes:
/// - The baseFeeVault's WITHDRAWAL_NETWORK should be configured to withdraw to the network this contract is deployed on.
/// - The baseFeeVault's MIN_WITHDRAWAL_AMOUNT should be set to a reasonable value below ethToGive in order for withdrawals to be successful.
contract Gasback {
/*«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-*/
/* CONSTANTS */
Expand Down Expand Up @@ -46,6 +49,7 @@ contract Gasback {
/* CONSTRUCTOR */
/*-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»*/

/// @dev When using this contract with EIP-7702, setters must be called to configure the constructor values.
constructor() payable {
GasbackStorage storage $ = _getGasbackStorage();
$.gasbackRatioNumerator = 0.6 ether;
Expand Down Expand Up @@ -136,6 +140,7 @@ contract Gasback {

/// @dev For the gasback logic.
fallback() external payable {
require(tx.gasprice != 0, "Gasback: gasprice is 0"); // Prevents L1 -> L2 deposits from being used.
uint256 gasToBurn;

/// @solidity memory-safe-assembly
Expand All @@ -159,7 +164,7 @@ contract Gasback {
if (ethToGive > selfBalance && block.basefee <= $.gasbackMaxBaseFee) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, 0xc70746b1) // `triggerBaseFeeVaultWithdraw(uint256)`.
mstore(0x00, 0xc70746b1) // `triggerBaseFeeVaultWithdraw(uint256)`. we don't check success here because it will revert if the base fee vault is out of ETH.
mstore(0x20, ethToGive)
pop(call(gas(), address(), 0, 0x1c, 0x24, 0x00, 0x00))
}
Expand Down
1 change: 0 additions & 1 deletion test/FeeVaultSplitter.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -582,4 +582,3 @@ contract FeeVaultSplitterTest is SoladyTest {
assertEq(address(splitter).balance, 0);
}
}

1 change: 1 addition & 0 deletions test/Gasback.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ contract GasbackTest is SoladyTest {
Gasback public gasback;

function setUp() public {
vm.txGasPrice(1);
gasback = new Gasback();
vm.deal(address(gasback), 2 ** 160);
}
Expand Down
6 changes: 5 additions & 1 deletion test/utils/TestPlus.sol
Original file line number Diff line number Diff line change
Expand Up @@ -553,7 +553,11 @@ contract TestPlus is Brutalizer {

/// @dev Truncate the bytes to `n` bytes.
/// Returns the result for function chaining.
function _truncateBytes(bytes memory b, uint256 n) internal pure returns (bytes memory result) {
function _truncateBytes(bytes memory b, uint256 n)
internal
pure
returns (bytes memory result)
{
/// @solidity memory-safe-assembly
assembly {
if gt(mload(b), n) { mstore(b, n) }
Expand Down
Loading