diff --git a/src/contracts/atlas/AtlETH.sol b/src/contracts/atlas/AtlETH.sol index 60bfb9ee..22a40fad 100644 --- a/src/contracts/atlas/AtlETH.sol +++ b/src/contracts/atlas/AtlETH.sol @@ -80,7 +80,8 @@ abstract contract AtlETH is Permit69 { /// @dev Burns the specified amount of atlETH tokens from the caller's balance and transfers the equivalent amount /// of ETH to the caller. /// @param amount The amount of atlETH tokens to redeem for ETH. - function withdraw(uint256 amount) external onlyWhenUnlocked { + function withdraw(uint256 amount) external { + _checkIfUnlocked(); _burn(msg.sender, amount); SafeTransferLib.safeTransferETH(msg.sender, amount); } @@ -95,7 +96,7 @@ abstract contract AtlETH is Permit69 { function _mint(address to, uint256 amount) internal { S_totalSupply += amount; s_balanceOf[to].balance += SafeCast.toUint112(amount); - emit Transfer(address(0), to, amount); + emit Mint(to, amount); } /// @notice Burns atlETH tokens from the specified account. @@ -104,7 +105,7 @@ abstract contract AtlETH is Permit69 { function _burn(address from, uint256 amount) internal { _deduct(from, amount); S_totalSupply -= amount; - emit Transfer(from, address(0), amount); + emit Burn(from, amount); } /// @notice Deducts atlETH tokens from the specified account. @@ -162,13 +163,15 @@ abstract contract AtlETH is Permit69 { /// held by the sender. Unbonding AtlETH tokens can still be used by solvers while the unbonding /// process is ongoing, but adjustments may be made at withdrawal to ensure solvency. /// @param amount The amount of AtlETH tokens to unbond. - function unbond(uint256 amount) external onlyWhenUnlocked { + function unbond(uint256 amount) external { + _checkIfUnlocked(); _unbond(msg.sender, amount); } /// @notice Redeems the specified amount of AtlETH tokens for withdrawal. /// @param amount The amount of AtlETH tokens to redeem for withdrawal. - function redeem(uint256 amount) external onlyWhenUnlocked { + function redeem(uint256 amount) external { + _checkIfUnlocked(); _redeem(msg.sender, amount); } @@ -289,9 +292,7 @@ abstract contract AtlETH is Permit69 { emit SurchargeRecipientTransferred(msg.sender); } - /// @notice Blocks certain AtlETH functions during a metacall transaction. - modifier onlyWhenUnlocked() { + function _checkIfUnlocked() internal view { if (!_isUnlocked()) revert InvalidLockState(); - _; } } diff --git a/src/contracts/atlas/Atlas.sol b/src/contracts/atlas/Atlas.sol index 5635d17a..5a65d25f 100644 --- a/src/contracts/atlas/Atlas.sol +++ b/src/contracts/atlas/Atlas.sol @@ -322,13 +322,9 @@ contract Atlas is Escrow, Factory { /// @param callConfig The CallConfig of the current metacall tx. function _handleErrors(bytes memory revertData, uint32 callConfig) internal view { bytes4 _errorSwitch = bytes4(revertData); + if (msg.sender == SIMULATOR) { - // Simulation - if (_errorSwitch == PreOpsSimFail.selector) { - revert PreOpsSimFail(); - } else if (_errorSwitch == UserOpSimFail.selector) { - revert UserOpSimFail(); - } else if (_errorSwitch == SolverSimFail.selector) { + if (_errorSwitch == SolverSimFail.selector) { // Expects revertData in form [bytes4, uint256] uint256 _solverOutcomeResult; assembly { @@ -336,20 +332,22 @@ contract Atlas is Escrow, Factory { _solverOutcomeResult := mload(add(dataLocation, sub(mload(revertData), 32))) } revert SolverSimFail(_solverOutcomeResult); - } else if (_errorSwitch == AllocateValueSimFail.selector) { - revert AllocateValueSimFail(); - } else if (_errorSwitch == PostOpsSimFail.selector) { - revert PostOpsSimFail(); + } else if ( + _errorSwitch == PreOpsSimFail.selector || _errorSwitch == UserOpSimFail.selector + || _errorSwitch == AllocateValueSimFail.selector || _errorSwitch == PostOpsSimFail.selector + ) { + assembly { + mstore(0, _errorSwitch) + revert(0, 4) + } } } - if (_errorSwitch == UserNotFulfilled.selector) { - revert UserNotFulfilled(); - } - // If allowReuseUserOps = true, it reverts and bubbles up whatever the error - // was that it caught. This is to prevent storing the nonce as used so the userOp - // can be reused. Otherwise, the whole metacall doesn't revert but the inner + + // NOTE: If error was UserNotFulfilled, we revert and bubble up the error. + // For any other error, we only bubble up the revert if allowReuseUserOps = true. This is to prevent storing the + // nonce as used so the userOp can be reused. Otherwise, the whole metacall doesn't revert but the inner // execute() does so, no operation changes are persisted. - if (callConfig.allowsReuseUserOps()) { + if (_errorSwitch == UserNotFulfilled.selector || callConfig.allowsReuseUserOps()) { assembly { mstore(0, _errorSwitch) revert(0, 4) diff --git a/src/contracts/atlas/GasAccounting.sol b/src/contracts/atlas/GasAccounting.sol index 43e0c7ec..cfe149bd 100644 --- a/src/contracts/atlas/GasAccounting.sol +++ b/src/contracts/atlas/GasAccounting.sol @@ -197,7 +197,6 @@ abstract contract GasAccounting is SafetyLocks { internal returns (uint256 deficit) { - if (amount > type(uint112).max) revert ValueTooLarge(); uint112 _amt = SafeCast.toUint112(amount); EscrowAccountAccessData memory _aData = S_accessData[owner]; @@ -248,12 +247,10 @@ abstract contract GasAccounting is SafetyLocks { /// @param amount The amount by which to increase the owner's bonded balance. /// @param gasValueUsed The ETH value of gas used in the SolverOperation. function _credit(address owner, uint256 amount, uint256 gasValueUsed) internal { - uint112 _amt = SafeCast.toUint112(amount); - EscrowAccountAccessData memory _aData = S_accessData[owner]; _aData.lastAccessedBlock = uint32(block.number); - _aData.bonded += _amt; + _aData.bonded += SafeCast.toUint112(amount); S_bondedTotalSupply += amount; diff --git a/src/contracts/types/AtlasErrors.sol b/src/contracts/types/AtlasErrors.sol index 606f7239..e3046bdb 100644 --- a/src/contracts/types/AtlasErrors.sol +++ b/src/contracts/types/AtlasErrors.sol @@ -67,17 +67,8 @@ contract AtlasErrors { error InvalidEscrowDuration(); // AtlETH - error InsufficientUnbondedBalance(uint256 balance, uint256 requested); - error InsufficientBondedBalance(uint256 balance, uint256 requested); - error PermitDeadlineExpired(); - error InvalidSigner(); error EscrowLockActive(); - error InsufficientWithdrawableBalance(uint256 balance, uint256 requested); - error InsufficientAvailableBalance(uint256 balance, uint256 requested); - error InsufficientSurchargeBalance(uint256 balance, uint256 requested); error InsufficientBalanceForDeduction(uint256 balance, uint256 requested); - error ValueTooLarge(); - error BidTooHigh(uint256 indexInSolverOps, uint256 bidAmount); // DAppIntegration error OnlyGovernance(); diff --git a/src/contracts/types/AtlasEvents.sol b/src/contracts/types/AtlasEvents.sol index 54093db8..8e501540 100644 --- a/src/contracts/types/AtlasEvents.sol +++ b/src/contracts/types/AtlasEvents.sol @@ -16,8 +16,8 @@ contract AtlasEvents { event Bond(address indexed owner, uint256 amount); event Unbond(address indexed owner, uint256 amount, uint256 earliestAvailable); event Redeem(address indexed owner, uint256 amount); - event Transfer(address indexed from, address indexed to, uint256 amount); - event Approval(address indexed owner, address indexed spender, uint256 amount); + event Mint(address indexed to, uint256 amount); + event Burn(address indexed from, uint256 amount); // Escrow events event SolverTxResult( @@ -35,9 +35,9 @@ contract AtlasEvents { event ExecutionEnvironmentCreated(address indexed user, address indexed executionEnvironment); // Surcharge events - event SurchargeWithdrawn(address to, uint256 amount); - event SurchargeRecipientTransferStarted(address currentRecipient, address newRecipient); - event SurchargeRecipientTransferred(address newRecipient); + event SurchargeWithdrawn(address indexed to, uint256 amount); + event SurchargeRecipientTransferStarted(address indexed currentRecipient, address indexed newRecipient); + event SurchargeRecipientTransferred(address indexed newRecipient); // DAppControl events event GovernanceTransferStarted(address indexed previousGovernance, address indexed newGovernance); diff --git a/test/AtlETH.t.sol b/test/AtlETH.t.sol index 9c8a8aee..df30ead6 100644 --- a/test/AtlETH.t.sol +++ b/test/AtlETH.t.sol @@ -18,7 +18,7 @@ contract AtlETHTest is BaseTest { deal(userEOA, 1e18); vm.prank(userEOA); vm.expectEmit(true, true, false, true); - emit AtlasEvents.Transfer(address(0), userEOA, 1e18); + emit AtlasEvents.Mint(userEOA, 1e18); atlas.deposit{ value: 1e18 }(); assertEq(atlas.balanceOf(userEOA), 1e18, "user's atlETH balance should be 1 ETH"); @@ -32,7 +32,7 @@ contract AtlETHTest is BaseTest { vm.prank(solverOneEOA); vm.expectEmit(true, true, false, true); - emit AtlasEvents.Transfer(solverOneEOA, address(0), 1e18); + emit AtlasEvents.Burn(solverOneEOA, 1e18); atlas.withdraw(1e18); assertEq(atlas.balanceOf(solverOneEOA), 0, "solverOne's atlETH balance should be 0"); @@ -118,7 +118,7 @@ contract AtlETHTest is BaseTest { vm.prank(userEOA); vm.expectEmit(true, true, false, true); - emit AtlasEvents.Transfer(address(0), userEOA, 1e18); + emit AtlasEvents.Mint(userEOA, 1e18); vm.expectEmit(true, true, false, true); emit AtlasEvents.Bond(userEOA, 1e18); atlas.depositAndBond{ value: 1e18 }(1e18); diff --git a/test/GasAccounting.t.sol b/test/GasAccounting.t.sol index 430471dc..3423a502 100644 --- a/test/GasAccounting.t.sol +++ b/test/GasAccounting.t.sol @@ -914,7 +914,7 @@ contract GasAccountingTest is AtlasConstants, BaseTest { uint256 bondedTotalSupplyBefore = mockGasAccounting.bondedTotalSupply(); uint256 depositsBefore = mockGasAccounting.deposits(); (uint112 unbondingBefore,) = mockGasAccounting._balanceOf(solverOp.from); - vm.expectRevert(AtlasErrors.ValueTooLarge.selector); + vm.expectRevert(abi.encodeWithSelector(SafeCast.SafeCastOverflowedUintDowncast.selector, 112, assignedAmount)); mockGasAccounting.assign(solverOp.from, assignedAmount, assignedAmount, true); // Check assign reverted with overflow, and accounting values did not change