Skip to content

Commit

Permalink
Merge branch 'develop' into postOp-gas-price
Browse files Browse the repository at this point in the history
  • Loading branch information
drortirosh committed Jan 8, 2024
2 parents b7902f0 + e8896ac commit 8faf84a
Show file tree
Hide file tree
Showing 46 changed files with 535 additions and 428 deletions.
6 changes: 3 additions & 3 deletions contracts/core/BaseAccount.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import "./UserOperationLib.sol";
* Specific account implementation should inherit it and provide the account-specific logic.
*/
abstract contract BaseAccount is IAccount {
using UserOperationLib for UserOperation;
using UserOperationLib for PackedUserOperation;

/**
* Return value in case of signature failure, with no time-range.
Expand Down Expand Up @@ -48,7 +48,7 @@ abstract contract BaseAccount is IAccount {
* to pay for the user operation.
*/
function validateUserOp(
UserOperation calldata userOp,
PackedUserOperation calldata userOp,
bytes32 userOpHash,
uint256 missingAccountFunds
) external virtual override returns (uint256 validationData) {
Expand Down Expand Up @@ -83,7 +83,7 @@ abstract contract BaseAccount is IAccount {
* Note that the validation code cannot use block.timestamp (or block.number) directly.
*/
function _validateSignature(
UserOperation calldata userOp,
PackedUserOperation calldata userOp,
bytes32 userOpHash
) internal virtual returns (uint256 validationData);

Expand Down
10 changes: 7 additions & 3 deletions contracts/core/BasePaymaster.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import "@openzeppelin/contracts/utils/introspection/IERC165.sol";
import "../interfaces/IPaymaster.sol";
import "../interfaces/IEntryPoint.sol";
import "./Helpers.sol";

import "./UserOperationLib.sol";
/**
* Helper class for creating a paymaster.
* provides helper methods for staking.
Expand All @@ -17,6 +17,10 @@ import "./Helpers.sol";
abstract contract BasePaymaster is IPaymaster, Ownable {
IEntryPoint public immutable entryPoint;

uint256 internal constant PAYMASTER_VALIDATION_GAS_OFFSET = UserOperationLib.PAYMASTER_VALIDATION_GAS_OFFSET;
uint256 internal constant PAYMASTER_POSTOP_GAS_OFFSET = UserOperationLib.PAYMASTER_POSTOP_GAS_OFFSET;
uint256 internal constant PAYMASTER_DATA_OFFSET = UserOperationLib.PAYMASTER_DATA_OFFSET;

constructor(IEntryPoint _entryPoint) Ownable(msg.sender) {
_validateEntryPointInterface(_entryPoint);
entryPoint = _entryPoint;
Expand All @@ -30,7 +34,7 @@ abstract contract BasePaymaster is IPaymaster, Ownable {

/// @inheritdoc IPaymaster
function validatePaymasterUserOp(
UserOperation calldata userOp,
PackedUserOperation calldata userOp,
bytes32 userOpHash,
uint256 maxCost
) external override returns (bytes memory context, uint256 validationData) {
Expand All @@ -45,7 +49,7 @@ abstract contract BasePaymaster is IPaymaster, Ownable {
* @param maxCost - The maximum cost of the user operation.
*/
function _validatePaymasterUserOp(
UserOperation calldata userOp,
PackedUserOperation calldata userOp,
bytes32 userOpHash,
uint256 maxCost
) internal virtual returns (bytes memory context, uint256 validationData);
Expand Down
86 changes: 37 additions & 49 deletions contracts/core/EntryPoint.sol
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
*/
contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard, OpenZeppelin.ERC165 {

using UserOperationLib for UserOperation;
using UserOperationLib for PackedUserOperation;

SenderCreator private senderCreator = new SenderCreator();

Expand Down Expand Up @@ -71,7 +71,7 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard,
*/
function _executeUserOp(
uint256 opIndex,
UserOperation calldata userOp,
PackedUserOperation calldata userOp,
UserOpInfo memory opInfo
)
internal
Expand Down Expand Up @@ -141,7 +141,7 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard,

/// @inheritdoc IEntryPoint
function handleOps(
UserOperation[] calldata ops,
PackedUserOperation[] calldata ops,
address payable beneficiary
) public nonReentrant {
uint256 opslen = ops.length;
Expand Down Expand Up @@ -183,7 +183,7 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard,
uint256 totalOps = 0;
for (uint256 i = 0; i < opasLen; i++) {
UserOpsPerAggregator calldata opa = opsPerAggregator[i];
UserOperation[] calldata ops = opa.userOps;
PackedUserOperation[] calldata ops = opa.userOps;
IAggregator aggregator = opa.aggregator;

//address(1) is special marker of "signature error"
Expand All @@ -207,7 +207,7 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard,
uint256 opIndex = 0;
for (uint256 a = 0; a < opasLen; a++) {
UserOpsPerAggregator calldata opa = opsPerAggregator[a];
UserOperation[] calldata ops = opa.userOps;
PackedUserOperation[] calldata ops = opa.userOps;
IAggregator aggregator = opa.aggregator;

uint256 opslen = ops.length;
Expand All @@ -234,7 +234,7 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard,
for (uint256 a = 0; a < opasLen; a++) {
UserOpsPerAggregator calldata opa = opsPerAggregator[a];
emit SignatureAggregatorChanged(address(opa.aggregator));
UserOperation[] calldata ops = opa.userOps;
PackedUserOperation[] calldata ops = opa.userOps;
uint256 opslen = ops.length;

for (uint256 i = 0; i < opslen; i++) {
Expand All @@ -254,8 +254,10 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard,
struct MemoryUserOp {
address sender;
uint256 nonce;
uint256 callGasLimit;
uint256 verificationGasLimit;
uint128 verificationGasLimit;
uint128 callGasLimit;
uint128 paymasterVerificationGasLimit;
uint128 paymasterPostOpGasLimit;
uint256 preVerificationGas;
address paymaster;
uint256 maxFeePerGas;
Expand Down Expand Up @@ -290,7 +292,10 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard,
unchecked {
// handleOps was called with gas limit too low. abort entire bundle.
if (
gasleft() < callGasLimit + mUserOp.verificationGasLimit + 5000
gasleft() <
callGasLimit +
mUserOp.paymasterPostOpGasLimit +
5000
) {
assembly {
mstore(0, INNER_OUT_OF_GAS)
Expand Down Expand Up @@ -325,7 +330,7 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard,

/// @inheritdoc IEntryPoint
function getUserOpHash(
UserOperation calldata userOp
PackedUserOperation calldata userOp
) public view returns (bytes32) {
return
keccak256(abi.encode(userOp.hash(), address(this), block.chainid));
Expand All @@ -337,25 +342,26 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard,
* @param mUserOp - The memory user operation.
*/
function _copyUserOpToMemory(
UserOperation calldata userOp,
PackedUserOperation calldata userOp,
MemoryUserOp memory mUserOp
) internal pure {
mUserOp.sender = userOp.sender;
mUserOp.nonce = userOp.nonce;
mUserOp.callGasLimit = userOp.callGasLimit;
mUserOp.verificationGasLimit = userOp.verificationGasLimit;
(mUserOp.verificationGasLimit, mUserOp.callGasLimit) = UserOperationLib.unpackAccountGasLimits(userOp.accountGasLimits);
mUserOp.preVerificationGas = userOp.preVerificationGas;
mUserOp.maxFeePerGas = userOp.maxFeePerGas;
mUserOp.maxPriorityFeePerGas = userOp.maxPriorityFeePerGas;
bytes calldata paymasterAndData = userOp.paymasterAndData;
if (paymasterAndData.length > 0) {
require(
paymasterAndData.length >= 20,
paymasterAndData.length >= UserOperationLib.PAYMASTER_DATA_OFFSET,
"AA93 invalid paymasterAndData"
);
mUserOp.paymaster = address(bytes20(paymasterAndData[:20]));
(mUserOp.paymaster, mUserOp.paymasterVerificationGasLimit, mUserOp.paymasterPostOpGasLimit) = UserOperationLib.unpackPaymasterStaticFields(paymasterAndData);
} else {
mUserOp.paymaster = address(0);
mUserOp.paymasterVerificationGasLimit = 0;
mUserOp.paymasterPostOpGasLimit = 0;
}
}

Expand All @@ -367,12 +373,10 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard,
MemoryUserOp memory mUserOp
) internal pure returns (uint256 requiredPrefund) {
unchecked {
// When using a Paymaster, the verificationGasLimit is used also to as a limit for the postOp call.
// Our security model might call postOp eventually twice.
uint256 mul = mUserOp.paymaster != address(0) ? 2 : 1;
uint256 requiredGas = mUserOp.callGasLimit +
mUserOp.verificationGasLimit *
mul +
uint256 requiredGas = mUserOp.verificationGasLimit +
mUserOp.callGasLimit +
mUserOp.paymasterVerificationGasLimit +
mUserOp.paymasterPostOpGasLimit +
mUserOp.preVerificationGas;

requiredPrefund = requiredGas * mUserOp.maxFeePerGas;
Expand Down Expand Up @@ -430,18 +434,16 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard,
*/
function _validateAccountPrepayment(
uint256 opIndex,
UserOperation calldata op,
PackedUserOperation calldata op,
UserOpInfo memory opInfo,
uint256 requiredPrefund
)
internal
returns (
uint256 gasUsedByValidateAccountPrepayment,
uint256 validationData
)
{
unchecked {
uint256 preGas = gasleft();
MemoryUserOp memory mUserOp = opInfo.mUserOp;
address sender = mUserOp.sender;
_createSenderIfNeeded(opIndex, opInfo, op.initCode);
Expand Down Expand Up @@ -470,7 +472,6 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard,
}
senderInfo.deposit = deposit - requiredPrefund;
}
gasUsedByValidateAccountPrepayment = preGas - gasleft();
}
}

Expand All @@ -484,25 +485,15 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard,
* @param op - The user operation.
* @param opInfo - The operation info.
* @param requiredPreFund - The required prefund amount.
* @param gasUsedByValidateAccountPrepayment - The gas used by _validateAccountPrepayment.
*/
function _validatePaymasterPrepayment(
uint256 opIndex,
UserOperation calldata op,
PackedUserOperation calldata op,
UserOpInfo memory opInfo,
uint256 requiredPreFund,
uint256 gasUsedByValidateAccountPrepayment
uint256 requiredPreFund
) internal returns (bytes memory context, uint256 validationData) {
unchecked {
MemoryUserOp memory mUserOp = opInfo.mUserOp;
uint256 verificationGasLimit = mUserOp.verificationGasLimit;
require(
verificationGasLimit > gasUsedByValidateAccountPrepayment,
"AA41 too little verificationGas"
);
uint256 gas = verificationGasLimit -
gasUsedByValidateAccountPrepayment;

address paymaster = mUserOp.paymaster;
DepositInfo storage paymasterInfo = deposits[paymaster];
uint256 deposit = paymasterInfo.deposit;
Expand All @@ -511,7 +502,7 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard,
}
paymasterInfo.deposit = deposit - requiredPreFund;
try
IPaymaster(paymaster).validatePaymasterUserOp{gas: gas}(
IPaymaster(paymaster).validatePaymasterUserOp{gas: mUserOp.paymasterVerificationGasLimit}(
op,
opInfo.userOpHash,
requiredPreFund
Expand Down Expand Up @@ -586,7 +577,7 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard,
*/
function _validatePrepayment(
uint256 opIndex,
UserOperation calldata userOp,
PackedUserOperation calldata userOp,
UserOpInfo memory outOpInfo
)
internal
Expand All @@ -602,16 +593,14 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard,
uint256 maxGasValues = mUserOp.preVerificationGas |
mUserOp.verificationGasLimit |
mUserOp.callGasLimit |
mUserOp.paymasterVerificationGasLimit |
mUserOp.paymasterPostOpGasLimit |
userOp.maxFeePerGas |
userOp.maxPriorityFeePerGas;
require(maxGasValues <= type(uint120).max, "AA94 gas values overflow");

uint256 gasUsedByValidateAccountPrepayment;
uint256 requiredPreFund = _getRequiredPrefund(mUserOp);
(
gasUsedByValidateAccountPrepayment,
validationData
) = _validateAccountPrepayment(
validationData = _validateAccountPrepayment(
opIndex,
userOp,
outOpInfo,
Expand All @@ -628,14 +617,13 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard,
opIndex,
userOp,
outOpInfo,
requiredPreFund,
gasUsedByValidateAccountPrepayment
requiredPreFund
);
}
unchecked {
uint256 gasUsed = preGas - gasleft();

if (userOp.verificationGasLimit < gasUsed) {
if (mUserOp.verificationGasLimit + mUserOp.paymasterVerificationGasLimit < gasUsed) {
revert FailedOp(opIndex, "AA40 over verificationGasLimit");
}
outOpInfo.prefund = requiredPreFund;
Expand Down Expand Up @@ -676,7 +664,7 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard,
actualGasCost = actualGas * gasPrice;
if (mode != IPaymaster.PostOpMode.postOpReverted) {
try IPaymaster(paymaster).postOp{
gas: mUserOp.verificationGasLimit
gas: mUserOp.paymasterPostOpGasLimit
}(mode, context, actualGasCost, gasPrice)
// solhint-disable-next-line no-empty-blocks
{} catch {
Expand All @@ -693,7 +681,7 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard,
uint256 executionGasLimit = mUserOp.callGasLimit;
// Note that 'verificationGasLimit' here is the limit given to the 'postOp' which is part of execution
if (context.length > 0){
executionGasLimit += mUserOp.verificationGasLimit;
executionGasLimit += mUserOp.paymasterPostOpGasLimit;
}
uint256 executionGasUsed = actualGas - opInfo.preOpGas;
// this check is required for the gas used within EntryPoint and not covered by explicit gas limits
Expand Down
6 changes: 3 additions & 3 deletions contracts/core/EntryPointSimulations.sol
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ contract EntryPointSimulations is EntryPoint, IEntryPointSimulations {

/// @inheritdoc IEntryPointSimulations
function simulateValidation(
UserOperation calldata userOp
PackedUserOperation calldata userOp
)
external
returns (
Expand Down Expand Up @@ -85,7 +85,7 @@ contract EntryPointSimulations is EntryPoint, IEntryPointSimulations {

/// @inheritdoc IEntryPointSimulations
function simulateHandleOp(
UserOperation calldata op,
PackedUserOperation calldata op,
address target,
bytes calldata targetCallData
)
Expand Down Expand Up @@ -121,7 +121,7 @@ contract EntryPointSimulations is EntryPoint, IEntryPointSimulations {
}

function _simulationOnlyValidations(
UserOperation calldata userOp
PackedUserOperation calldata userOp
)
internal
view
Expand Down
Loading

0 comments on commit 8faf84a

Please sign in to comment.