mirror of
https://github.com/luxfi/eoa-contracts.git
synced 2026-10-30 16:58:32 +00:00
127 lines
4.5 KiB
Solidity
127 lines
4.5 KiB
Solidity
// SPDX-License-Identifier: GPL-3.0
|
|
pragma solidity 0.8.17;
|
|
|
|
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
|
|
import {IPaymaster} from "@account-abstraction/contracts/interfaces/IPaymaster.sol";
|
|
import {IEntryPoint} from "@account-abstraction/contracts/interfaces/IEntryPoint.sol";
|
|
import {UserOperation} from "@account-abstraction/contracts/interfaces/UserOperation.sol";
|
|
import {BaseSmartAccountErrors} from "../common/Errors.sol";
|
|
import "@account-abstraction/contracts/core/Helpers.sol";
|
|
|
|
/**
|
|
* Helper class for creating a paymaster.
|
|
* provides helper methods for staking.
|
|
* validates that the postOp is called only by the ENTRY_POINT
|
|
@notice Could have Ownable2Step
|
|
*/
|
|
abstract contract BasePaymaster is IPaymaster, Ownable, BaseSmartAccountErrors {
|
|
IEntryPoint public immutable ENTRY_POINT;
|
|
|
|
constructor(address _owner, IEntryPoint _entryPoint) {
|
|
ENTRY_POINT = _entryPoint;
|
|
_transferOwnership(_owner);
|
|
}
|
|
|
|
/**
|
|
* add a deposit for this paymaster, used for paying for transaction fees
|
|
*/
|
|
function deposit() external payable virtual;
|
|
|
|
/// @inheritdoc IPaymaster
|
|
function postOp(
|
|
PostOpMode mode,
|
|
bytes calldata context,
|
|
uint256 actualGasCost
|
|
) external override {
|
|
_requireFromEntryPoint();
|
|
_postOp(mode, context, actualGasCost);
|
|
}
|
|
|
|
/// @inheritdoc IPaymaster
|
|
function validatePaymasterUserOp(
|
|
UserOperation calldata userOp,
|
|
bytes32 userOpHash,
|
|
uint256 maxCost
|
|
) external override returns (bytes memory context, uint256 validationData) {
|
|
_requireFromEntryPoint();
|
|
return _validatePaymasterUserOp(userOp, userOpHash, maxCost);
|
|
}
|
|
|
|
/**
|
|
* withdraw value from the deposit
|
|
* @param withdrawAddress target to send to
|
|
* @param amount to withdraw
|
|
*/
|
|
function withdrawTo(
|
|
address payable withdrawAddress,
|
|
uint256 amount
|
|
) external virtual;
|
|
|
|
/**
|
|
* 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.
|
|
*/
|
|
function addStake(uint32 unstakeDelaySec) external payable onlyOwner {
|
|
ENTRY_POINT.addStake{value: msg.value}(unstakeDelaySec);
|
|
}
|
|
|
|
/**
|
|
* 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 {
|
|
ENTRY_POINT.unlockStake();
|
|
}
|
|
|
|
/**
|
|
* 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.
|
|
*/
|
|
function withdrawStake(address payable withdrawAddress) external onlyOwner {
|
|
ENTRY_POINT.withdrawStake(withdrawAddress);
|
|
}
|
|
|
|
/**
|
|
* return current paymaster's deposit on the ENTRY_POINT.
|
|
*/
|
|
function getDeposit() public view returns (uint256) {
|
|
return ENTRY_POINT.balanceOf(address(this));
|
|
}
|
|
|
|
function _validatePaymasterUserOp(
|
|
UserOperation calldata userOp,
|
|
bytes32 userOpHash,
|
|
uint256 maxCost
|
|
) internal virtual returns (bytes memory context, uint256 validationData);
|
|
|
|
/**
|
|
* post-operation handler.
|
|
* (verified to be called only through the ENTRY_POINT)
|
|
* @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
|
|
// subclass must override this method if validatePaymasterUserOp returns a context
|
|
revert("must override");
|
|
}
|
|
|
|
/// validate the call is made from a valid entrypoint
|
|
function _requireFromEntryPoint() internal virtual {
|
|
if (msg.sender != address(ENTRY_POINT))
|
|
revert CallerIsNotAnEntryPoint(msg.sender);
|
|
}
|
|
}
|