Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Makes comments and formatting consistent #235

Merged
merged 8 commits into from
Jun 25, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 62 additions & 39 deletions contracts/core/BaseAccount.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,34 +11,45 @@ import "./Helpers.sol";

/**
* Basic account implementation.
* this contract provides the basic logic for implementing the IAccount interface - validateUserOp
* specific account implementation should inherit it and provide the account-specific logic
* This contract provides the basic logic for implementing the IAccount interface - validateUserOp
* Specific account implementation should inherit it and provide the account-specific logic.
*/
abstract contract BaseAccount is IAccount {
using UserOperationLib for UserOperation;

//return value in case of signature failure, with no time-range.
// equivalent to _packValidationData(true,0,0);
uint256 constant internal SIG_VALIDATION_FAILED = 1;
/**
* Return value in case of signature failure, with no time-range.
* Equivalent to _packValidationData(true,0,0).
*/
uint256 internal constant SIG_VALIDATION_FAILED = 1;

/**
* return the account nonce.
* subclass should return a nonce value that is used both by _validateAndUpdateNonce, and by the external provider (to read the current nonce)
* Return the account nonce.
* subclass should return a nonce value that is used both by _validateAndUpdateNonce,
* and by the external provider (to read the current nonce)
*/
function nonce() public view virtual returns (uint256);

/**
* return the entryPoint used by this account.
* subclass should return the current entryPoint used by this account.
* Return the entryPoint used by this account.
* Subclass should return the current entryPoint used by this account.
*/
function entryPoint() public view virtual returns (IEntryPoint);

/**
* Validate user's signature and nonce.
* subclass doesn't need to override this method. Instead, it should override the specific internal validation methods.
* Subclass doesn't need to override this method. Instead,
* it should override the specific internal validation methods.
* @param userOp - The user operation to validate.
* @param userOpHash - The hash of the user operation.
* @param missingAccountFunds - The amount of funds missing from the account
* to pay for the user operation.
*/
function validateUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds)
external override virtual returns (uint256 validationData) {
function validateUserOp(
UserOperation calldata userOp,
bytes32 userOpHash,
uint256 missingAccountFunds
) external virtual override returns (uint256 validationData) {
_requireFromEntryPoint();
validationData = _validateSignature(userOp, userOpHash);
if (userOp.initCode.length == 0) {
Expand All @@ -48,47 +59,59 @@ abstract contract BaseAccount is IAccount {
}

/**
* ensure the request comes from the known entrypoint.
* Ensure the request comes from the known entrypoint.
*/
function _requireFromEntryPoint() internal virtual view {
require(msg.sender == address(entryPoint()), "account: not from EntryPoint");
function _requireFromEntryPoint() internal view virtual {
require(
msg.sender == address(entryPoint()),
"account: not from EntryPoint"
);
}

/**
* validate the signature is valid for this message.
* @param userOp validate the userOp.signature field
* @param userOpHash convenient field: the hash of the request, to check the signature against
* (also hashes the entrypoint and chain id)
* @return validationData signature and time-range of this operation
* <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure,
* otherwise, an address of an "authorizer" contract.
* <6-byte> validUntil - last timestamp this operation is valid. 0 for "indefinite"
* <6-byte> validAfter - first timestamp this operation is valid
* If the account doesn't use time-range, it is enough to return SIG_VALIDATION_FAILED value (1) for signature failure.
* Note that the validation code cannot use block.timestamp (or block.number) directly.
* Validate the signature is valid for this message.
* @param userOp - Validate the userOp.signature field.
* @param userOpHash - Convenient field: the hash of the request, to check the signature against.
* (also hashes the entrypoint and chain id)
* @return validationData - Signature and time-range of this operation.
* <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure,
* otherwise, an address of an "authorizer" contract.
* <6-byte> validUntil - last timestamp this operation is valid. 0 for "indefinite"
* <6-byte> validAfter - first timestamp this operation is valid
* If the account doesn't use time-range, it is enough to return
* SIG_VALIDATION_FAILED value (1) for signature failure.
* Note that the validation code cannot use block.timestamp (or block.number) directly.
*/
function _validateSignature(UserOperation calldata userOp, bytes32 userOpHash)
internal virtual returns (uint256 validationData);
function _validateSignature(
UserOperation calldata userOp,
bytes32 userOpHash
) internal virtual returns (uint256 validationData);

/**
* validate the current nonce matches the UserOperation nonce.
* then it should update the account's state to prevent replay of this UserOperation.
* called only if initCode is empty (since "nonce" field is used as "salt" on account creation)
* @param userOp the op to validate.
* Validate the current nonce matches the UserOperation nonce, then update the
* account's state to prevent replay of this UserOperation.
* Called only if initCode is empty (since "nonce" field is used as "salt" on account creation)
* @param userOp - The op to validate.
*/
function _validateAndUpdateNonce(UserOperation calldata userOp) internal virtual;
function _validateAndUpdateNonce(
UserOperation calldata userOp
) internal virtual;

/**
* sends to the entrypoint (msg.sender) the missing funds for this transaction.
* subclass MAY override this method for better funds management
* Sends to the entrypoint (msg.sender) the missing funds for this transaction.
* SubClass MAY override this method for better funds management
* (e.g. send to the entryPoint more than the minimum required, so that in future transactions
* it will not be required to send again)
* @param missingAccountFunds the minimum value this method should send the entrypoint.
* this value MAY be zero, in case there is enough deposit, or the userOp has a paymaster.
* it will not be required to send again).
* @param missingAccountFunds - The minimum value this method should send the entrypoint.
* This value MAY be zero, in case there is enough deposit,
* or the userOp has a paymaster.
*/
function _payPrefund(uint256 missingAccountFunds) internal virtual {
if (missingAccountFunds != 0) {
(bool success,) = payable(msg.sender).call{value : missingAccountFunds, gas : type(uint256).max}("");
(bool success, ) = payable(msg.sender).call{
value: missingAccountFunds,
gas: type(uint256).max
}("");
(success);
//ignore failure (its EntryPoint's job to verify, not account.)
}
Expand Down
96 changes: 60 additions & 36 deletions contracts/core/BasePaymaster.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.12;


/* solhint-disable reason-string */

import "@openzeppelin/contracts/access/Ownable.sol";
Expand All @@ -12,100 +11,125 @@ import "./Helpers.sol";
/**
* Helper class for creating a paymaster.
* provides helper methods for staking.
* validates that the postOp is called only by the entryPoint
* Validates that the postOp is called only by the entryPoint.
*/
abstract contract BasePaymaster is IPaymaster, Ownable {

IEntryPoint immutable public entryPoint;
IEntryPoint public immutable entryPoint;

constructor(IEntryPoint _entryPoint) {
entryPoint = _entryPoint;
}

/// @inheritdoc IPaymaster
function validatePaymasterUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 maxCost)
external override returns (bytes memory context, uint256 validationData) {
_requireFromEntryPoint();
function validatePaymasterUserOp(
UserOperation calldata userOp,
bytes32 userOpHash,
uint256 maxCost
) external override returns (bytes memory context, uint256 validationData) {
_requireFromEntryPoint();
return _validatePaymasterUserOp(userOp, userOpHash, maxCost);
}

function _validatePaymasterUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 maxCost)
internal virtual returns (bytes memory context, uint256 validationData);
/**
* Validate a user operation.
* @param userOp - The user operation.
* @param userOpHash - The hash of the user operation.
* @param maxCost - The maximum cost of the user operation.
*/
function _validatePaymasterUserOp(
UserOperation calldata userOp,
bytes32 userOpHash,
uint256 maxCost
) internal virtual returns (bytes memory context, uint256 validationData);

/// @inheritdoc IPaymaster
function postOp(PostOpMode mode, bytes calldata context, uint256 actualGasCost) external override {
function postOp(
PostOpMode mode,
bytes calldata context,
uint256 actualGasCost
) external override {
_requireFromEntryPoint();
_postOp(mode, context, actualGasCost);
}

/**
* post-operation handler.
* Post-operation handler.
* (verified to be called only through the entryPoint)
* @dev if subclass returns a non-empty context from validatePaymasterUserOp, it must also implement this method.
* @param mode enum with the following options:
* opSucceeded - user operation succeeded.
* opReverted - user op reverted. still has to pay for gas.
* postOpReverted - user op succeeded, but caused postOp (in mode=opSucceeded) to revert.
* Now this is the 2nd call, after user's op was deliberately reverted.
* @param context - the context value returned by validatePaymasterUserOp
* @param actualGasCost - actual gas used so far (without this postOp call).
* @dev If subclass returns a non-empty context from validatePaymasterUserOp,
* it must also implement this method.
* @param mode - Enum with the following options:
* opSucceeded - User operation succeeded.
* opReverted - User op reverted. still has to pay for gas.
* postOpReverted - User op succeeded, but caused postOp (in mode=opSucceeded) to revert.
* Now this is the 2nd call, after user's op was deliberately reverted.
* @param context - The context value returned by validatePaymasterUserOp
* @param actualGasCost - Actual gas used so far (without this postOp call).
*/
function _postOp(PostOpMode mode, bytes calldata context, uint256 actualGasCost) internal virtual {

(mode,context,actualGasCost); // unused params
function _postOp(
PostOpMode mode,
bytes calldata context,
uint256 actualGasCost
) internal virtual {
(mode, context, actualGasCost); // unused params
// subclass must override this method if validatePaymasterUserOp returns a context
revert("must override");
}

/**
* add a deposit for this paymaster, used for paying for transaction fees
* Add a deposit for this paymaster, used for paying for transaction fees.
*/
function deposit() public payable {
entryPoint.depositTo{value : msg.value}(address(this));
entryPoint.depositTo{value: msg.value}(address(this));
}

/**
* withdraw value from the deposit
* @param withdrawAddress target to send to
* @param amount to withdraw
* Withdraw value from the deposit.
* @param withdrawAddress - Target to send to.
* @param amount - Amount to withdraw.
*/
function withdrawTo(address payable withdrawAddress, uint256 amount) public onlyOwner {
function withdrawTo(
address payable withdrawAddress,
uint256 amount
) public onlyOwner {
entryPoint.withdrawTo(withdrawAddress, amount);
}

/**
* add stake for this paymaster.
* Add stake for this paymaster.
* This method can also carry eth value to add to the current stake.
* @param unstakeDelaySec - the unstake delay for this paymaster. Can only be increased.
* @param unstakeDelaySec - The unstake delay for this paymaster. Can only be increased.
*/
function addStake(uint32 unstakeDelaySec) external payable onlyOwner {
entryPoint.addStake{value : msg.value}(unstakeDelaySec);
entryPoint.addStake{value: msg.value}(unstakeDelaySec);
}

/**
* return current paymaster's deposit on the entryPoint.
* Return current paymaster's deposit on the entryPoint.
*/
function getDeposit() public view returns (uint256) {
return entryPoint.balanceOf(address(this));
}

/**
* unlock the stake, in order to withdraw it.
* Unlock the stake, in order to withdraw it.
* The paymaster can't serve requests once unlocked, until it calls addStake again
*/
function unlockStake() external onlyOwner {
entryPoint.unlockStake();
}

/**
* withdraw the entire paymaster's stake.
* Withdraw the entire paymaster's stake.
* stake must be unlocked first (and then wait for the unstakeDelay to be over)
* @param withdrawAddress the address to send withdrawn value.
* @param withdrawAddress - The address to send withdrawn value.
*/
function withdrawStake(address payable withdrawAddress) external onlyOwner {
entryPoint.withdrawStake(withdrawAddress);
}

/// validate the call is made from a valid entrypoint
/**
* Validate the call is made from a valid entrypoint
*/
function _requireFromEntryPoint() internal virtual {
require(msg.sender == address(entryPoint), "Sender not EntryPoint");
}
Expand Down
Loading