This ERC-4337 operator address has been tagged based on 0xKofi compilation.
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
There are no matching entriesUpdate your filters to view other transactions | |||||||||
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
VerifyingSingletonPaymaster
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 800 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.17;
/* solhint-disable reason-string */
/* solhint-disable no-inline-assembly */
import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import {ReentrancyGuard} from "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import {UserOperation, UserOperationLib} from "@account-abstraction/contracts/interfaces/UserOperation.sol";
import {BasePaymaster, IEntryPoint} from "../../BasePaymaster.sol";
import {PaymasterHelpers, PaymasterData, PaymasterContext} from "../../PaymasterHelpers.sol";
import {SingletonPaymasterErrors} from "../../../common/Errors.sol";
/**
* @title A sample paymaster that uses external service to decide whether to pay for the UserOp.
* @dev The paymaster trusts an external signer to sign the transaction.
* The calling user must pass the UserOp to that external signer first, which performs whatever
* off-chain verification before signing the UserOp.
* @notice That this signature is NOT a replacement for wallet signature:
* - The paymaster signs to agree to PAY for GAS.
* - The wallet signs to prove identity and wallet ownership.
*/
contract VerifyingSingletonPaymaster is
BasePaymaster,
ReentrancyGuard,
SingletonPaymasterErrors
{
using ECDSA for bytes32;
using UserOperationLib for UserOperation;
using PaymasterHelpers for UserOperation;
using PaymasterHelpers for bytes;
using PaymasterHelpers for PaymasterData;
// Gas used in EntryPoint._handlePostOp() method (including this#postOp() call)
uint256 private unaccountedEPGasOverhead;
mapping(address => uint256) public paymasterIdBalances;
address public verifyingSigner;
event EPGasOverheadChanged(
uint256 indexed _oldValue,
uint256 indexed _newValue
);
event VerifyingSignerChanged(
address indexed _oldSigner,
address indexed _newSigner,
address indexed _actor
);
event GasDeposited(address indexed _paymasterId, uint256 indexed _value);
event GasWithdrawn(
address indexed _paymasterId,
address indexed _to,
uint256 indexed _value
);
event GasBalanceDeducted(
address indexed _paymasterId,
uint256 indexed _charge
);
constructor(
address _owner,
IEntryPoint _entryPoint,
address _verifyingSigner
) payable BasePaymaster(_owner, _entryPoint) {
if (address(_entryPoint) == address(0)) revert EntryPointCannotBeZero();
if (_verifyingSigner == address(0))
revert VerifyingSignerCannotBeZero();
assembly {
sstore(verifyingSigner.slot, _verifyingSigner)
}
unaccountedEPGasOverhead = 9600;
}
/**
* @dev Add a deposit for this paymaster and given paymasterId (Dapp Depositor address), used for paying for transaction fees
* @param paymasterId dapp identifier for which deposit is being made
*/
function depositFor(address paymasterId) external payable nonReentrant {
if (paymasterId == address(0)) revert PaymasterIdCannotBeZero();
if (msg.value == 0) revert DepositCanNotBeZero();
paymasterIdBalances[paymasterId] =
paymasterIdBalances[paymasterId] +
msg.value;
entryPoint.depositTo{value: msg.value}(address(this));
emit GasDeposited(paymasterId, msg.value);
}
/**
* @dev get the current deposit for paymasterId (Dapp Depositor address)
* @param paymasterId dapp identifier
*/
function getBalance(
address paymasterId
) external view returns (uint256 balance) {
balance = paymasterIdBalances[paymasterId];
}
/**
@dev Override the default implementation.
*/
function deposit() public payable virtual override {
revert("user DepositFor instead");
}
/**
* @dev Withdraws the specified amount of gas tokens from the paymaster's balance and transfers them to the specified address.
* @param withdrawAddress The address to which the gas tokens should be transferred.
* @param amount The amount of gas tokens to withdraw.
*/
function withdrawTo(
address payable withdrawAddress,
uint256 amount
) public override nonReentrant {
if (withdrawAddress == address(0)) revert CanNotWithdrawToZeroAddress();
uint256 currentBalance = paymasterIdBalances[msg.sender];
if (amount > currentBalance)
revert InsufficientBalance(amount, currentBalance);
paymasterIdBalances[msg.sender] =
paymasterIdBalances[msg.sender] -
amount;
entryPoint.withdrawTo(withdrawAddress, amount);
emit GasWithdrawn(msg.sender, withdrawAddress, amount);
}
/**
* @dev Set a new verifying signer address.
* Can only be called by the owner of the contract.
* @param _newVerifyingSigner The new address to be set as the verifying signer.
* @notice If _newVerifyingSigner is set to zero address, it will revert with an error.
* After setting the new signer address, it will emit an event VerifyingSignerChanged.
*/
function setSigner(address _newVerifyingSigner) external payable onlyOwner {
if (_newVerifyingSigner == address(0))
revert VerifyingSignerCannotBeZero();
address oldSigner = verifyingSigner;
assembly {
sstore(verifyingSigner.slot, _newVerifyingSigner)
}
emit VerifyingSignerChanged(oldSigner, _newVerifyingSigner, msg.sender);
}
function setUnaccountedEPGasOverhead(uint256 value) external onlyOwner {
uint256 oldValue = unaccountedEPGasOverhead;
unaccountedEPGasOverhead = value;
emit EPGasOverheadChanged(oldValue, value);
}
/**
* @dev This method is called by the off-chain service, to sign the request.
* It is called on-chain from the validatePaymasterUserOp, to validate the signature.
* @notice That this signature covers all fields of the UserOperation, except the "paymasterAndData",
* which will carry the signature itself.
* @return hash we're going to sign off-chain (and validate on-chain)
*/
function getHash(
UserOperation calldata userOp,
address paymasterId
) public view returns (bytes32) {
//can't use userOp.hash(), since it contains also the paymasterAndData itself.
address sender = userOp.getSender();
return
keccak256(
abi.encode(
sender,
userOp.nonce,
keccak256(userOp.initCode),
keccak256(userOp.callData),
userOp.callGasLimit,
userOp.verificationGasLimit,
userOp.preVerificationGas,
userOp.maxFeePerGas,
userOp.maxPriorityFeePerGas,
block.chainid,
address(this),
paymasterId
)
);
}
/**
* @dev Verify that an external signer signed the paymaster data of a user operation.
* The paymaster data is expected to be the paymaster and a signature over the entire request parameters.
* @param userOp The UserOperation struct that represents the current user operation.
* userOpHash The hash of the UserOperation struct.
* @param requiredPreFund The required amount of pre-funding for the paymaster.
* @return context A context string returned by the entry point after successful validation.
* @return validationData An integer returned by the entry point after successful validation.
*/
function _validatePaymasterUserOp(
UserOperation calldata userOp,
bytes32 /*userOpHash*/,
uint256 requiredPreFund
) internal override returns (bytes memory context, uint256 validationData) {
PaymasterData memory paymasterData = userOp._decodePaymasterData();
bytes32 hash = getHash(userOp, paymasterData.paymasterId);
uint256 sigLength = paymasterData.signatureLength;
// we only "require" it here so that the revert reason on invalid signature will be of "VerifyingPaymaster", and not "ECDSA"
if (sigLength != 65) revert InvalidPaymasterSignatureLength(sigLength);
//don't revert on signature failure: return SIG_VALIDATION_FAILED
if (
verifyingSigner !=
hash.toEthSignedMessageHash().recover(paymasterData.signature)
) {
// empty context and sigTimeRange 1
return ("", 1);
}
if (requiredPreFund > paymasterIdBalances[paymasterData.paymasterId])
revert InsufficientBalance(
requiredPreFund,
paymasterIdBalances[paymasterData.paymasterId]
);
return (userOp.paymasterContext(paymasterData, userOp.gasPrice()), 0);
}
/**
* @dev Executes the paymaster's payment conditions
* @param mode tells whether the op succeeded, reverted, or if the op succeeded but cause the postOp to revert
* @param context payment conditions signed by the paymaster in `validatePaymasterUserOp`
* @param actualGasCost amount to be paid to the entry point in wei
*/
function _postOp(
PostOpMode mode,
bytes calldata context,
uint256 actualGasCost
) internal virtual override {
PaymasterContext memory data = context._decodePaymasterContext();
address extractedPaymasterId = data.paymasterId;
uint256 balToDeduct = actualGasCost +
unaccountedEPGasOverhead *
data.gasPrice;
paymasterIdBalances[extractedPaymasterId] =
paymasterIdBalances[extractedPaymasterId] -
balToDeduct;
emit GasBalanceDeducted(extractedPaymasterId, balToDeduct);
}
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.12;
/* solhint-disable no-inline-assembly */
/**
* returned data from validateUserOp.
* validateUserOp returns a uint256, with is created by `_packedValidationData` and parsed by `_parseValidationData`
* @param aggregator - address(0) - the account validated the signature by itself.
* address(1) - the account failed to validate the signature.
* otherwise - this is an address of a signature aggregator that must be used to validate the signature.
* @param validAfter - this UserOp is valid only after this timestamp.
* @param validaUntil - this UserOp is valid only up to this timestamp.
*/
struct ValidationData {
address aggregator;
uint48 validAfter;
uint48 validUntil;
}
//extract sigFailed, validAfter, validUntil.
// also convert zero validUntil to type(uint48).max
function _parseValidationData(uint validationData) pure returns (ValidationData memory data) {
address aggregator = address(uint160(validationData));
uint48 validUntil = uint48(validationData >> 160);
if (validUntil == 0) {
validUntil = type(uint48).max;
}
uint48 validAfter = uint48(validationData >> (48 + 160));
return ValidationData(aggregator, validAfter, validUntil);
}
// intersect account and paymaster ranges.
function _intersectTimeRange(uint256 validationData, uint256 paymasterValidationData) pure returns (ValidationData memory) {
ValidationData memory accountValidationData = _parseValidationData(validationData);
ValidationData memory pmValidationData = _parseValidationData(paymasterValidationData);
address aggregator = accountValidationData.aggregator;
if (aggregator == address(0)) {
aggregator = pmValidationData.aggregator;
}
uint48 validAfter = accountValidationData.validAfter;
uint48 validUntil = accountValidationData.validUntil;
uint48 pmValidAfter = pmValidationData.validAfter;
uint48 pmValidUntil = pmValidationData.validUntil;
if (validAfter < pmValidAfter) validAfter = pmValidAfter;
if (validUntil > pmValidUntil) validUntil = pmValidUntil;
return ValidationData(aggregator, validAfter, validUntil);
}
/**
* helper to pack the return value for validateUserOp
* @param data - the ValidationData to pack
*/
function _packValidationData(ValidationData memory data) pure returns (uint256) {
return uint160(data.aggregator) | (uint256(data.validUntil) << 160) | (uint256(data.validAfter) << (160 + 48));
}
/**
* helper to pack the return value for validateUserOp, when not using an aggregator
* @param sigFailed - true for signature failure, false for success
* @param validUntil last timestamp this UserOperation is valid (or zero for infinite)
* @param validAfter first timestamp this UserOperation is valid
*/
function _packValidationData(bool sigFailed, uint48 validUntil, uint48 validAfter) pure returns (uint256) {
return (sigFailed ? 1 : 0) | (uint256(validUntil) << 160) | (uint256(validAfter) << (160 + 48));
}
/**
* keccak function over calldata.
* @dev copy calldata into memory, do keccak and drop allocated memory. Strangely, this is more efficient than letting solidity do it.
*/
function calldataKeccak(bytes calldata data) pure returns (bytes32 ret) {
assembly {
let mem := mload(0x40)
let len := data.length
calldatacopy(mem, data.offset, len)
ret := keccak256(mem, len)
}
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.12;
import "./UserOperation.sol";
/**
* Aggregated Signatures validator.
*/
interface IAggregator {
/**
* validate aggregated signature.
* revert if the aggregated signature does not match the given list of operations.
*/
function validateSignatures(UserOperation[] calldata userOps, bytes calldata signature) external view;
/**
* validate signature of a single userOp
* This method is should be called by bundler after EntryPoint.simulateValidation() returns (reverts) with ValidationResultWithAggregation
* First it validates the signature over the userOp. Then it returns data to be used when creating the handleOps.
* @param userOp the userOperation received from the user.
* @return sigForUserOp the value to put into the signature field of the userOp when calling handleOps.
* (usually empty, unless account and aggregator support some kind of "multisig"
*/
function validateUserOpSignature(UserOperation calldata userOp)
external view returns (bytes memory sigForUserOp);
/**
* aggregate multiple signatures into a single value.
* This method is called off-chain to calculate the signature to pass with handleOps()
* bundler MAY use optimized custom code perform this aggregation
* @param userOps array of UserOperations to collect the signatures from.
* @return aggregatedSignature the aggregated signature
*/
function aggregateSignatures(UserOperation[] calldata userOps) external view returns (bytes memory aggregatedSignature);
}/**
** Account-Abstraction (EIP-4337) singleton EntryPoint implementation.
** Only one instance required on each chain.
**/
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.12;
/* solhint-disable avoid-low-level-calls */
/* solhint-disable no-inline-assembly */
/* solhint-disable reason-string */
import "./UserOperation.sol";
import "./IStakeManager.sol";
import "./IAggregator.sol";
import "./INonceManager.sol";
interface IEntryPoint is IStakeManager, INonceManager {
/***
* An event emitted after each successful request
* @param userOpHash - unique identifier for the request (hash its entire content, except signature).
* @param sender - the account that generates this request.
* @param paymaster - if non-null, the paymaster that pays for this request.
* @param nonce - the nonce value from the request.
* @param success - true if the sender transaction succeeded, false if reverted.
* @param actualGasCost - actual amount paid (by account or paymaster) for this UserOperation.
* @param actualGasUsed - total gas used by this UserOperation (including preVerification, creation, validation and execution).
*/
event UserOperationEvent(bytes32 indexed userOpHash, address indexed sender, address indexed paymaster, uint256 nonce, bool success, uint256 actualGasCost, uint256 actualGasUsed);
/**
* account "sender" was deployed.
* @param userOpHash the userOp that deployed this account. UserOperationEvent will follow.
* @param sender the account that is deployed
* @param factory the factory used to deploy this account (in the initCode)
* @param paymaster the paymaster used by this UserOp
*/
event AccountDeployed(bytes32 indexed userOpHash, address indexed sender, address factory, address paymaster);
/**
* An event emitted if the UserOperation "callData" reverted with non-zero length
* @param userOpHash the request unique identifier.
* @param sender the sender of this request
* @param nonce the nonce used in the request
* @param revertReason - the return bytes from the (reverted) call to "callData".
*/
event UserOperationRevertReason(bytes32 indexed userOpHash, address indexed sender, uint256 nonce, bytes revertReason);
/**
* an event emitted by handleOps(), before starting the execution loop.
* any event emitted before this event, is part of the validation.
*/
event BeforeExecution();
/**
* signature aggregator used by the following UserOperationEvents within this bundle.
*/
event SignatureAggregatorChanged(address indexed aggregator);
/**
* a custom revert error of handleOps, to identify the offending op.
* NOTE: if simulateValidation passes successfully, there should be no reason for handleOps to fail on it.
* @param opIndex - index into the array of ops to the failed one (in simulateValidation, this is always zero)
* @param reason - revert reason
* The string starts with a unique code "AAmn", where "m" is "1" for factory, "2" for account and "3" for paymaster issues,
* so a failure can be attributed to the correct entity.
* Should be caught in off-chain handleOps simulation and not happen on-chain.
* Useful for mitigating DoS attempts against batchers or for troubleshooting of factory/account/paymaster reverts.
*/
error FailedOp(uint256 opIndex, string reason);
/**
* error case when a signature aggregator fails to verify the aggregated signature it had created.
*/
error SignatureValidationFailed(address aggregator);
/**
* Successful result from simulateValidation.
* @param returnInfo gas and time-range returned values
* @param senderInfo stake information about the sender
* @param factoryInfo stake information about the factory (if any)
* @param paymasterInfo stake information about the paymaster (if any)
*/
error ValidationResult(ReturnInfo returnInfo,
StakeInfo senderInfo, StakeInfo factoryInfo, StakeInfo paymasterInfo);
/**
* Successful result from simulateValidation, if the account returns a signature aggregator
* @param returnInfo gas and time-range returned values
* @param senderInfo stake information about the sender
* @param factoryInfo stake information about the factory (if any)
* @param paymasterInfo stake information about the paymaster (if any)
* @param aggregatorInfo signature aggregation info (if the account requires signature aggregator)
* bundler MUST use it to verify the signature, or reject the UserOperation
*/
error ValidationResultWithAggregation(ReturnInfo returnInfo,
StakeInfo senderInfo, StakeInfo factoryInfo, StakeInfo paymasterInfo,
AggregatorStakeInfo aggregatorInfo);
/**
* return value of getSenderAddress
*/
error SenderAddressResult(address sender);
/**
* return value of simulateHandleOp
*/
error ExecutionResult(uint256 preOpGas, uint256 paid, uint48 validAfter, uint48 validUntil, bool targetSuccess, bytes targetResult);
//UserOps handled, per aggregator
struct UserOpsPerAggregator {
UserOperation[] userOps;
// aggregator address
IAggregator aggregator;
// aggregated signature
bytes signature;
}
/**
* Execute a batch of UserOperation.
* no signature aggregator is used.
* if any account requires an aggregator (that is, it returned an aggregator when
* performing simulateValidation), then handleAggregatedOps() must be used instead.
* @param ops the operations to execute
* @param beneficiary the address to receive the fees
*/
function handleOps(UserOperation[] calldata ops, address payable beneficiary) external;
/**
* Execute a batch of UserOperation with Aggregators
* @param opsPerAggregator the operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts)
* @param beneficiary the address to receive the fees
*/
function handleAggregatedOps(
UserOpsPerAggregator[] calldata opsPerAggregator,
address payable beneficiary
) external;
/**
* generate a request Id - unique identifier for this request.
* the request ID is a hash over the content of the userOp (except the signature), the entrypoint and the chainid.
*/
function getUserOpHash(UserOperation calldata userOp) external view returns (bytes32);
/**
* Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp.
* @dev this method always revert. Successful result is ValidationResult error. other errors are failures.
* @dev The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage outside the account's data.
* @param userOp the user operation to validate.
*/
function simulateValidation(UserOperation calldata userOp) external;
/**
* gas and return values during simulation
* @param preOpGas the gas used for validation (including preValidationGas)
* @param prefund the required prefund for this operation
* @param sigFailed validateUserOp's (or paymaster's) signature check failed
* @param validAfter - first timestamp this UserOp is valid (merging account and paymaster time-range)
* @param validUntil - last timestamp this UserOp is valid (merging account and paymaster time-range)
* @param paymasterContext returned by validatePaymasterUserOp (to be passed into postOp)
*/
struct ReturnInfo {
uint256 preOpGas;
uint256 prefund;
bool sigFailed;
uint48 validAfter;
uint48 validUntil;
bytes paymasterContext;
}
/**
* returned aggregated signature info.
* the aggregator returned by the account, and its current stake.
*/
struct AggregatorStakeInfo {
address aggregator;
StakeInfo stakeInfo;
}
/**
* Get counterfactual sender address.
* Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation.
* this method always revert, and returns the address in SenderAddressResult error
* @param initCode the constructor code to be passed into the UserOperation.
*/
function getSenderAddress(bytes memory initCode) external;
/**
* simulate full execution of a UserOperation (including both validation and target execution)
* this method will always revert with "ExecutionResult".
* it performs full validation of the UserOperation, but ignores signature error.
* an optional target address is called after the userop succeeds, and its value is returned
* (before the entire call is reverted)
* Note that in order to collect the the success/failure of the target call, it must be executed
* with trace enabled to track the emitted events.
* @param op the UserOperation to simulate
* @param target if nonzero, a target address to call after userop simulation. If called, the targetSuccess and targetResult
* are set to the return from that call.
* @param targetCallData callData to pass to target address
*/
function simulateHandleOp(UserOperation calldata op, address target, bytes calldata targetCallData) external;
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.12;
interface INonceManager {
/**
* Return the next nonce for this sender.
* Within a given key, the nonce values are sequenced (starting with zero, and incremented by one on each userop)
* But UserOp with different keys can come with arbitrary order.
*
* @param sender the account address
* @param key the high 192 bit of the nonce
* @return nonce a full nonce to pass for next UserOp with this sender.
*/
function getNonce(address sender, uint192 key)
external view returns (uint256 nonce);
/**
* Manually increment the nonce of the sender.
* This method is exposed just for completeness..
* Account does NOT need to call it, neither during validation, nor elsewhere,
* as the EntryPoint will update the nonce regardless.
* Possible use-case is call it with various keys to "initialize" their nonces to one, so that future
* UserOperations will not pay extra for the first transaction with a given key.
*/
function incrementNonce(uint192 key) external;
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.12;
import "./UserOperation.sol";
/**
* the interface exposed by a paymaster contract, who agrees to pay the gas for user's operations.
* a paymaster must hold a stake to cover the required entrypoint stake and also the gas for the transaction.
*/
interface IPaymaster {
enum PostOpMode {
opSucceeded, // user op succeeded
opReverted, // user op reverted. still has to pay for gas.
postOpReverted //user op succeeded, but caused postOp to revert. Now it's a 2nd call, after user's op was deliberately reverted.
}
/**
* payment validation: check if paymaster agrees to pay.
* Must verify sender is the entryPoint.
* Revert to reject this request.
* Note that bundlers will reject this method if it changes the state, unless the paymaster is trusted (whitelisted)
* The paymaster pre-pays using its deposit, and receive back a refund after the postOp method returns.
* @param userOp the user operation
* @param userOpHash hash of the user's request data.
* @param maxCost the maximum cost of this transaction (based on maximum gas and gas price from userOp)
* @return context value to send to a postOp
* zero length to signify postOp is not required.
* @return validationData signature and time-range of this operation, encoded the same as the return value of validateUserOperation
* <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
* Note that the validation code cannot use block.timestamp (or block.number) directly.
*/
function validatePaymasterUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 maxCost)
external returns (bytes memory context, uint256 validationData);
/**
* post-operation handler.
* Must verify sender is the entryPoint
* @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) external;
}// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.12;
/**
* manage deposits and stakes.
* deposit is just a balance used to pay for UserOperations (either by a paymaster or an account)
* stake is value locked for at least "unstakeDelay" by the staked entity.
*/
interface IStakeManager {
event Deposited(
address indexed account,
uint256 totalDeposit
);
event Withdrawn(
address indexed account,
address withdrawAddress,
uint256 amount
);
/// Emitted when stake or unstake delay are modified
event StakeLocked(
address indexed account,
uint256 totalStaked,
uint256 unstakeDelaySec
);
/// Emitted once a stake is scheduled for withdrawal
event StakeUnlocked(
address indexed account,
uint256 withdrawTime
);
event StakeWithdrawn(
address indexed account,
address withdrawAddress,
uint256 amount
);
/**
* @param deposit the entity's deposit
* @param staked true if this entity is staked.
* @param stake actual amount of ether staked for this entity.
* @param unstakeDelaySec minimum delay to withdraw the stake.
* @param withdrawTime - first block timestamp where 'withdrawStake' will be callable, or zero if already locked
* @dev sizes were chosen so that (deposit,staked, stake) fit into one cell (used during handleOps)
* and the rest fit into a 2nd cell.
* 112 bit allows for 10^15 eth
* 48 bit for full timestamp
* 32 bit allows 150 years for unstake delay
*/
struct DepositInfo {
uint112 deposit;
bool staked;
uint112 stake;
uint32 unstakeDelaySec;
uint48 withdrawTime;
}
//API struct used by getStakeInfo and simulateValidation
struct StakeInfo {
uint256 stake;
uint256 unstakeDelaySec;
}
/// @return info - full deposit information of given account
function getDepositInfo(address account) external view returns (DepositInfo memory info);
/// @return the deposit (for gas payment) of the account
function balanceOf(address account) external view returns (uint256);
/**
* add to the deposit of the given account
*/
function depositTo(address account) external payable;
/**
* add to the account's stake - amount and delay
* any pending unstake is first cancelled.
* @param _unstakeDelaySec the new lock duration before the deposit can be withdrawn.
*/
function addStake(uint32 _unstakeDelaySec) external payable;
/**
* attempt to unlock the stake.
* the value can be withdrawn (using withdrawStake) after the unstake delay.
*/
function unlockStake() external;
/**
* withdraw from the (unlocked) stake.
* must first call unlockStake and wait for the unstakeDelay to pass
* @param withdrawAddress the address to send withdrawn value.
*/
function withdrawStake(address payable withdrawAddress) external;
/**
* withdraw from the deposit.
* @param withdrawAddress the address to send withdrawn value.
* @param withdrawAmount the amount to withdraw.
*/
function withdrawTo(address payable withdrawAddress, uint256 withdrawAmount) external;
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.12;
/* solhint-disable no-inline-assembly */
import {calldataKeccak} from "../core/Helpers.sol";
/**
* 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 initCode if set, the account contract will be created by this constructor/
* @param callData the method call to execute on this account.
* @param callGasLimit the gas limit passed to the callData method call.
* @param verificationGasLimit gas used for validateUserOp and validatePaymasterUserOp.
* @param preVerificationGas gas not calculated by the handleOps method, but added to the gas paid. Covers batch overhead.
* @param maxFeePerGas same as EIP-1559 gas parameter.
* @param maxPriorityFeePerGas same as EIP-1559 gas parameter.
* @param paymasterAndData if set, this field holds the paymaster address and paymaster-specific 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 UserOperation {
address sender;
uint256 nonce;
bytes initCode;
bytes callData;
uint256 callGasLimit;
uint256 verificationGasLimit;
uint256 preVerificationGas;
uint256 maxFeePerGas;
uint256 maxPriorityFeePerGas;
bytes paymasterAndData;
bytes signature;
}
/**
* Utility functions helpful when working with UserOperation structs.
*/
library UserOperationLib {
function getSender(UserOperation calldata userOp) internal pure returns (address) {
address data;
//read sender from userOp, which is first userOp member (saves 800 gas...)
assembly {data := calldataload(userOp)}
return address(uint160(data));
}
//relayer/block builder might submit the TX with higher priorityFee, but the user should not
// pay above what he signed for.
function gasPrice(UserOperation calldata userOp) internal view returns (uint256) {
unchecked {
uint256 maxFeePerGas = userOp.maxFeePerGas;
uint256 maxPriorityFeePerGas = userOp.maxPriorityFeePerGas;
if (maxFeePerGas == maxPriorityFeePerGas) {
//legacy mode (for networks that don't support basefee opcode)
return maxFeePerGas;
}
return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee);
}
}
function pack(UserOperation calldata userOp) internal pure returns (bytes memory ret) {
address sender = getSender(userOp);
uint256 nonce = userOp.nonce;
bytes32 hashInitCode = calldataKeccak(userOp.initCode);
bytes32 hashCallData = calldataKeccak(userOp.callData);
uint256 callGasLimit = userOp.callGasLimit;
uint256 verificationGasLimit = userOp.verificationGasLimit;
uint256 preVerificationGas = userOp.preVerificationGas;
uint256 maxFeePerGas = userOp.maxFeePerGas;
uint256 maxPriorityFeePerGas = userOp.maxPriorityFeePerGas;
bytes32 hashPaymasterAndData = calldataKeccak(userOp.paymasterAndData);
return abi.encode(
sender, nonce,
hashInitCode, hashCallData,
callGasLimit, verificationGasLimit, preVerificationGas,
maxFeePerGas, maxPriorityFeePerGas,
hashPaymasterAndData
);
}
function hash(UserOperation calldata userOp) internal pure returns (bytes32) {
return keccak256(pack(userOp));
}
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol)
pragma solidity ^0.8.0;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be _NOT_ENTERED
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)
pragma solidity ^0.8.0;
import "../Strings.sol";
/**
* @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
*
* These functions can be used to verify that a message was signed by the holder
* of the private keys of a given address.
*/
library ECDSA {
enum RecoverError {
NoError,
InvalidSignature,
InvalidSignatureLength,
InvalidSignatureS,
InvalidSignatureV // Deprecated in v4.8
}
function _throwError(RecoverError error) private pure {
if (error == RecoverError.NoError) {
return; // no error: do nothing
} else if (error == RecoverError.InvalidSignature) {
revert("ECDSA: invalid signature");
} else if (error == RecoverError.InvalidSignatureLength) {
revert("ECDSA: invalid signature length");
} else if (error == RecoverError.InvalidSignatureS) {
revert("ECDSA: invalid signature 's' value");
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature` or error string. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {toEthSignedMessageHash} on it.
*
* Documentation for signature generation:
* - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
* - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
*
* _Available since v4.3._
*/
function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
if (signature.length == 65) {
bytes32 r;
bytes32 s;
uint8 v;
// ecrecover takes the signature parameters, and the only way to get them
// currently is to use assembly.
/// @solidity memory-safe-assembly
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
return tryRecover(hash, v, r, s);
} else {
return (address(0), RecoverError.InvalidSignatureLength);
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature`. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {toEthSignedMessageHash} on it.
*/
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, signature);
_throwError(error);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
*
* See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
*
* _Available since v4.3._
*/
function tryRecover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal pure returns (address, RecoverError) {
bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
uint8 v = uint8((uint256(vs) >> 255) + 27);
return tryRecover(hash, v, r, s);
}
/**
* @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
*
* _Available since v4.2._
*/
function recover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, r, vs);
_throwError(error);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `v`,
* `r` and `s` signature fields separately.
*
* _Available since v4.3._
*/
function tryRecover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address, RecoverError) {
// EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
// unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
// the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
// signatures from current libraries generate a unique signature with an s-value in the lower half order.
//
// If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
// with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
// vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
// these malleable signatures as well.
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return (address(0), RecoverError.InvalidSignatureS);
}
// If the signature is valid (and not malleable), return the signer address
address signer = ecrecover(hash, v, r, s);
if (signer == address(0)) {
return (address(0), RecoverError.InvalidSignature);
}
return (signer, RecoverError.NoError);
}
/**
* @dev Overload of {ECDSA-recover} that receives the `v`,
* `r` and `s` signature fields separately.
*/
function recover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, v, r, s);
_throwError(error);
return recovered;
}
/**
* @dev Returns an Ethereum Signed Message, created from a `hash`. This
* produces hash corresponding to the one signed with the
* https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* JSON-RPC method as part of EIP-191.
*
* See {recover}.
*/
function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
// 32 is the length in bytes of hash,
// enforced by the type signature above
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
}
/**
* @dev Returns an Ethereum Signed Message, created from `s`. This
* produces hash corresponding to the one signed with the
* https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* JSON-RPC method as part of EIP-191.
*
* See {recover}.
*/
function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s));
}
/**
* @dev Returns an Ethereum Signed Typed Data, created from a
* `domainSeparator` and a `structHash`. This produces hash corresponding
* to the one signed with the
* https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
* JSON-RPC method as part of EIP-712.
*
* See {recover}.
*/
function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
enum Rounding {
Down, // Toward negative infinity
Up, // Toward infinity
Zero // Toward zero
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds up instead
* of rounding down.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
* with further edits by Uniswap Labs also under MIT license.
*/
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator
) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
require(denominator > prod1);
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
// See https://cs.stackexchange.com/q/138556/92363.
// Does not overflow because the denominator cannot be zero at this stage in the function.
uint256 twos = denominator & (~denominator + 1);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
// in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator,
Rounding rounding
) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
//
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
//
// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
//
// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1 << (log2(a) >> 1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10**64) {
value /= 10**64;
result += 64;
}
if (value >= 10**32) {
value /= 10**32;
result += 32;
}
if (value >= 10**16) {
value /= 10**16;
result += 16;
}
if (value >= 10**8) {
value /= 10**8;
result += 8;
}
if (value >= 10**4) {
value /= 10**4;
result += 4;
}
if (value >= 10**2) {
value /= 10**2;
result += 2;
}
if (value >= 10**1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256, rounded down, of a positive value.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)
pragma solidity ^0.8.0;
import "./math/Math.sol";
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant _SYMBOLS = "0123456789abcdef";
uint8 private constant _ADDRESS_LENGTH = 20;
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
unchecked {
uint256 length = Math.log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
/// @solidity memory-safe-assembly
assembly {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
/// @solidity memory-safe-assembly
assembly {
mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
unchecked {
return toHexString(value, Math.log256(value) + 1);
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
*/
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity 0.8.17;
contract BaseSmartAccountErrors {
/**
* @notice Throws at onlyEntryPoint when msg.sender is not an EntryPoint set for this Smart Account
* @param caller address that tried to call onlyEntryPoint-protected method
*/
error CallerIsNotAnEntryPoint(address caller);
}
contract FallbackManagerErrors {
/**
* @notice Throws if zero address has been provided as Fallback Handler address
*/
error HandlerCannotBeZero();
}
contract SmartAccountErrors is BaseSmartAccountErrors {
/**
* @notice Throws if zero address has been provided as Entry Point address
*/
error EntryPointCannotBeZero();
/**
* @notice Throws at mixedAuth when msg.sender is not an owner neither _self
* @param caller address that tried to call mixedAuth-protected method
*/
error MixedAuthFail(address caller);
/**
* @notice Throws if transfer of tokens failed
* @param token token contract address
* @param dest token transfer receiver
* @param amount the amount of tokens in a failed transfer
*/
error TokenTransferFailed(address token, address dest, uint256 amount);
/**
* @notice Throws if trying to change an owner of a SmartAccount to the zero address
*/
error OwnerCannotBeZero();
/**
* @notice Throws if zero address has been provided as Base Implementation address
*/
error BaseImplementationCannotBeZero();
/**
* @notice Throws if there is no code at implementationAddress
* @param implementationAddress implementation address provided
*/
error InvalidImplementation(address implementationAddress);
/**
* @notice Throws at onlyOwner when msg.sender is not an owner
* @param caller address that tried to call onlyOwner method
*/
error CallerIsNotOwner(address caller);
/**
* @notice Throws at _requireFromEntryPointOrOwner when msg.sender is not an EntryPoint neither an owner
* @param caller address that tried to call _requireFromEntryPointOrOwner-protected method
*/
error CallerIsNotEntryPointOrOwner(address caller);
/**
* @notice Throws if trying to initialize a Smart Account that has already been initialized
* @param smartAccount Smart Account Address
*/
error AlreadyInitialized(address smartAccount);
/**
* @notice Throws if not if enough gas is left at some point
* @param gasLeft how much gas left at the moment of a check
* @param gasRequired how much gas required to proceed
*/
error NotEnoughGasLeft(uint256 gasLeft, uint256 gasRequired);
/**
* @notice Throws if not able to estimate gas
* It can be when amount of gas and its price are both zero and at the same time
* Transaction has failed to be executed
* @param targetTxGas gas required for target transaction
* @param gasPrice gas price passed in Refund Info
* @param success whether transaction has been executed successfully or not
*/
error CanNotEstimateGas(
uint256 targetTxGas,
uint256 gasPrice,
bool success
);
/**
* @notice Throws if contract signature is provided in frong format
* @param uintS s converted to uint256
* @param contractSignatureLength length of a contract signature
* @param signatureLength the whole signature length
*/
error WrongContractSignatureFormat(
uint256 uintS,
uint256 contractSignatureLength,
uint256 signatureLength
);
/**
* @notice Throws when isValidSignature for the conrtact signature and data hash return differs from EIP1271 Magic Value
* @param contractSignature the contract signature that has been verified
*/
error WrongContractSignature(bytes contractSignature);
/**
* @notice Throws when the address that signed the data (restored from signature)
* differs from the address we expected to sign the data (i.e. some authorized address)
* @param restoredSigner the signer address restored from signature
* @param expectedSigner the address that was expected to be a signer
*/
error InvalidSignature(address restoredSigner, address expectedSigner);
/**
* @notice Throws when the transaction execution fails
*/
error ExecutionFailed();
/**
* @notice Throws when if trying to transfer to zero address
*/
error TransferToZeroAddressAttempt();
/**
* @notice Throws when data for executeBatchCall provided in wrong format (i.e. empty array or lengths mismatch)
* @param destLength length of destination contracts array
* @param valueLength length of txn values array
* @param funcLength length of function signatures array
*/
error WrongBatchProvided(
uint256 destLength,
uint256 valueLength,
uint256 funcLength
);
/**
* @notice Throws when invalid nonce has been provided in an AA flow
* @param nonceProvided nonce that has been provided within User Operation
* @param nonceExpected expected nonce
*/
error InvalidUserOpNonceProvided(
uint256 nonceProvided,
uint256 nonceExpected
);
}
contract SmartAccountFactoryErrors is SmartAccountErrors {
/**
* @notice Throws when data for executeBatchCall provided in wrong format (i.e. empty array or lengths mismatch)
* @param owner Owner of a Proxy (Smart Account)
* @param index Deployment index
*/
error ProxyDeploymentFailed(address owner, uint256 index);
}
contract ModuleManagerErrors {
/**
* @notice Throws when trying to initialize module manager that already been initialized
*/
error ModulesAlreadyInitialized();
/**
* @notice Throws when a delegatecall in course of module manager initialization has failed
*/
error ModulesSetupExecutionFailed();
/**
* @notice Throws when address(0) or SENTINEL_MODULES constant has been provided as a module address
* @param module Module address provided
*/
error ModuleCannotBeZeroOrSentinel(address module);
/**
* @notice Throws when trying to enable module that has already been enabled
* @param module Module address provided
*/
error ModuleAlreadyEnabled(address module);
/**
* @notice Throws when module and previous module mismatch
* @param expectedModule expected module at modules[prevModule]
* @param returnedModule the module that has been found at modules[prevModule]
* @param prevModule previous module address provided at call
*/
error ModuleAndPrevModuleMismatch(
address expectedModule,
address returnedModule,
address prevModule
);
/**
* @notice Throws when trying to execute transaction from module that is not enabled
* @param module Module address provided
*/
error ModuleNotEnabled(address module);
}
contract SelfAuthorizedErrors {
/**
* @notice Throws when the caller is not address(this)
* @param caller Caller address
*/
error CallerIsNotSelf(address caller);
}
contract SingletonPaymasterErrors {
/**
* @notice Throws when the Entrypoint address provided is address(0)
*/
error EntryPointCannotBeZero();
/**
* @notice Throws when the verifiying signer address provided is address(0)
*/
error VerifyingSignerCannotBeZero();
/**
* @notice Throws when the paymaster address provided is address(0)
*/
error PaymasterIdCannotBeZero();
/**
* @notice Throws when the 0 has been provided as deposit
*/
error DepositCanNotBeZero();
/**
* @notice Throws when trying to withdraw to address(0)
*/
error CanNotWithdrawToZeroAddress();
/**
* @notice Throws when trying to withdraw more than balance available
* @param amountRequired required balance
* @param currentBalance available balance
*/
error InsufficientBalance(uint256 amountRequired, uint256 currentBalance);
/**
* @notice Throws when signature provided has invalid length
* @param sigLength length oif the signature provided
*/
error InvalidPaymasterSignatureLength(uint256 sigLength);
}
//// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.17;
/* solhint-disable reason-string */
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, UserOperationLib} 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 entryPoint
*/
// @notice Could have Ownable2Step
abstract contract BasePaymaster is IPaymaster, Ownable, BaseSmartAccountErrors {
IEntryPoint public immutable entryPoint;
constructor(address _owner, IEntryPoint _entryPoint) {
entryPoint = _entryPoint;
_transferOwnership(_owner);
}
/// @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);
}
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 {
_requireFromEntryPoint();
_postOp(mode, context, actualGasCost);
}
/**
* 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).
*/
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
*/
function deposit() external payable virtual;
/**
* 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 {
entryPoint.addStake{value: msg.value}(unstakeDelaySec);
}
/**
* 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.
* 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.
* 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 {
entryPoint.withdrawStake(withdrawAddress);
}
/// validate the call is made from a valid entrypoint
function _requireFromEntryPoint() internal virtual {
// require(msg.sender == address(entryPoint), "Sender not EntryPoint"); // won't need BaseSmartAccountErrors import
if (msg.sender != address(entryPoint))
revert CallerIsNotAnEntryPoint(msg.sender);
}
}// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.17;
import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import {UserOperation} from "@account-abstraction/contracts/interfaces/UserOperation.sol";
struct PaymasterData {
address paymasterId;
bytes signature;
uint256 signatureLength;
}
struct PaymasterContext {
address paymasterId;
uint256 gasPrice;
}
/**
* @title PaymasterHelpers - helper functions for paymasters
*/
library PaymasterHelpers {
using ECDSA for bytes32;
/**
* @dev Encodes the paymaster context: paymasterId and gasPrice
* @param op UserOperation object
* @param data PaymasterData passed
* @param gasPrice effective gasPrice
*/
function paymasterContext(
UserOperation calldata op,
PaymasterData memory data,
uint256 gasPrice
) internal pure returns (bytes memory context) {
return abi.encode(data.paymasterId, gasPrice);
}
/**
* @dev Decodes paymaster data assuming it follows PaymasterData
*/
function _decodePaymasterData(
UserOperation calldata op
) internal pure returns (PaymasterData memory) {
bytes calldata paymasterAndData = op.paymasterAndData;
(address paymasterId, bytes memory signature) = abi.decode(
paymasterAndData[20:],
(address, bytes)
);
return PaymasterData(paymasterId, signature, signature.length);
}
/**
* @dev Decodes paymaster context assuming it follows PaymasterContext
*/
function _decodePaymasterContext(
bytes memory context
) internal pure returns (PaymasterContext memory) {
(address paymasterId, uint256 gasPrice) = abi.decode(
context,
(address, uint256)
);
return PaymasterContext(paymasterId, gasPrice);
}
}{
"optimizer": {
"enabled": true,
"runs": 800
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"contract IEntryPoint","name":"_entryPoint","type":"address"},{"internalType":"address","name":"_verifyingSigner","type":"address"}],"stateMutability":"payable","type":"constructor"},{"inputs":[{"internalType":"address","name":"caller","type":"address"}],"name":"CallerIsNotAnEntryPoint","type":"error"},{"inputs":[],"name":"CanNotWithdrawToZeroAddress","type":"error"},{"inputs":[],"name":"DepositCanNotBeZero","type":"error"},{"inputs":[],"name":"EntryPointCannotBeZero","type":"error"},{"inputs":[{"internalType":"uint256","name":"amountRequired","type":"uint256"},{"internalType":"uint256","name":"currentBalance","type":"uint256"}],"name":"InsufficientBalance","type":"error"},{"inputs":[{"internalType":"uint256","name":"sigLength","type":"uint256"}],"name":"InvalidPaymasterSignatureLength","type":"error"},{"inputs":[],"name":"PaymasterIdCannotBeZero","type":"error"},{"inputs":[],"name":"VerifyingSignerCannotBeZero","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_oldValue","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"_newValue","type":"uint256"}],"name":"EPGasOverheadChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_paymasterId","type":"address"},{"indexed":true,"internalType":"uint256","name":"_charge","type":"uint256"}],"name":"GasBalanceDeducted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_paymasterId","type":"address"},{"indexed":true,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"GasDeposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_paymasterId","type":"address"},{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":true,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"GasWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_oldSigner","type":"address"},{"indexed":true,"internalType":"address","name":"_newSigner","type":"address"},{"indexed":true,"internalType":"address","name":"_actor","type":"address"}],"name":"VerifyingSignerChanged","type":"event"},{"inputs":[{"internalType":"uint32","name":"unstakeDelaySec","type":"uint32"}],"name":"addStake","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"deposit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"paymasterId","type":"address"}],"name":"depositFor","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"entryPoint","outputs":[{"internalType":"contract IEntryPoint","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"paymasterId","type":"address"}],"name":"getBalance","outputs":[{"internalType":"uint256","name":"balance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes","name":"initCode","type":"bytes"},{"internalType":"bytes","name":"callData","type":"bytes"},{"internalType":"uint256","name":"callGasLimit","type":"uint256"},{"internalType":"uint256","name":"verificationGasLimit","type":"uint256"},{"internalType":"uint256","name":"preVerificationGas","type":"uint256"},{"internalType":"uint256","name":"maxFeePerGas","type":"uint256"},{"internalType":"uint256","name":"maxPriorityFeePerGas","type":"uint256"},{"internalType":"bytes","name":"paymasterAndData","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct UserOperation","name":"userOp","type":"tuple"},{"internalType":"address","name":"paymasterId","type":"address"}],"name":"getHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"paymasterIdBalances","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum IPaymaster.PostOpMode","name":"mode","type":"uint8"},{"internalType":"bytes","name":"context","type":"bytes"},{"internalType":"uint256","name":"actualGasCost","type":"uint256"}],"name":"postOp","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newVerifyingSigner","type":"address"}],"name":"setSigner","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"name":"setUnaccountedEPGasOverhead","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unlockStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes","name":"initCode","type":"bytes"},{"internalType":"bytes","name":"callData","type":"bytes"},{"internalType":"uint256","name":"callGasLimit","type":"uint256"},{"internalType":"uint256","name":"verificationGasLimit","type":"uint256"},{"internalType":"uint256","name":"preVerificationGas","type":"uint256"},{"internalType":"uint256","name":"maxFeePerGas","type":"uint256"},{"internalType":"uint256","name":"maxPriorityFeePerGas","type":"uint256"},{"internalType":"bytes","name":"paymasterAndData","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct UserOperation","name":"userOp","type":"tuple"},{"internalType":"bytes32","name":"userOpHash","type":"bytes32"},{"internalType":"uint256","name":"maxCost","type":"uint256"}],"name":"validatePaymasterUserOp","outputs":[{"internalType":"bytes","name":"context","type":"bytes"},{"internalType":"uint256","name":"validationData","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"verifyingSigner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address payable","name":"withdrawAddress","type":"address"}],"name":"withdrawStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"withdrawAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawTo","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60a0604052604051620018f4380380620018f483398101604081905262000026916200011b565b82826200003333620000b2565b6001600160a01b0381166080526200004b82620000b2565b5050600180556001600160a01b038216620000795760405163091748f960e21b815260040160405180910390fd5b6001600160a01b038116620000a157604051638fc6a93160e01b815260040160405180910390fd5b60045550506125806002556200016f565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146200011857600080fd5b50565b6000806000606084860312156200013157600080fd5b83516200013e8162000102565b6020850151909350620001518162000102565b6040850151909250620001648162000102565b809150509250925092565b608051611738620001bc600039600081816102a1015281816103db015281816105f8015281816107e701528181610893015281816109270152818161099e0152610c7601526117386000f3fe6080604052600436106101445760003560e01c8063aa67c919116100c0578063d0e30db011610074578063f2fde38b11610059578063f2fde38b14610335578063f465c77e14610355578063f8b2cb4f1461038357600080fd5b8063d0e30db01461030d578063deeb38741461031557600080fd5b8063bb9fe6bf116100a5578063bb9fe6bf146102c3578063c23a5cea146102d8578063c399ec88146102f857600080fd5b8063aa67c9191461027c578063b0d691fe1461028f57600080fd5b80636c19e783116101175780638da5cb5b116100fc5780638da5cb5b14610211578063a40a7ddc1461022f578063a9a234091461025c57600080fd5b80636c19e783146101e9578063715018a6146101fc57600080fd5b80630396cb60146101495780631f67de801461015e578063205c28781461019157806323d9ac9b146101b1575b600080fd5b61015c6101573660046112bd565b6103b9565b005b34801561016a57600080fd5b5061017e610179366004611311565b610444565b6040519081526020015b60405180910390f35b34801561019d57600080fd5b5061015c6101ac366004611363565b610535565b3480156101bd57600080fd5b506004546101d1906001600160a01b031681565b6040516001600160a01b039091168152602001610188565b61015c6101f736600461138f565b61069a565b34801561020857600080fd5b5061015c610712565b34801561021d57600080fd5b506000546001600160a01b03166101d1565b34801561023b57600080fd5b5061017e61024a36600461138f565b60036020526000908152604090205481565b34801561026857600080fd5b5061015c6102773660046113ac565b610726565b61015c61028a36600461138f565b610740565b34801561029b57600080fd5b506101d17f000000000000000000000000000000000000000000000000000000000000000081565b3480156102cf57600080fd5b5061015c610889565b3480156102e457600080fd5b5061015c6102f336600461138f565b610900565b34801561030457600080fd5b5061017e610986565b61015c610a16565b34801561032157600080fd5b5061015c61033036600461143b565b610a5e565b34801561034157600080fd5b5061015c61035036600461138f565b610a9f565b34801561036157600080fd5b50610375610370366004611454565b610b2c565b6040516101889291906114a2565b34801561038f57600080fd5b5061017e61039e36600461138f565b6001600160a01b031660009081526003602052604090205490565b6103c1610b50565b604051621cb65b60e51b815263ffffffff821660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690630396cb609034906024016000604051808303818588803b15801561042857600080fd5b505af115801561043c573d6000803e3d6000fd5b505050505050565b6000823580602085013561045b60408701876114f7565b60405161046992919061153e565b60405190819003902061047f60608801886114f7565b60405161048d92919061153e565b604080519182900382206001600160a01b0395861660208401529082019390935260608101919091526080808201929092529086013560a08083019190915286013560c08083019190915286013560e0808301919091528601356101008083019190915286013561012082015246610140820152306101608201529084166101808201526101a001604051602081830303815290604052805190602001209150505b92915050565b61053d610baa565b6001600160a01b038216610564576040516392bc9df360e01b815260040160405180910390fd5b33600090815260036020526040902054808211156105a45760405163cf47918160e01b815260048101839052602481018290526044015b60405180910390fd5b336000908152600360205260409020546105bf908390611564565b3360009081526003602052604090819020919091555163040b850f60e31b81526001600160a01b038481166004830152602482018490527f0000000000000000000000000000000000000000000000000000000000000000169063205c287890604401600060405180830381600087803b15801561063c57600080fd5b505af1158015610650573d6000803e3d6000fd5b50506040518492506001600160a01b038616915033907f926a144b6fffc1d73f115b81af7ec66a7c12aed0ff73197c39a683753fc1d92590600090a45061069660018055565b5050565b6106a2610b50565b6001600160a01b0381166106c957604051638fc6a93160e01b815260040160405180910390fd5b60048054908290556040516001600160a01b039182169133919084169083907fe1f62c0e6d7bb6d470828565415bf2e87dbfea50e52d2d753788b529bd0c6d6290600090a45050565b61071a610b50565b6107246000610c03565b565b61072e610c6b565b61073a84848484610cb6565b50505050565b610748610baa565b6001600160a01b03811661076f576040516355cd1c6560e11b815260040160405180910390fd5b34600003610790576040516333a6177160e11b815260040160405180910390fd5b6001600160a01b0381166000908152600360205260409020546107b4903490611577565b6001600160a01b038281166000908152600360205260409081902092909255905163b760faf960e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000009091169063b760faf99034906024016000604051808303818588803b15801561082e57600080fd5b505af1158015610842573d6000803e3d6000fd5b50506040513493506001600160a01b03851692507f1dbbf474736d6415d6a265fabee708fe6e988f6fd0c9d870ded36cab380898dd9150600090a361088660018055565b50565b610891610b50565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bb9fe6bf6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156108ec57600080fd5b505af115801561073a573d6000803e3d6000fd5b610908610b50565b60405163611d2e7560e11b81526001600160a01b0382811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063c23a5cea90602401600060405180830381600087803b15801561096b57600080fd5b505af115801561097f573d6000803e3d6000fd5b5050505050565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156109ed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a11919061158a565b905090565b60405162461bcd60e51b815260206004820152601760248201527f75736572204465706f736974466f7220696e7374656164000000000000000000604482015260640161059b565b610a66610b50565b6002805490829055604051829082907f0b2f957fc0a9306310238ef9a212935360e98fe3f8bc525f4cb69d38b1efa85990600090a35050565b610aa7610b50565b6001600160a01b038116610b235760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161059b565b61088681610c03565b60606000610b38610c6b565b610b43858585610d90565b915091505b935093915050565b6000546001600160a01b031633146107245760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161059b565b600260015403610bfc5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161059b565b6002600155565b600080546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461072457604051635dac3db760e11b815233600482015260240161059b565b6000610cf784848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610f2292505050565b805160208201516002549293509091600091610d12916115a3565b610d1c9085611577565b6001600160a01b038316600090815260036020526040902054909150610d43908290611564565b6001600160a01b03831660008181526003602052604080822093909355915183927f5dc1c754041954fe976773fa441397a7928c7127a1c83904214a7d256339900791a350505050505050565b6060600080610d9e86610f71565b90506000610db0878360000151610444565b604083015190915060418114610ddc5760405163e4b52b1760e01b81526004810182905260240161059b565b610e418360200151610e3b846040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b90610fff565b6004546001600160a01b03908116911614610e75576001604051806020016040528060008152509094509450505050610b48565b82516001600160a01b0316600090815260036020526040902054861115610ed55782516001600160a01b03166000908152600360205260409081902054905163cf47918160e01b815261059b918891600401918252602082015260400190565b610f1383610ee28a611023565b9051604080516001600160a01b03909216602083015281810192909252815180820383018152606090910190915290565b98600098509650505050505050565b604080518082019091526000808252602082015260008083806020019051810190610f4d91906115ba565b604080518082019091526001600160a01b0390921682526020820152949350505050565b610f9e604051806060016040528060006001600160a01b0316815260200160608152602001600081525090565b366000610faf6101208501856114f7565b9092509050600080610fc483601481876115e8565b810190610fd19190611628565b604080516060810182526001600160a01b039093168352602083018290529051908201529695505050505050565b600080600061100e8585611052565b9150915061101b81611097565b509392505050565b600060e082013561010083013580820361103e575092915050565b61104a824883016111e1565b949350505050565b60008082516041036110885760208301516040840151606085015160001a61107c878285856111f9565b94509450505050611090565b506000905060025b9250929050565b60008160048111156110ab576110ab6116ec565b036110b35750565b60018160048111156110c7576110c76116ec565b036111145760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015260640161059b565b6002816004811115611128576111286116ec565b036111755760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e67746800604482015260640161059b565b6003816004811115611189576111896116ec565b036108865760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b606482015260840161059b565b60008183106111f057816111f2565b825b9392505050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561123057506000905060036112b4565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611284573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166112ad576000600192509250506112b4565b9150600090505b94509492505050565b6000602082840312156112cf57600080fd5b813563ffffffff811681146111f257600080fd5b600061016082840312156112f657600080fd5b50919050565b6001600160a01b038116811461088657600080fd5b6000806040838503121561132457600080fd5b823567ffffffffffffffff81111561133b57600080fd5b611347858286016112e3565b9250506020830135611358816112fc565b809150509250929050565b6000806040838503121561137657600080fd5b8235611381816112fc565b946020939093013593505050565b6000602082840312156113a157600080fd5b81356111f2816112fc565b600080600080606085870312156113c257600080fd5b8435600381106113d157600080fd5b9350602085013567ffffffffffffffff808211156113ee57600080fd5b818701915087601f83011261140257600080fd5b81358181111561141157600080fd5b88602082850101111561142357600080fd5b95986020929092019750949560400135945092505050565b60006020828403121561144d57600080fd5b5035919050565b60008060006060848603121561146957600080fd5b833567ffffffffffffffff81111561148057600080fd5b61148c868287016112e3565b9660208601359650604090950135949350505050565b604081526000835180604084015260005b818110156114d057602081870181015160608684010152016114b3565b506000606082850101526060601f19601f8301168401019150508260208301529392505050565b6000808335601e1984360301811261150e57600080fd5b83018035915067ffffffffffffffff82111561152957600080fd5b60200191503681900382131561109057600080fd5b8183823760009101908152919050565b634e487b7160e01b600052601160045260246000fd5b8181038181111561052f5761052f61154e565b8082018082111561052f5761052f61154e565b60006020828403121561159c57600080fd5b5051919050565b808202811582820484141761052f5761052f61154e565b600080604083850312156115cd57600080fd5b82516115d8816112fc565b6020939093015192949293505050565b600080858511156115f857600080fd5b8386111561160557600080fd5b5050820193919092039150565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561163b57600080fd5b8235611646816112fc565b9150602083013567ffffffffffffffff8082111561166357600080fd5b818501915085601f83011261167757600080fd5b81358181111561168957611689611612565b604051601f8201601f19908116603f011681019083821181831017156116b1576116b1611612565b816040528281528860208487010111156116ca57600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b634e487b7160e01b600052602160045260246000fdfea2646970667358221220293125c4717fe502700b023d6789a8a934644dc68d4874835a636ee9b178431564736f6c63430008110033000000000000000000000000129443ca2a9dec2020808a2868b38dda457eacc70000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d2789000000000000000000000000c6dab8652e5e9749523ba948f42d5944584e4e73
Deployed Bytecode
0x6080604052600436106101445760003560e01c8063aa67c919116100c0578063d0e30db011610074578063f2fde38b11610059578063f2fde38b14610335578063f465c77e14610355578063f8b2cb4f1461038357600080fd5b8063d0e30db01461030d578063deeb38741461031557600080fd5b8063bb9fe6bf116100a5578063bb9fe6bf146102c3578063c23a5cea146102d8578063c399ec88146102f857600080fd5b8063aa67c9191461027c578063b0d691fe1461028f57600080fd5b80636c19e783116101175780638da5cb5b116100fc5780638da5cb5b14610211578063a40a7ddc1461022f578063a9a234091461025c57600080fd5b80636c19e783146101e9578063715018a6146101fc57600080fd5b80630396cb60146101495780631f67de801461015e578063205c28781461019157806323d9ac9b146101b1575b600080fd5b61015c6101573660046112bd565b6103b9565b005b34801561016a57600080fd5b5061017e610179366004611311565b610444565b6040519081526020015b60405180910390f35b34801561019d57600080fd5b5061015c6101ac366004611363565b610535565b3480156101bd57600080fd5b506004546101d1906001600160a01b031681565b6040516001600160a01b039091168152602001610188565b61015c6101f736600461138f565b61069a565b34801561020857600080fd5b5061015c610712565b34801561021d57600080fd5b506000546001600160a01b03166101d1565b34801561023b57600080fd5b5061017e61024a36600461138f565b60036020526000908152604090205481565b34801561026857600080fd5b5061015c6102773660046113ac565b610726565b61015c61028a36600461138f565b610740565b34801561029b57600080fd5b506101d17f0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d278981565b3480156102cf57600080fd5b5061015c610889565b3480156102e457600080fd5b5061015c6102f336600461138f565b610900565b34801561030457600080fd5b5061017e610986565b61015c610a16565b34801561032157600080fd5b5061015c61033036600461143b565b610a5e565b34801561034157600080fd5b5061015c61035036600461138f565b610a9f565b34801561036157600080fd5b50610375610370366004611454565b610b2c565b6040516101889291906114a2565b34801561038f57600080fd5b5061017e61039e36600461138f565b6001600160a01b031660009081526003602052604090205490565b6103c1610b50565b604051621cb65b60e51b815263ffffffff821660048201527f0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d27896001600160a01b031690630396cb609034906024016000604051808303818588803b15801561042857600080fd5b505af115801561043c573d6000803e3d6000fd5b505050505050565b6000823580602085013561045b60408701876114f7565b60405161046992919061153e565b60405190819003902061047f60608801886114f7565b60405161048d92919061153e565b604080519182900382206001600160a01b0395861660208401529082019390935260608101919091526080808201929092529086013560a08083019190915286013560c08083019190915286013560e0808301919091528601356101008083019190915286013561012082015246610140820152306101608201529084166101808201526101a001604051602081830303815290604052805190602001209150505b92915050565b61053d610baa565b6001600160a01b038216610564576040516392bc9df360e01b815260040160405180910390fd5b33600090815260036020526040902054808211156105a45760405163cf47918160e01b815260048101839052602481018290526044015b60405180910390fd5b336000908152600360205260409020546105bf908390611564565b3360009081526003602052604090819020919091555163040b850f60e31b81526001600160a01b038481166004830152602482018490527f0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d2789169063205c287890604401600060405180830381600087803b15801561063c57600080fd5b505af1158015610650573d6000803e3d6000fd5b50506040518492506001600160a01b038616915033907f926a144b6fffc1d73f115b81af7ec66a7c12aed0ff73197c39a683753fc1d92590600090a45061069660018055565b5050565b6106a2610b50565b6001600160a01b0381166106c957604051638fc6a93160e01b815260040160405180910390fd5b60048054908290556040516001600160a01b039182169133919084169083907fe1f62c0e6d7bb6d470828565415bf2e87dbfea50e52d2d753788b529bd0c6d6290600090a45050565b61071a610b50565b6107246000610c03565b565b61072e610c6b565b61073a84848484610cb6565b50505050565b610748610baa565b6001600160a01b03811661076f576040516355cd1c6560e11b815260040160405180910390fd5b34600003610790576040516333a6177160e11b815260040160405180910390fd5b6001600160a01b0381166000908152600360205260409020546107b4903490611577565b6001600160a01b038281166000908152600360205260409081902092909255905163b760faf960e01b81523060048201527f0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d27899091169063b760faf99034906024016000604051808303818588803b15801561082e57600080fd5b505af1158015610842573d6000803e3d6000fd5b50506040513493506001600160a01b03851692507f1dbbf474736d6415d6a265fabee708fe6e988f6fd0c9d870ded36cab380898dd9150600090a361088660018055565b50565b610891610b50565b7f0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d27896001600160a01b031663bb9fe6bf6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156108ec57600080fd5b505af115801561073a573d6000803e3d6000fd5b610908610b50565b60405163611d2e7560e11b81526001600160a01b0382811660048301527f0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d2789169063c23a5cea90602401600060405180830381600087803b15801561096b57600080fd5b505af115801561097f573d6000803e3d6000fd5b5050505050565b6040516370a0823160e01b81523060048201526000907f0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d27896001600160a01b0316906370a0823190602401602060405180830381865afa1580156109ed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a11919061158a565b905090565b60405162461bcd60e51b815260206004820152601760248201527f75736572204465706f736974466f7220696e7374656164000000000000000000604482015260640161059b565b610a66610b50565b6002805490829055604051829082907f0b2f957fc0a9306310238ef9a212935360e98fe3f8bc525f4cb69d38b1efa85990600090a35050565b610aa7610b50565b6001600160a01b038116610b235760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161059b565b61088681610c03565b60606000610b38610c6b565b610b43858585610d90565b915091505b935093915050565b6000546001600160a01b031633146107245760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161059b565b600260015403610bfc5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161059b565b6002600155565b600080546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b336001600160a01b037f0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d2789161461072457604051635dac3db760e11b815233600482015260240161059b565b6000610cf784848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610f2292505050565b805160208201516002549293509091600091610d12916115a3565b610d1c9085611577565b6001600160a01b038316600090815260036020526040902054909150610d43908290611564565b6001600160a01b03831660008181526003602052604080822093909355915183927f5dc1c754041954fe976773fa441397a7928c7127a1c83904214a7d256339900791a350505050505050565b6060600080610d9e86610f71565b90506000610db0878360000151610444565b604083015190915060418114610ddc5760405163e4b52b1760e01b81526004810182905260240161059b565b610e418360200151610e3b846040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b90610fff565b6004546001600160a01b03908116911614610e75576001604051806020016040528060008152509094509450505050610b48565b82516001600160a01b0316600090815260036020526040902054861115610ed55782516001600160a01b03166000908152600360205260409081902054905163cf47918160e01b815261059b918891600401918252602082015260400190565b610f1383610ee28a611023565b9051604080516001600160a01b03909216602083015281810192909252815180820383018152606090910190915290565b98600098509650505050505050565b604080518082019091526000808252602082015260008083806020019051810190610f4d91906115ba565b604080518082019091526001600160a01b0390921682526020820152949350505050565b610f9e604051806060016040528060006001600160a01b0316815260200160608152602001600081525090565b366000610faf6101208501856114f7565b9092509050600080610fc483601481876115e8565b810190610fd19190611628565b604080516060810182526001600160a01b039093168352602083018290529051908201529695505050505050565b600080600061100e8585611052565b9150915061101b81611097565b509392505050565b600060e082013561010083013580820361103e575092915050565b61104a824883016111e1565b949350505050565b60008082516041036110885760208301516040840151606085015160001a61107c878285856111f9565b94509450505050611090565b506000905060025b9250929050565b60008160048111156110ab576110ab6116ec565b036110b35750565b60018160048111156110c7576110c76116ec565b036111145760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015260640161059b565b6002816004811115611128576111286116ec565b036111755760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e67746800604482015260640161059b565b6003816004811115611189576111896116ec565b036108865760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b606482015260840161059b565b60008183106111f057816111f2565b825b9392505050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561123057506000905060036112b4565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611284573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166112ad576000600192509250506112b4565b9150600090505b94509492505050565b6000602082840312156112cf57600080fd5b813563ffffffff811681146111f257600080fd5b600061016082840312156112f657600080fd5b50919050565b6001600160a01b038116811461088657600080fd5b6000806040838503121561132457600080fd5b823567ffffffffffffffff81111561133b57600080fd5b611347858286016112e3565b9250506020830135611358816112fc565b809150509250929050565b6000806040838503121561137657600080fd5b8235611381816112fc565b946020939093013593505050565b6000602082840312156113a157600080fd5b81356111f2816112fc565b600080600080606085870312156113c257600080fd5b8435600381106113d157600080fd5b9350602085013567ffffffffffffffff808211156113ee57600080fd5b818701915087601f83011261140257600080fd5b81358181111561141157600080fd5b88602082850101111561142357600080fd5b95986020929092019750949560400135945092505050565b60006020828403121561144d57600080fd5b5035919050565b60008060006060848603121561146957600080fd5b833567ffffffffffffffff81111561148057600080fd5b61148c868287016112e3565b9660208601359650604090950135949350505050565b604081526000835180604084015260005b818110156114d057602081870181015160608684010152016114b3565b506000606082850101526060601f19601f8301168401019150508260208301529392505050565b6000808335601e1984360301811261150e57600080fd5b83018035915067ffffffffffffffff82111561152957600080fd5b60200191503681900382131561109057600080fd5b8183823760009101908152919050565b634e487b7160e01b600052601160045260246000fd5b8181038181111561052f5761052f61154e565b8082018082111561052f5761052f61154e565b60006020828403121561159c57600080fd5b5051919050565b808202811582820484141761052f5761052f61154e565b600080604083850312156115cd57600080fd5b82516115d8816112fc565b6020939093015192949293505050565b600080858511156115f857600080fd5b8386111561160557600080fd5b5050820193919092039150565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561163b57600080fd5b8235611646816112fc565b9150602083013567ffffffffffffffff8082111561166357600080fd5b818501915085601f83011261167757600080fd5b81358181111561168957611689611612565b604051601f8201601f19908116603f011681019083821181831017156116b1576116b1611612565b816040528281528860208487010111156116ca57600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b634e487b7160e01b600052602160045260246000fdfea2646970667358221220293125c4717fe502700b023d6789a8a934644dc68d4874835a636ee9b178431564736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000129443ca2a9dec2020808a2868b38dda457eacc70000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d2789000000000000000000000000c6dab8652e5e9749523ba948f42d5944584e4e73
-----Decoded View---------------
Arg [0] : _owner (address): 0x129443cA2a9Dec2020808a2868b38dDA457eaCC7
Arg [1] : _entryPoint (address): 0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789
Arg [2] : _verifyingSigner (address): 0xC6dAB8652E5E9749523bA948F42d5944584E4e73
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000129443ca2a9dec2020808a2868b38dda457eacc7
Arg [1] : 0000000000000000000000005ff137d4b0fdcd49dca30c7cf57e578a026d2789
Arg [2] : 000000000000000000000000c6dab8652e5e9749523ba948f42d5944584e4e73
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.