Aere Network public source. Everything here can be checked against the live chain (chain id 2800, https://rpc.aere.network). Scope note, stated up front rather than buried: consensus on chain 2800 is classical secp256k1 ECDSA QBFT. The post-quantum work in this repository is at the signature, precompile, account and transport layers. Nothing here makes the consensus post-quantum, and no document in it should be read as claiming so.
115 lines
3.8 KiB
Solidity
115 lines
3.8 KiB
Solidity
// SPDX-License-Identifier: MIT
|
|
pragma solidity ^0.8.23;
|
|
|
|
import "@openzeppelin/contracts/access/Ownable.sol";
|
|
|
|
/// @dev Minimal subset of ERC-4337 v0.7 IEntryPoint needed by paymasters.
|
|
interface IEntryPoint {
|
|
function depositTo(address account) external payable;
|
|
function balanceOf(address account) external view returns (uint256);
|
|
function withdrawTo(address payable withdrawAddress, uint256 amount) external;
|
|
function addStake(uint32 unstakeDelaySec) external payable;
|
|
function unlockStake() external;
|
|
function withdrawStake(address payable withdrawAddress) external;
|
|
}
|
|
|
|
/// @dev ERC-4337 v0.7 PackedUserOperation struct (used by paymaster hook).
|
|
struct PackedUserOperation {
|
|
address sender;
|
|
uint256 nonce;
|
|
bytes initCode;
|
|
bytes callData;
|
|
bytes32 accountGasLimits;
|
|
uint256 preVerificationGas;
|
|
bytes32 gasFees;
|
|
bytes paymasterAndData;
|
|
bytes signature;
|
|
}
|
|
|
|
/**
|
|
* @title PaymasterBase
|
|
* @notice Minimal in-house BasePaymaster compatible with OpenZeppelin v4.9.
|
|
* Avoids the OZ-v5 dependency that the upstream eth-infinitism package pulls in.
|
|
*
|
|
* ERC-4337 v0.7 spec:
|
|
* - validatePaymasterUserOp returns (context, validationData)
|
|
* - postOp is called with (mode, context, actualGasCost, actualUserOpFeePerGas)
|
|
*
|
|
* Subclasses override `_validatePaymasterUserOp` and (optionally) `_postOp`.
|
|
*/
|
|
abstract contract PaymasterBase is Ownable {
|
|
IEntryPoint public immutable entryPoint;
|
|
|
|
enum PostOpMode { opSucceeded, opReverted, postOpReverted }
|
|
|
|
modifier onlyEntryPoint() {
|
|
require(msg.sender == address(entryPoint), "Paymaster: not from EntryPoint");
|
|
_;
|
|
}
|
|
|
|
constructor(IEntryPoint _entryPoint) {
|
|
entryPoint = _entryPoint;
|
|
}
|
|
|
|
/// EntryPoint calls this during UserOp validation.
|
|
function validatePaymasterUserOp(
|
|
PackedUserOperation calldata userOp,
|
|
bytes32 userOpHash,
|
|
uint256 maxCost
|
|
) external onlyEntryPoint returns (bytes memory context, uint256 validationData) {
|
|
return _validatePaymasterUserOp(userOp, userOpHash, maxCost);
|
|
}
|
|
|
|
/// EntryPoint calls this after UserOp execution (if the paymaster requested it via context).
|
|
function postOp(
|
|
PostOpMode mode,
|
|
bytes calldata context,
|
|
uint256 actualGasCost,
|
|
uint256 actualUserOpFeePerGas
|
|
) external onlyEntryPoint {
|
|
_postOp(mode, context, actualGasCost, actualUserOpFeePerGas);
|
|
}
|
|
|
|
function _validatePaymasterUserOp(
|
|
PackedUserOperation calldata userOp,
|
|
bytes32 userOpHash,
|
|
uint256 maxCost
|
|
) internal virtual returns (bytes memory context, uint256 validationData);
|
|
|
|
function _postOp(
|
|
PostOpMode /*mode*/,
|
|
bytes calldata /*context*/,
|
|
uint256 /*actualGasCost*/,
|
|
uint256 /*actualUserOpFeePerGas*/
|
|
) internal virtual {
|
|
// Default: no-op. Most paymasters don't need post-op logic.
|
|
}
|
|
|
|
// ───────────────────── EntryPoint deposit helpers ─────────────────────
|
|
|
|
/// Fund the paymaster's gas deposit at the EntryPoint.
|
|
function deposit() external payable {
|
|
entryPoint.depositTo{ value: msg.value }(address(this));
|
|
}
|
|
|
|
function depositBalance() external view returns (uint256) {
|
|
return entryPoint.balanceOf(address(this));
|
|
}
|
|
|
|
function withdrawDeposit(address payable to, uint256 amount) external onlyOwner {
|
|
entryPoint.withdrawTo(to, amount);
|
|
}
|
|
|
|
function addStake(uint32 unstakeDelaySec) external payable onlyOwner {
|
|
entryPoint.addStake{ value: msg.value }(unstakeDelaySec);
|
|
}
|
|
|
|
function unlockStake() external onlyOwner { entryPoint.unlockStake(); }
|
|
|
|
function withdrawStake(address payable to) external onlyOwner {
|
|
entryPoint.withdrawStake(to);
|
|
}
|
|
|
|
receive() external payable {}
|
|
}
|