Skip to content

Commit

Permalink
refactor: packed MemoryUserOp
Browse files Browse the repository at this point in the history
  • Loading branch information
pegahcarter committed Mar 12, 2024
1 parent 7af70c8 commit 46a3138
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 41 deletions.
34 changes: 17 additions & 17 deletions contracts/core/EntryPoint.sol
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard,
)
internal
returns
(uint256 collected) {
(uint128 collected) {
uint256 preGas = gasleft();
bytes memory context = getMemoryBytesFromOffset(opInfo.contextOffset);
bool success;
Expand Down Expand Up @@ -284,15 +284,15 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard,
*/
struct MemoryUserOp {
address sender;
uint256 nonce;
uint256 verificationGasLimit;
uint256 callGasLimit;
uint256 paymasterVerificationGasLimit;
uint256 paymasterPostOpGasLimit;
uint256 preVerificationGas;
address paymaster;
uint256 maxFeePerGas;
uint256 maxPriorityFeePerGas;
uint256 nonce;
uint128 paymasterVerificationGasLimit;
uint128 paymasterPostOpGasLimit;
uint128 verificationGasLimit;
uint128 callGasLimit;
uint128 maxFeePerGas;
uint128 maxPriorityFeePerGas;
uint128 preVerificationGas;
}

struct UserOpInfo {
Expand All @@ -315,7 +315,7 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard,
bytes memory callData,
UserOpInfo memory opInfo,
bytes calldata context
) external returns (uint256 actualGasCost) {
) external returns (uint128 actualGasCost) {
uint256 preGas = gasleft();
require(msg.sender == address(this), "AA92 internal call only");
MemoryUserOp memory mUserOp = opInfo.mUserOp;
Expand Down Expand Up @@ -533,7 +533,7 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard,
revert FailedOp(opIndex, "AA31 paymaster deposit too low");
}
paymasterInfo.deposit = deposit - requiredPreFund;
uint256 pmVerificationGasLimit = mUserOp.paymasterVerificationGasLimit;
uint128 pmVerificationGasLimit = mUserOp.paymasterVerificationGasLimit;
try
IPaymaster(paymaster).validatePaymasterUserOp{gas: pmVerificationGasLimit}(
op,
Expand Down Expand Up @@ -686,13 +686,13 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard,
IPaymaster.PostOpMode mode,
UserOpInfo memory opInfo,
bytes memory context,
uint256 actualGas
) private returns (uint256 actualGasCost) {
uint128 actualGas
) private returns (uint128 actualGasCost) {
uint256 preGas = gasleft();
unchecked {
address refundAddress;
MemoryUserOp memory mUserOp = opInfo.mUserOp;
uint256 gasPrice = getUserOpGasPrice(mUserOp);
uint128 gasPrice = getUserOpGasPrice(mUserOp);

address paymaster = mUserOp.paymaster;
if (paymaster == address(0)) {
Expand Down Expand Up @@ -756,10 +756,10 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard,
*/
function getUserOpGasPrice(
MemoryUserOp memory mUserOp
) internal view returns (uint256) {
) internal view returns (uint128) {
unchecked {
uint256 maxFeePerGas = mUserOp.maxFeePerGas;
uint256 maxPriorityFeePerGas = mUserOp.maxPriorityFeePerGas;
uint128 maxFeePerGas = mUserOp.maxFeePerGas;
uint128 maxPriorityFeePerGas = mUserOp.maxPriorityFeePerGas;
if (maxFeePerGas == maxPriorityFeePerGas) {
//legacy mode (for networks that don't support basefee opcode)
return maxFeePerGas;
Expand Down
39 changes: 20 additions & 19 deletions contracts/core/UserOperationLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ library UserOperationLib {
uint256 public constant PAYMASTER_VALIDATION_GAS_OFFSET = 20;
uint256 public constant PAYMASTER_POSTOP_GAS_OFFSET = 36;
uint256 public constant PAYMASTER_DATA_OFFSET = 52;
uint256 public constant LOW_UINT128_MASK = uint256(type(uint128).max);
/**
* Get sender from user operation data.
* @param userOp - The user operation data.
Expand All @@ -36,9 +37,9 @@ library UserOperationLib {
*/
function gasPrice(
PackedUserOperation calldata userOp
) internal view returns (uint256) {
) internal view returns (uint128) {
unchecked {
(uint256 maxPriorityFeePerGas, uint256 maxFeePerGas) = unpackUints(userOp.gasFees);
(uint128 maxPriorityFeePerGas, uint128 maxFeePerGas) = unpackUints(userOp.gasFees);
if (maxFeePerGas == maxPriorityFeePerGas) {
//legacy mode (for networks that don't support basefee opcode)
return maxFeePerGas;
Expand All @@ -56,70 +57,70 @@ library UserOperationLib {
) internal pure returns (bytes memory ret) {
address sender = getSender(userOp);
uint256 nonce = userOp.nonce;
bytes32 hashPaymasterAndData = calldataKeccak(userOp.paymasterAndData);
bytes32 hashInitCode = calldataKeccak(userOp.initCode);
bytes32 hashCallData = calldataKeccak(userOp.callData);
bytes32 accountGasLimits = userOp.accountGasLimits;
uint256 preVerificationGas = userOp.preVerificationGas;
bytes32 gasFees = userOp.gasFees;
bytes32 hashPaymasterAndData = calldataKeccak(userOp.paymasterAndData);
uint128 preVerificationGas = userOp.preVerificationGas;

return abi.encode(
sender, nonce,
hashPaymasterAndData,
hashInitCode, hashCallData,
accountGasLimits, preVerificationGas, gasFees,
hashPaymasterAndData
accountGasLimits, gasFees, preVerificationGas
);
}

function unpackUints(
bytes32 packed
) internal pure returns (uint256 high128, uint256 low128) {
return (uint128(bytes16(packed)), uint128(uint256(packed)));
) internal pure returns (uint128, uint128) {
return (unpackHigh128(packed), unpackLow128(packed));
}

//unpack just the high 128-bits from a packed value
function unpackHigh128(bytes32 packed) internal pure returns (uint256) {
return uint256(packed) >> 128;
function unpackHigh128(bytes32 packed) internal pure returns (uint128) {
return uint128(uint256(packed) >> 128);
}

// unpack just the low 128-bits from a packed value
function unpackLow128(bytes32 packed) internal pure returns (uint256) {
return uint128(uint256(packed));
function unpackLow128(bytes32 packed) internal pure returns (uint128) {
return uint128(uint256(packed) & LOW_UINT128_MASK);
}

function unpackMaxPriorityFeePerGas(PackedUserOperation calldata userOp)
internal pure returns (uint256) {
internal pure returns (uint128) {
return unpackHigh128(userOp.gasFees);
}

function unpackMaxFeePerGas(PackedUserOperation calldata userOp)
internal pure returns (uint256) {
internal pure returns (uint128) {
return unpackLow128(userOp.gasFees);
}

function unpackVerificationGasLimit(PackedUserOperation calldata userOp)
internal pure returns (uint256) {
internal pure returns (uint128) {
return unpackHigh128(userOp.accountGasLimits);
}

function unpackCallGasLimit(PackedUserOperation calldata userOp)
internal pure returns (uint256) {
internal pure returns (uint128) {
return unpackLow128(userOp.accountGasLimits);
}

function unpackPaymasterVerificationGasLimit(PackedUserOperation calldata userOp)
internal pure returns (uint256) {
internal pure returns (uint128) {
return uint128(bytes16(userOp.paymasterAndData[PAYMASTER_VALIDATION_GAS_OFFSET : PAYMASTER_POSTOP_GAS_OFFSET]));
}

function unpackPostOpGasLimit(PackedUserOperation calldata userOp)
internal pure returns (uint256) {
internal pure returns (uint128) {
return uint128(bytes16(userOp.paymasterAndData[PAYMASTER_POSTOP_GAS_OFFSET : PAYMASTER_DATA_OFFSET]));
}

function unpackPaymasterStaticFields(
bytes calldata paymasterAndData
) internal pure returns (address paymaster, uint256 validationGasLimit, uint256 postOpGasLimit) {
) internal pure returns (address paymaster, uint128 validationGasLimit, uint128 postOpGasLimit) {
return (
address(bytes20(paymasterAndData[: PAYMASTER_VALIDATION_GAS_OFFSET])),
uint128(bytes16(paymasterAndData[PAYMASTER_VALIDATION_GAS_OFFSET : PAYMASTER_POSTOP_GAS_OFFSET])),
Expand Down
10 changes: 5 additions & 5 deletions contracts/interfaces/PackedUserOperation.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,24 @@ pragma solidity >=0.7.5;
* User Operation struct
* @param sender - The sender account of this request.
* @param nonce - Unique value the sender uses to verify it is not a replay.
* @param paymasterAndData - If set, this field holds the paymaster address, verification gas limit, postOp gas limit and paymaster-specific extra data
* The paymaster will pay for the transaction instead of the sender.
* @param initCode - If set, the account contract will be created by this constructor/
* @param callData - The method call to execute on this account.
* @param accountGasLimits - Packed gas limits for validateUserOp and gas limit passed to the callData method call.
* @param gasFees - packed gas fields maxPriorityFeePerGas and maxFeePerGas - Same as EIP-1559 gas parameters.
* @param preVerificationGas - Gas not calculated by the handleOps method, but added to the gas paid.
* Covers batch overhead.
* @param gasFees - packed gas fields maxPriorityFeePerGas and maxFeePerGas - Same as EIP-1559 gas parameters.
* @param paymasterAndData - If set, this field holds the paymaster address, verification gas limit, postOp gas limit and paymaster-specific extra data
* The paymaster will pay for the transaction instead of the sender.
* @param signature - Sender-verified signature over the entire request, the EntryPoint address and the chain ID.
*/
struct PackedUserOperation {
address sender;
uint256 nonce;
bytes paymasterAndData;
bytes initCode;
bytes callData;
bytes32 accountGasLimits;
uint256 preVerificationGas;
bytes32 gasFees;
bytes paymasterAndData;
uint128 preVerificationGas;
bytes signature;
}

0 comments on commit 46a3138

Please sign in to comment.