From d953dc47a02fdff2208bb18c31f9ac82c4b47402 Mon Sep 17 00:00:00 2001 From: j6i <43463199+j6i@users.noreply.github.com> Date: Fri, 3 Oct 2025 20:39:41 -0700 Subject: [PATCH 1/5] add accruedRecipient, add test --- src/Gasback.sol | 22 ++++++++++++++++++++++ test/Gasback.t.sol | 26 ++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/src/Gasback.sol b/src/Gasback.sol index 978507e..117e287 100644 --- a/src/Gasback.sol +++ b/src/Gasback.sol @@ -34,6 +34,8 @@ contract Gasback { uint256 minVaultBalance; // The amount of ETH accrued by taking a cut from the gas burned. uint256 accrued; + // The address to send accrued ETH to. + address accruedRecipient; // A mapping of addresses authorized to withdraw the accrued ETH. mapping(address => bool) accuralWithdrawers; } @@ -58,6 +60,7 @@ contract Gasback { $.gasbackMaxBaseFee = type(uint256).max; $.baseFeeVault = 0x4200000000000000000000000000000000000019; $.minVaultBalance = 0.42 ether; + $.accruedRecipient = 0x4200000000000000000000000000000000000019; } /*«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-*/ @@ -120,6 +123,25 @@ contract Gasback { return true; } + /// @dev Withdraws from the accrued amount to the accrued recipient. + function withdrawAccruedToAccruedRecipient(uint256 amount) public virtual returns (bool) { + // Checked math prevents underflow. + _getGasbackStorage().accrued -= amount; + + address accruedRecipient = _getGasbackStorage().accruedRecipient; + /// @solidity memory-safe-assembly + assembly { + if iszero(call(gas(), accruedRecipient, amount, 0x00, 0x00, 0x00, 0x00)) { revert(0x00, 0x00) } + } + return true; + } + + /// @dev Sets the accrued recipient. + function setAccruedRecipient(address value) public onlySystemOrThis returns (bool) { + _getGasbackStorage().accruedRecipient = value; + return true; + } + /*«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-*/ /* ADMIN FUNCTIONS */ /*-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»*/ diff --git a/test/Gasback.t.sol b/test/Gasback.t.sol index 03463f1..3ccac5a 100644 --- a/test/Gasback.t.sol +++ b/test/Gasback.t.sol @@ -75,4 +75,30 @@ contract GasbackTest is SoladyTest { assertTrue(success); assertEq(pranker.balance, 0); } + + function testGasbackWithAccruedToAccruedRecipient() public { + address system = 0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE; + vm.prank(system); + gasback.setAccruedRecipient(address(42)); + + uint256 baseFee = 1 ether; + uint256 gasToBurn = 333; + + address pranker = address(111); + vm.fee(baseFee); + vm.deal(pranker, 1000 ether); + + vm.prank(pranker); + (bool success,) = address(gasback).call(abi.encode(gasToBurn)); + assertTrue(success); + + uint256 accrued = gasback.accrued(); + + assertNotEq(accrued, 0); + + vm.prank(pranker); + gasback.withdrawAccruedToAccruedRecipient(accrued); + + assertEq(address(42).balance, accrued); + } } From da33c4ebf1417b81b1ba3008031122d1db8eb247 Mon Sep 17 00:00:00 2001 From: j6i <43463199+j6i@users.noreply.github.com> Date: Fri, 3 Oct 2025 20:40:09 -0700 Subject: [PATCH 2/5] follow naming --- test/Gasback.t.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Gasback.t.sol b/test/Gasback.t.sol index 3ccac5a..aad4b7a 100644 --- a/test/Gasback.t.sol +++ b/test/Gasback.t.sol @@ -76,7 +76,7 @@ contract GasbackTest is SoladyTest { assertEq(pranker.balance, 0); } - function testGasbackWithAccruedToAccruedRecipient() public { + function testConvertGasbackWithAccruedToAccruedRecipient() public { address system = 0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE; vm.prank(system); gasback.setAccruedRecipient(address(42)); From 4d8b26fd76477ef22a6d8575744579847934133e Mon Sep 17 00:00:00 2001 From: j6i <43463199+j6i@users.noreply.github.com> Date: Fri, 3 Oct 2025 20:46:55 -0700 Subject: [PATCH 3/5] update comment --- src/Gasback.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Gasback.sol b/src/Gasback.sol index 117e287..224713f 100644 --- a/src/Gasback.sol +++ b/src/Gasback.sol @@ -34,7 +34,7 @@ contract Gasback { uint256 minVaultBalance; // The amount of ETH accrued by taking a cut from the gas burned. uint256 accrued; - // The address to send accrued ETH to. + // The recipient of the accrued ETH. address accruedRecipient; // A mapping of addresses authorized to withdraw the accrued ETH. mapping(address => bool) accuralWithdrawers; From dd69a02216f007301e23e04a4c1d8fa870be233f Mon Sep 17 00:00:00 2001 From: j6i <43463199+j6i@users.noreply.github.com> Date: Fri, 3 Oct 2025 20:52:58 -0700 Subject: [PATCH 4/5] format --- src/Gasback.sol | 4 +++- test/Gasback.t.sol | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Gasback.sol b/src/Gasback.sol index 224713f..b7f3270 100644 --- a/src/Gasback.sol +++ b/src/Gasback.sol @@ -131,7 +131,9 @@ contract Gasback { address accruedRecipient = _getGasbackStorage().accruedRecipient; /// @solidity memory-safe-assembly assembly { - if iszero(call(gas(), accruedRecipient, amount, 0x00, 0x00, 0x00, 0x00)) { revert(0x00, 0x00) } + if iszero(call(gas(), accruedRecipient, amount, 0x00, 0x00, 0x00, 0x00)) { + revert(0x00, 0x00) + } } return true; } diff --git a/test/Gasback.t.sol b/test/Gasback.t.sol index aad4b7a..1710cc2 100644 --- a/test/Gasback.t.sol +++ b/test/Gasback.t.sol @@ -87,7 +87,7 @@ contract GasbackTest is SoladyTest { address pranker = address(111); vm.fee(baseFee); vm.deal(pranker, 1000 ether); - + vm.prank(pranker); (bool success,) = address(gasback).call(abi.encode(gasToBurn)); assertTrue(success); From d0f180a91a27ceeaea62572d26a22551cd50d0dc Mon Sep 17 00:00:00 2001 From: j6i <43463199+j6i@users.noreply.github.com> Date: Fri, 3 Oct 2025 20:53:23 -0700 Subject: [PATCH 5/5] snapshot --- .gas-snapshot | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/.gas-snapshot b/.gas-snapshot index b3a3bea..152f635 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -1,8 +1,9 @@ -GasbackTest:testConvertGasback() (gas: 50450) -GasbackTest:testConvertGasback(uint256,uint256) (runs: 256, μ: 370473, ~: 135584) -GasbackTest:testConvertGasbackBaseFeeVault() (gas: 24310) -GasbackTest:testConvertGasbackMaxBaseFee() (gas: 21878) -GasbackTest:testConvertGasbackMinVaultBalance() (gas: 24154) -GasbackTest:test__codesize() (gas: 8178) +GasbackTest:testConvertGasback() (gas: 73039) +GasbackTest:testConvertGasback(uint256,uint256) (runs: 257, μ: 423506, ~: 308109) +GasbackTest:testConvertGasbackBaseFeeVault() (gas: 27070) +GasbackTest:testConvertGasbackMaxBaseFee() (gas: 44525) +GasbackTest:testConvertGasbackMinVaultBalance() (gas: 26953) +GasbackTest:testConvertGasbackWithAccruedToAccruedRecipient() (gas: 69305) +GasbackTest:test__codesize() (gas: 9846) SoladyTest:test__codesize() (gas: 4099) TestPlus:test__codesize() (gas: 393) \ No newline at end of file