Skip to content

Commit

Permalink
set gas refund beneficiary as metacall parameter
Browse files Browse the repository at this point in the history
  • Loading branch information
jj1980a committed Nov 18, 2024
1 parent a4d5b88 commit b212c99
Show file tree
Hide file tree
Showing 18 changed files with 45 additions and 39 deletions.
8 changes: 6 additions & 2 deletions src/contracts/atlas/Atlas.sol
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,13 @@ contract Atlas is Escrow, Factory {
/// @param userOp The UserOperation struct containing the user's transaction data.
/// @param solverOps The SolverOperation array containing the solvers' transaction data.
/// @param dAppOp The DAppOperation struct containing the DApp's transaction data.
/// @param gasRefundBeneficiary The address to receive the gas refund.
/// @return auctionWon A boolean indicating whether there was a successful, winning solver.
function metacall(
UserOperation calldata userOp, // set by user
SolverOperation[] calldata solverOps, // supplied by ops relay
DAppOperation calldata dAppOp // supplied by front end via atlas SDK
DAppOperation calldata dAppOp, // supplied by front end via atlas SDK
address gasRefundBeneficiary // address(0) = msg.sender
)
external
payable
Expand Down Expand Up @@ -97,7 +99,9 @@ contract Atlas is Escrow, Factory {
try this.execute(_dConfig, userOp, solverOps, _executionEnvironment, _bundler, dAppOp.userOpHash, _isSimulation)
returns (Context memory ctx) {
// Gas Refund to sender only if execution is successful
(uint256 _ethPaidToBundler, uint256 _netGasSurcharge) = _settle(ctx, _dConfig.solverGasLimit);
(uint256 _ethPaidToBundler, uint256 _netGasSurcharge) = _settle(
ctx, _dConfig.solverGasLimit, gasRefundBeneficiary != address(0) ? gasRefundBeneficiary : msg.sender
);

auctionWon = ctx.solverSuccessful;
emit MetacallResult(
Expand Down
10 changes: 8 additions & 2 deletions src/contracts/atlas/GasAccounting.sol
Original file line number Diff line number Diff line change
Expand Up @@ -414,11 +414,13 @@ abstract contract GasAccounting is SafetyLocks {
/// refund for gas spent, and Atlas' gas surcharge is updated.
/// @param ctx Context struct containing relevant context information for the Atlas auction.
/// @param solverGasLimit The dApp's maximum gas limit for a solver, as set in the DAppConfig.
/// @param gasRefundBeneficiary The address to receive the gas refund.
/// @return claimsPaidToBundler The amount of ETH paid to the bundler in this function.
/// @return netAtlasGasSurcharge The net gas surcharge of the metacall, taken by Atlas.
function _settle(
Context memory ctx,
uint256 solverGasLimit
uint256 solverGasLimit,
address gasRefundBeneficiary
)
internal
returns (uint256 claimsPaidToBundler, uint256 netAtlasGasSurcharge)
Expand Down Expand Up @@ -474,13 +476,17 @@ abstract contract GasAccounting is SafetyLocks {
}
claimsPaidToBundler -= _currentDeficit;
} else {
if (_winningSolver == ctx.bundler) {
_winningSolver = gasRefundBeneficiary;
}

_credit(_winningSolver, _amountSolverReceives - _amountSolverPays, _adjustedClaims);
}

// Set lock to FullyLocked to prevent any reentrancy possibility
_setLockPhase(uint8(ExecutionPhase.FullyLocked));

if (claimsPaidToBundler != 0) SafeTransferLib.safeTransferETH(ctx.bundler, claimsPaidToBundler);
if (claimsPaidToBundler != 0) SafeTransferLib.safeTransferETH(gasRefundBeneficiary, claimsPaidToBundler);

return (claimsPaidToBundler, netAtlasGasSurcharge);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ contract FastLaneOnlineOuter is SolverGateway {

// Atlas call
(bool _success,) = ATLAS.call{ value: msg.value, gas: _metacallGasLimit(_gasReserved, userOp.gas, gasleft()) }(
abi.encodeCall(IAtlas.metacall, (userOp, _solverOps, _dAppOp))
abi.encodeCall(IAtlas.metacall, (userOp, _solverOps, _dAppOp, address(0)))
);

// Revert if the metacall failed - neither solvers nor baseline call fulfilled swap intent
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ contract GeneralizedBackrunUserBundler is DAppControl {
SolverOperation[] memory _solverOps = _getSolverOps(solverOpHashes);

(bool _success, bytes memory _data) =
ATLAS.call{ value: msg.value }(abi.encodeCall(IAtlas.metacall, (userOp, _solverOps, _dAppOp)));
ATLAS.call{ value: msg.value }(abi.encodeCall(IAtlas.metacall, (userOp, _solverOps, _dAppOp, address(0))));
if (!_success) {
assembly {
revert(add(_data, 32), mload(_data))
Expand Down
2 changes: 1 addition & 1 deletion src/contracts/helpers/Simulator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ contract Simulator is AtlasErrors {
payable
{
if (msg.sender != address(this)) revert InvalidEntryFunction();
if (!IAtlas(atlas).metacall{ value: msg.value }(userOp, solverOps, dAppOp)) {
if (!IAtlas(atlas).metacall{ value: msg.value }(userOp, solverOps, dAppOp, address(0))) {
revert NoAuctionWinner(); // should be unreachable
}
revert SimulationPassed();
Expand Down
3 changes: 2 additions & 1 deletion src/contracts/interfaces/IAtlas.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ interface IAtlas {
function metacall(
UserOperation calldata userOp,
SolverOperation[] calldata solverOps,
DAppOperation calldata dAppOp
DAppOperation calldata dAppOp,
address gasRefundBeneficiary
)
external
payable
Expand Down
4 changes: 2 additions & 2 deletions test/Accounting.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ contract AccountingTest is BaseTest {
SolverOperation[] memory solverOps = _setupBorrowRepayTestUsingBasicSwapIntent(address(honestSolver));

vm.startPrank(userEOA);
atlas.metacall{ value: 0 }({ userOp: userOp, solverOps: solverOps, dAppOp: dAppOp });
atlas.metacall{ value: 0 }({ userOp: userOp, solverOps: solverOps, dAppOp: dAppOp, gasRefundBeneficiary: address(0) });
vm.stopPrank();

// console.log("\nAFTER METACALL");
Expand All @@ -90,7 +90,7 @@ contract AccountingTest is BaseTest {
SolverOperation[] memory solverOps = _setupBorrowRepayTestUsingBasicSwapIntent(address(evilSolver));

vm.startPrank(userEOA);
atlas.metacall{ value: 0 }({ userOp: userOp, solverOps: solverOps, dAppOp: dAppOp });
atlas.metacall{ value: 0 }({ userOp: userOp, solverOps: solverOps, dAppOp: dAppOp, gasRefundBeneficiary: address(0) });
vm.stopPrank();
}

Expand Down
10 changes: 5 additions & 5 deletions test/Escrow.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ contract EscrowTest is BaseTest {
DAppOperation memory dappOp = validDAppOperation(userOp, solverOps).build();

vm.prank(userEOA);
bool auctionWon = atlas.metacall(userOp, solverOps, dappOp);
bool auctionWon = atlas.metacall(userOp, solverOps, dappOp, address(0));

assertLe(dAppControl.userOpGasLeft(), userGasLim, "userOpGasLeft should be <= userGasLim");
assertTrue(auctionWon, "2nd auction should have been won");
Expand Down Expand Up @@ -239,7 +239,7 @@ contract EscrowTest is BaseTest {
// Send msg.value so it must be sent back, testing the upper bound of remaining gas for graceful return
deal(userEOA, 1 ether);
vm.prank(userEOA);
bool auctionWon = atlas.metacall{gas: metacallGasLim, value: 1 ether}(userOp, solverOps, dappOp);
bool auctionWon = atlas.metacall{gas: metacallGasLim, value: 1 ether}(userOp, solverOps, dappOp, address(0));
assertEq(auctionWon, false, "call should not revert but auction should not be won either");
}

Expand Down Expand Up @@ -332,7 +332,7 @@ contract EscrowTest is BaseTest {
}

vm.prank(userEOA);
bool auctionWon = atlas.metacall(userOp, solverOps, dappOp);
bool auctionWon = atlas.metacall(userOp, solverOps, dappOp, address(0));

if (!revertExpected) {
assertTrue(auctionWon, "auction should have been won");
Expand Down Expand Up @@ -558,7 +558,7 @@ contract EscrowTest is BaseTest {
DAppOperation memory dappOp = validDAppOperation(userOp, solverOps).build();

vm.prank(userEOA);
(bool success,) = address(atlas).call(abi.encodeCall(atlas.metacall, (userOp, solverOps, dappOp)));
(bool success,) = address(atlas).call(abi.encodeCall(atlas.metacall, (userOp, solverOps, dappOp, address(0))));
assertTrue(success, "metacall should have succeeded");
}

Expand Down Expand Up @@ -670,7 +670,7 @@ contract EscrowTest is BaseTest {

vm.prank(userEOA);
if (metacallShouldRevert) vm.expectRevert(); // Metacall should revert, the reason isn't important, we're only checking the event
atlas.metacall(userOp, solverOps, dappOp);
atlas.metacall(userOp, solverOps, dappOp, address(0));
}
}

Expand Down
2 changes: 1 addition & 1 deletion test/ExPost.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ contract ExPostTest is BaseTest {
// uint256 solverTwoAtlEthBalance = atlas.balanceOf(solverTwoEOA);

(bool success,) =
address(atlas).call(abi.encodeCall(atlas.metacall, (userOp, solverOps, dAppOp)));
address(atlas).call(abi.encodeCall(atlas.metacall, (userOp, solverOps, dAppOp, address(0))));

if (success) {
console.log("success!");
Expand Down
6 changes: 3 additions & 3 deletions test/FlashLoan.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ contract FlashLoanTest is BaseTest {
result
);
vm.expectRevert();
atlas.metacall({ userOp: userOp, solverOps: solverOps, dAppOp: dAppOp });
atlas.metacall({ userOp: userOp, solverOps: solverOps, dAppOp: dAppOp, gasRefundBeneficiary: address(0) });
vm.stopPrank();

// now try it again with a valid solverOp - but dont fully pay back
Expand Down Expand Up @@ -181,7 +181,7 @@ contract FlashLoanTest is BaseTest {
result
);
vm.expectRevert();
atlas.metacall({ userOp: userOp, solverOps: solverOps, dAppOp: dAppOp });
atlas.metacall({ userOp: userOp, solverOps: solverOps, dAppOp: dAppOp, gasRefundBeneficiary: address(0) });
vm.stopPrank();

// final try, should be successful with full payback
Expand Down Expand Up @@ -246,7 +246,7 @@ contract FlashLoanTest is BaseTest {
true,
result
);
atlas.metacall({ userOp: userOp, solverOps: solverOps, dAppOp: dAppOp });
atlas.metacall({ userOp: userOp, solverOps: solverOps, dAppOp: dAppOp, gasRefundBeneficiary: address(0) });
vm.stopPrank();

// atlas 2e beginning bal + 1e from solver +100e eth from user = 103e atlas total
Expand Down
2 changes: 1 addition & 1 deletion test/GasAccounting.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ contract MockGasAccounting is TestAtlas, BaseTest {
}

function settle(Context memory ctx) external returns (uint256, uint256) {
return _settle(ctx, MOCK_SOLVER_GAS_LIMIT);
return _settle(ctx, MOCK_SOLVER_GAS_LIMIT, msg.sender);
}

function adjustAccountingForFees(Context memory ctx)
Expand Down
2 changes: 1 addition & 1 deletion test/MainTest.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,7 @@ contract MainTest is BaseTest {

vm.startPrank(userEOA);
IERC20(TOKEN_ONE).approve(address(atlas), type(uint256).max);
atlas.metacall(userOp, solverOps, dAppOp);
atlas.metacall(userOp, solverOps, dAppOp, address(0));
vm.stopPrank();

// Execution environment should exist now
Expand Down
4 changes: 2 additions & 2 deletions test/OEV.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ contract OEVTest is BaseTest {

// Should Fail
vm.prank(userEOA);
atlas.metacall({ userOp: userOp, solverOps: solverOps, dAppOp: dAppOp });
atlas.metacall({ userOp: userOp, solverOps: solverOps, dAppOp: dAppOp, gasRefundBeneficiary: address(0) });

assertEq(uint(chainlinkAtlasWrapper.latestAnswer()), uint(AggregatorV2V3Interface(chainlinkETHUSD).latestAnswer()), "Metacall unexpectedly succeeded");

Expand All @@ -176,7 +176,7 @@ contract OEVTest is BaseTest {

// Should Succeed
vm.prank(userEOA);
atlas.metacall({ userOp: userOp, solverOps: solverOps, dAppOp: dAppOp });
atlas.metacall({ userOp: userOp, solverOps: solverOps, dAppOp: dAppOp, gasRefundBeneficiary: address(0) });

console.log("Metacall Gas Cost:", gasLeftBefore - gasleft());

Expand Down
2 changes: 1 addition & 1 deletion test/OEValt.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ contract OEVTest is BaseTest {

// Should Succeed
vm.prank(transmitter);
atlas.metacall({ userOp: userOp, solverOps: solverOps, dAppOp: dAppOp });
atlas.metacall({ userOp: userOp, solverOps: solverOps, dAppOp: dAppOp, gasRefundBeneficiary: address(0) });

assertEq(uint(chainlinkAtlasWrapper.latestAnswer()), targetOracleAnswer, "Wrapper did not update as expected");
assertTrue(uint(chainlinkAtlasWrapper.latestAnswer()) != uint(IChainlinkFeed(chainlinkETHUSD).latestAnswer()), "Wrapper and base feed should report different answers");
Expand Down
19 changes: 7 additions & 12 deletions test/SwapIntent.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,10 @@ contract SwapIntentTest is BaseTest {
UserCondition userCondition = new UserCondition();

Condition[] memory conditions = new Condition[](2);
conditions[0] = Condition({
antecedent: address(userCondition),
context: abi.encodeCall(UserCondition.isLessThanFive, 3)
});
conditions[1] = Condition({
antecedent: address(userCondition),
context: abi.encodeCall(UserCondition.isLessThanFive, 4)
});
conditions[0] =
Condition({ antecedent: address(userCondition), context: abi.encodeCall(UserCondition.isLessThanFive, 3) });
conditions[1] =
Condition({ antecedent: address(userCondition), context: abi.encodeCall(UserCondition.isLessThanFive, 4) });

SwapIntent memory swapIntent = SwapIntent({
tokenUserBuys: DAI_ADDRESS,
Expand Down Expand Up @@ -124,8 +120,7 @@ contract SwapIntentTest is BaseTest {
// userOp.signature = abi.encodePacked(sig.r, sig.s, sig.v);

// Build solver calldata (function selector on solver contract and its params)
bytes memory solverOpData =
abi.encodeCall(SimpleRFQSolver.fulfillRFQ, (swapIntent, executionEnvironment));
bytes memory solverOpData = abi.encodeCall(SimpleRFQSolver.fulfillRFQ, (swapIntent, executionEnvironment));

// Builds the SolverOperation
solverOps[0] = txBuilder.buildSolverOperation({
Expand Down Expand Up @@ -176,7 +171,7 @@ contract SwapIntentTest is BaseTest {

uint256 gasLeftBefore = gasleft();

atlas.metacall({ userOp: userOp, solverOps: solverOps, dAppOp: dAppOp });
atlas.metacall({ userOp: userOp, solverOps: solverOps, dAppOp: dAppOp, gasRefundBeneficiary: address(0) });

console.log("Metacall Gas Cost:", gasLeftBefore - gasleft());
vm.stopPrank();
Expand Down Expand Up @@ -304,7 +299,7 @@ contract SwapIntentTest is BaseTest {
assertEq(DAI.balanceOf(address(uniswapSolver)), 0, "Solver has DAI before metacall");

// NOTE: Should metacall return something? Feels like a lot of data you might want to know about the tx
atlas.metacall({ userOp: userOp, solverOps: solverOps, dAppOp: dAppOp });
atlas.metacall({ userOp: userOp, solverOps: solverOps, dAppOp: dAppOp, gasRefundBeneficiary: address(0) });
vm.stopPrank();

console.log("\nAFTER METACALL");
Expand Down
2 changes: 1 addition & 1 deletion test/SwapIntentInvertBid.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ contract SwapIntentTest is BaseTest {
uint256 gasLeftBefore = gasleft();

vm.startPrank(userEOA);
atlas.metacall({ userOp: userOp, solverOps: solverOps, dAppOp: dAppOp });
atlas.metacall({ userOp: userOp, solverOps: solverOps, dAppOp: dAppOp, gasRefundBeneficiary: address(0) });

console.log("Metacall Gas Cost:", gasLeftBefore - gasleft());
vm.stopPrank();
Expand Down
2 changes: 1 addition & 1 deletion test/TrebleSwap.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ contract TrebleSwapTest is BaseTest {

// Do the actual metacall
vm.prank(userEOA);
bool auctionWon = atlas.metacall{ value: msgValue }(args.userOp, args.solverOps, args.dAppOp);
bool auctionWon = atlas.metacall{ value: msgValue }(args.userOp, args.solverOps, args.dAppOp, address(0));

// Estimate gas surcharge Atlas should have taken
txGasUsed = estAtlasGasSurcharge - gasleft();
Expand Down
2 changes: 1 addition & 1 deletion test/V2RewardDAppControl.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ contract V2RewardDAppControlTest is BaseTest {
console.log("User DAI balance", DAI.balanceOf(userEOA));

vm.prank(governanceEOA);
atlas.metacall({ userOp: userOp, solverOps: solverOps, dAppOp: dAppOp });
atlas.metacall({ userOp: userOp, solverOps: solverOps, dAppOp: dAppOp, gasRefundBeneficiary: address(0) });

console.log("\nAFTER METACALL");
console.log("User WETH balance", WETH.balanceOf(userEOA));
Expand Down

0 comments on commit b212c99

Please sign in to comment.