Source Code
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Latest 4 internal transactions
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 26469702 | 115 days ago | 0.00000001 FRAX | ||||
| 26420467 | 117 days ago | 0 FRAX | ||||
| 12600651 | 436 days ago | Contract Creation | 0 FRAX | |||
| 12600651 | 436 days ago | Contract Creation | 0 FRAX |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
EntryPointSimulations
Compiler Version
v0.8.26+commit.8a97fa7a
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.23;
/* solhint-disable avoid-low-level-calls */
/* solhint-disable no-inline-assembly */
import "./EntryPoint.sol";
import "./IEntryPointSimulations.sol";
import {UserOperationLib} from "account-abstraction/core/UserOperationLib.sol";
import {IEntryPoint as EP} from "account-abstraction/interfaces/IEntryPoint.sol";
struct SimulationArgs {
PackedUserOperation op;
address target;
bytes targetCallData;
}
/*
* This contract inherits the EntryPoint and extends it with the view-only methods that are executed by
* the bundler in order to check UserOperation validity and estimate its gas consumption.
* This contract should never be deployed on-chain and is only used as a parameter for the "eth_call" request.
*/
contract EntryPointSimulations is EntryPoint, IEntryPointSimulations {
EntryPointSimulations immutable thisContract = this;
AggregatorStakeInfo private NOT_AGGREGATED = AggregatorStakeInfo(address(0), StakeInfo(0, 0));
SenderCreator private _senderCreator;
// Thrown when the binary search fails due hitting the simulation gasLimit.
error SimulationOutOfGas(uint256 optimalGas, uint256 minGas, uint256 maxGas);
error innerCallResult(uint256 remainingGas);
function initSenderCreator() internal virtual {
//this is the address of the first contract created with CREATE by this address.
address createdObj = address(uint160(uint256(keccak256(abi.encodePacked(hex"d694", address(this), hex"01")))));
_senderCreator = SenderCreator(createdObj);
}
function senderCreator() internal view virtual override returns (SenderCreator) {
// return the same senderCreator as real EntryPoint.
// this call is slightly (100) more expensive than EntryPoint's access to immutable member
return _senderCreator;
}
/**
* simulation contract should not be deployed, and specifically, accounts should not trust
* it as entrypoint, since the simulation functions don't check the signatures
*/
constructor() {}
/// @inheritdoc IEntryPointSimulations
function simulateValidation(PackedUserOperation calldata userOp) public returns (ValidationResult memory) {
UserOpInfo memory outOpInfo;
_simulationOnlyValidations(userOp);
(uint256 validationData, uint256 paymasterValidationData,) = // uint256 paymasterVerificationGasLimit
_validatePrepayment(0, userOp, outOpInfo);
_validateAccountAndPaymasterValidationData(0, validationData, paymasterValidationData, address(0));
StakeInfo memory paymasterInfo = _getStakeInfo(outOpInfo.mUserOp.paymaster);
StakeInfo memory senderInfo = _getStakeInfo(outOpInfo.mUserOp.sender);
StakeInfo memory factoryInfo;
{
bytes calldata initCode = userOp.initCode;
address factory = initCode.length >= 20 ? address(bytes20(initCode[0:20])) : address(0);
factoryInfo = _getStakeInfo(factory);
}
address aggregator = address(uint160(validationData));
ReturnInfo memory returnInfo = ReturnInfo(
outOpInfo.preOpGas,
outOpInfo.prefund,
validationData,
paymasterValidationData,
getMemoryBytesFromOffset(outOpInfo.contextOffset)
);
AggregatorStakeInfo memory aggregatorInfo = NOT_AGGREGATED;
if (uint160(aggregator) != SIG_VALIDATION_SUCCESS && uint160(aggregator) != SIG_VALIDATION_FAILED) {
aggregatorInfo = AggregatorStakeInfo(aggregator, _getStakeInfo(aggregator));
}
return ValidationResult(returnInfo, senderInfo, factoryInfo, paymasterInfo, aggregatorInfo);
}
function simulateValidationBulk(PackedUserOperation[] calldata userOps)
public
returns (ValidationResult[] memory)
{
ValidationResult[] memory results = new ValidationResult[](userOps.length);
for (uint256 i = 0; i < userOps.length; i++) {
ValidationResult memory result = simulateValidation(userOps[i]);
results[i] = result;
}
return results;
}
function simulateValidationLast(PackedUserOperation[] calldata userOps)
external
returns (ValidationResult memory)
{
ValidationResult[] memory results = simulateValidationBulk(userOps);
return results[userOps.length - 1];
}
function simulateCallAndRevert(address target, bytes calldata data, uint256 gas) external {
(bool success, bytes memory returnData) = target.call{gas: gas}(data);
if (!success) {
if (returnData.length == 0) revert();
assembly {
revert(add(32, returnData), mload(returnData))
}
}
}
// Helper function to perform the simulation and capture results from revert bytes.
function simulateCall(address entryPoint, address target, bytes calldata data, uint256 gas)
external
returns (bool success, bytes memory result)
{
bytes memory payload = abi.encodeWithSelector(this.simulateCallAndRevert.selector, target, data, gas);
try EP(payable(entryPoint)).delegateAndRevert(address(thisContract), payload) {}
catch (bytes memory reason) {
bytes memory reasonData = new bytes(reason.length - 4);
for (uint256 i = 4; i < reason.length; i++) {
reasonData[i - 4] = reason[i];
}
(success, result) = abi.decode(reasonData, (bool, bytes));
}
}
/*
* Helper function to estimate the call gas limit for a given userOperation.
* The userOperation's callGasLimit is found by performing a onchain binary search.
*
* @param queuedUserOps - The userOperations that should be simulated before the targetUserOperation.
* @param targetUserOp - The userOperation to simulate.
* @param entryPoint - The address of the entryPoint contract.
* @param toleranceDelta - The maximum difference between the estimated gas and the actual gas.
* @param initialMinGas - The initial gas value to start the binary search with.
* @param gasAllowance - The margin to add to the binary search to account for overhead.
* @return optimalGas - The estimated gas limit for the call.
*/
function simulateCallData(
SimulationArgs[] calldata queuedUserOps,
SimulationArgs calldata targetUserOp,
address entryPoint,
uint256 initialMinGas,
uint256 toleranceDelta,
uint256 gasAllowance
) public returns (TargetCallResult memory) {
// Run all queued userOps to ensure that state is valid for the target userOp.
for (uint256 i = 0; i < queuedUserOps.length; i++) {
UserOpInfo memory queuedOpInfo;
SimulationArgs calldata args = queuedUserOps[i];
_simulationOnlyValidations(args.op);
_validatePrepayment(0, args.op, queuedOpInfo);
if (args.target == address(0)) {
continue;
}
args.target.call(args.targetCallData);
}
// Extract out the target userOperation info.
PackedUserOperation calldata op = targetUserOp.op;
address target = targetUserOp.target;
bytes memory targetCallData = targetUserOp.targetCallData;
// Run our target userOperation.
UserOpInfo memory opInfo;
_simulationOnlyValidations(op);
_validatePrepayment(0, op, opInfo);
if (target == address(0)) {
return TargetCallResult(0, false, new bytes(0));
}
uint256 minGas;
bool targetSuccess;
bytes memory targetResult;
if (initialMinGas > 0) {
targetSuccess = true;
targetResult = hex"";
minGas = initialMinGas;
} else {
// Find the minGas (reduces number of iterations + checks if the call reverts).
uint256 remainingGas = gasleft();
(targetSuccess, targetResult) = thisContract.simulateCall(entryPoint, target, targetCallData, gasleft());
minGas = remainingGas - gasleft();
}
// Set bounds for binary search.
uint256 maxGas = minGas + gasAllowance;
uint256 optimalGas = maxGas;
while ((maxGas - minGas) >= toleranceDelta) {
// Check that we can do one more run.
if (gasleft() < minGas + 5_000) {
revert SimulationOutOfGas(optimalGas, minGas, maxGas);
}
uint256 midGas = (minGas + maxGas) / 2;
(bool success, bytes memory result) = thisContract.simulateCall(entryPoint, target, targetCallData, midGas);
if (success) {
// If the call is successful, reduce the maxGas and store this as the candidate
optimalGas = midGas;
maxGas = midGas - 1;
targetResult = result;
} else {
// If it fails, we need more gas, so increase the minGas
minGas = midGas + 1;
}
}
return TargetCallResult(optimalGas, targetSuccess, targetResult);
}
/// @inheritdoc IEntryPointSimulations
function simulateHandleOp(PackedUserOperation calldata op) public nonReentrant returns (ExecutionResult memory) {
UserOpInfo memory opInfo;
_simulationOnlyValidations(op);
(uint256 validationData, uint256 paymasterValidationData, uint256 paymasterVerificationGasLimit) =
_validatePrepayment(0, op, opInfo);
(uint256 paid, uint256 paymasterPostOpGasLimit) = _executeUserOp(op, opInfo);
return ExecutionResult(
opInfo.preOpGas,
paid,
validationData,
paymasterValidationData,
paymasterVerificationGasLimit,
paymasterPostOpGasLimit,
false,
"0x"
);
}
function simulateHandleOpBulk(PackedUserOperation[] calldata ops) public returns (ExecutionResult[] memory) {
ExecutionResult[] memory results = new ExecutionResult[](ops.length);
for (uint256 i = 0; i < ops.length; i++) {
ExecutionResult memory result = simulateHandleOp(ops[i]);
results[i] = result;
}
return results;
}
function simulateHandleOpLast(PackedUserOperation[] calldata ops) external returns (ExecutionResult memory) {
ExecutionResult[] memory results = new ExecutionResult[](ops.length);
results = simulateHandleOpBulk(ops);
return results[ops.length - 1];
}
function _simulationOnlyValidations(PackedUserOperation calldata userOp) internal {
//initialize senderCreator(). we can't rely on constructor
initSenderCreator();
string memory revertReason =
_validateSenderAndPaymaster(userOp.initCode, userOp.sender, userOp.paymasterAndData);
// solhint-disable-next-line no-empty-blocks
if (bytes(revertReason).length != 0) {
revert FailedOp(0, revertReason);
}
}
/**
* Called only during simulation.
* This function always reverts to prevent warm/cold storage differentiation in simulation vs execution.
* @param initCode - The smart account constructor code.
* @param sender - The sender address.
* @param paymasterAndData - The paymaster address (followed by other params, ignored by this method)
*/
function _validateSenderAndPaymaster(bytes calldata initCode, address sender, bytes calldata paymasterAndData)
internal
view
returns (string memory)
{
if (initCode.length == 0 && sender.code.length == 0) {
// it would revert anyway. but give a meaningful message
return ("AA20 account not deployed");
}
if (paymasterAndData.length >= 20) {
address paymaster = address(bytes20(paymasterAndData[0:20]));
if (paymaster.code.length == 0) {
// It would revert anyway. but give a meaningful message.
return ("AA30 paymaster not deployed");
}
}
// always revert
return ("");
}
//make sure depositTo cost is more than normal EntryPoint's cost,
// to mitigate DoS vector on the bundler
// empiric test showed that without this wrapper, simulation depositTo costs less..
function depositTo(address account) public payable override(IStakeManager, StakeManager) {
unchecked {
// silly code, to waste some gas to make sure depositTo is always little more
// expensive than on-chain call
uint256 x = 1;
while (x < 5) {
x++;
}
StakeManager.depositTo(account);
}
}
}pragma solidity ^0.8.23;
/* solhint-disable avoid-low-level-calls */
/* solhint-disable no-inline-assembly */
import "account-abstraction/interfaces/IAccount.sol";
import "account-abstraction/interfaces/IAccountExecute.sol";
import "account-abstraction/interfaces/IPaymaster.sol";
import "./IEntryPoint.sol";
import "account-abstraction/utils/Exec.sol";
import "account-abstraction/core/StakeManager.sol";
import "account-abstraction/core/SenderCreator.sol";
import "account-abstraction/core/Helpers.sol";
import "account-abstraction/core/NonceManager.sol";
import "account-abstraction/core/UserOperationLib.sol";
import "@openzeppelin/contracts/utils/introspection/ERC165.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
/*
* Account-Abstraction (EIP-4337) singleton EntryPoint implementation.
* Only one instance required on each chain.
*/
/// @custom:security-contact https://bounty.ethereum.org
contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard {
// ERC165
using UserOperationLib for PackedUserOperation;
SenderCreator private immutable _senderCreator = new SenderCreator();
function senderCreator() internal view virtual returns (SenderCreator) {
return _senderCreator;
}
//compensate for innerHandleOps' emit message and deposit refund.
// allow some slack for future gas price changes.
uint256 private constant INNER_GAS_OVERHEAD = 10000;
// Marker for inner call revert on out of gas
bytes32 private constant INNER_OUT_OF_GAS = hex"deaddead";
bytes32 private constant INNER_REVERT_LOW_PREFUND = hex"deadaa51";
uint256 private constant REVERT_REASON_MAX_LEN = 2048;
uint256 private constant PENALTY_PERCENT = 10;
/// @inheritdoc IERC165
// function supportsInterface(
// bytes4 interfaceId
// ) public view virtual override returns (bool) {
// // note: solidity "type(IEntryPoint).interfaceId" is without inherited methods but we want to check everything
// return
// interfaceId ==
// (type(IEntryPoint).interfaceId ^
// type(IStakeManager).interfaceId ^
// type(INonceManager).interfaceId) ||
// interfaceId == type(IEntryPoint).interfaceId ||
// interfaceId == type(IStakeManager).interfaceId ||
// interfaceId == type(INonceManager).interfaceId ||
// super.supportsInterface(interfaceId);
// }
/**
* Compensate the caller's beneficiary address with the collected fees of all UserOperations.
* @param beneficiary - The address to receive the fees.
* @param amount - Amount to transfer.
*/
function _compensate(address payable beneficiary, uint256 amount) internal {
require(beneficiary != address(0), "AA90 invalid beneficiary");
(bool success,) = beneficiary.call{value: amount}("");
require(success, "AA91 failed send to beneficiary");
}
/**
* Execute a user operation.
* @param userOp - The userOp to execute.
* @param opInfo - The opInfo filled by validatePrepayment for this userOp.
* @return collected - The total amount this userOp paid.
*/
function _executeUserOp(PackedUserOperation calldata userOp, UserOpInfo memory opInfo)
internal
returns (uint256 collected, uint256 paymasterPostOpGasLimit)
{
uint256 preGas = gasleft();
bytes memory context = getMemoryBytesFromOffset(opInfo.contextOffset);
{
uint256 saveFreePtr;
assembly ("memory-safe") {
saveFreePtr := mload(0x40)
}
bytes calldata callData = userOp.callData;
bytes4 methodSig;
assembly {
let len := callData.length
if gt(len, 3) { methodSig := calldataload(callData.offset) }
}
if (methodSig == IAccountExecute.executeUserOp.selector) {
bytes memory executeUserOp = abi.encodeCall(IAccountExecute.executeUserOp, (userOp, opInfo.userOpHash));
(collected, paymasterPostOpGasLimit) = innerHandleOp(executeUserOp, opInfo, context, preGas);
} else {
(collected, paymasterPostOpGasLimit) = innerHandleOp(callData, opInfo, context, preGas);
}
}
}
function emitUserOperationEvent(UserOpInfo memory opInfo, bool success, uint256 actualGasCost, uint256 actualGas)
internal
virtual
{
emit UserOperationEvent(
opInfo.userOpHash,
opInfo.mUserOp.sender,
opInfo.mUserOp.paymaster,
opInfo.mUserOp.nonce,
success,
actualGasCost,
actualGas
);
}
function emitPrefundTooLow(UserOpInfo memory opInfo) internal virtual {
emit UserOperationPrefundTooLow(opInfo.userOpHash, opInfo.mUserOp.sender, opInfo.mUserOp.nonce);
}
/// @inheritdoc IEntryPoint
// function handleOps(
// PackedUserOperation[] calldata ops,
// address payable beneficiary
// ) public nonReentrant {
// uint256 opslen = ops.length;
// UserOpInfo[] memory opInfos = new UserOpInfo[](opslen);
//
// unchecked {
// for (uint256 i = 0; i < opslen; i++) {
// UserOpInfo memory opInfo = opInfos[i];
// (
// uint256 validationData,
// uint256 pmValidationData,
// uint256 paymasterVerificationGasLimit
// ) = _validatePrepayment(i, ops[i], opInfo);
// _validateAccountAndPaymasterValidationData(
// i,
// validationData,
// pmValidationData,
// address(0)
// );
// }
//
// uint256 collected = 0;
// emit BeforeExecution();
//
// for (uint256 i = 0; i < opslen; i++) {
// (
// uint256 collectedAmount,
// uint256 paymasterVerificationGasLimit
// ) = _executeUserOp(i, ops[i], opInfos[i]);
// collected += collectedAmount;
// }
//
// _compensate(beneficiary, collected);
// }
// }
/// @inheritdoc IEntryPoint
// function handleAggregatedOps(
// UserOpsPerAggregator[] calldata opsPerAggregator,
// address payable beneficiary
// ) public nonReentrant {
// uint256 opasLen = opsPerAggregator.length;
// uint256 totalOps = 0;
// for (uint256 i = 0; i < opasLen; i++) {
// UserOpsPerAggregator calldata opa = opsPerAggregator[i];
// PackedUserOperation[] calldata ops = opa.userOps;
// IAggregator aggregator = opa.aggregator;
//
// //address(1) is special marker of "signature error"
// require(
// address(aggregator) != address(1),
// "AA96 invalid aggregator"
// );
//
// if (address(aggregator) != address(0)) {
// // solhint-disable-next-line no-empty-blocks
// try aggregator.validateSignatures(ops, opa.signature) {} catch {
// revert SignatureValidationFailed(address(aggregator));
// }
// }
//
// totalOps += ops.length;
// }
//
// UserOpInfo[] memory opInfos = new UserOpInfo[](totalOps);
//
// uint256 opIndex = 0;
// for (uint256 a = 0; a < opasLen; a++) {
// UserOpsPerAggregator calldata opa = opsPerAggregator[a];
// PackedUserOperation[] calldata ops = opa.userOps;
// IAggregator aggregator = opa.aggregator;
//
// uint256 opslen = ops.length;
// for (uint256 i = 0; i < opslen; i++) {
// UserOpInfo memory opInfo = opInfos[opIndex];
// (
// uint256 validationData,
// uint256 paymasterValidationData,
// uint256 paymasterVerificationGasLimit
// ) = _validatePrepayment(opIndex, ops[i], opInfo);
// _validateAccountAndPaymasterValidationData(
// i,
// validationData,
// paymasterValidationData,
// address(aggregator)
// );
// opIndex++;
// }
// }
//
// emit BeforeExecution();
//
// uint256 collected = 0;
// opIndex = 0;
// for (uint256 a = 0; a < opasLen; a++) {
// UserOpsPerAggregator calldata opa = opsPerAggregator[a];
// emit SignatureAggregatorChanged(address(opa.aggregator));
// PackedUserOperation[] calldata ops = opa.userOps;
// uint256 opslen = ops.length;
//
// for (uint256 i = 0; i < opslen; i++) {
// (
// uint256 collectedAmount,
// uint256 paymasterVerificationGasLimit
// ) = _executeUserOp(i, ops[i], opInfos[i]);
// collected += collectedAmount;
//
// opIndex++;
// }
// }
// emit SignatureAggregatorChanged(address(0));
//
// _compensate(beneficiary, collected);
// }
/**
* A memory copy of UserOp static fields only.
* Excluding: callData, initCode and signature. Replacing paymasterAndData with paymaster.
*/
struct MemoryUserOp {
address sender;
uint256 nonce;
uint256 verificationGasLimit;
uint256 callGasLimit;
uint256 paymasterVerificationGasLimit;
uint256 paymasterPostOpGasLimit;
uint256 preVerificationGas;
address paymaster;
uint256 maxFeePerGas;
uint256 maxPriorityFeePerGas;
}
struct UserOpInfo {
MemoryUserOp mUserOp;
bytes32 userOpHash;
uint256 prefund;
uint256 contextOffset;
uint256 preOpGas;
}
/**
* Inner function to handle a UserOperation.
* Must be declared "external" to open a call context, but it can only be called by handleOps.
* @param callData - The callData to execute.
* @param opInfo - The UserOpInfo struct.
* @param context - The context bytes.
* @return actualGasCost - the actual cost in eth this UserOperation paid for gas
*/
function innerHandleOp(bytes memory callData, UserOpInfo memory opInfo, bytes memory context, uint256 preGas)
public
returns (uint256 actualGasCost, uint256 paymasterPostOpGasLimit)
{
MemoryUserOp memory mUserOp = opInfo.mUserOp;
uint256 callGasLimit = mUserOp.callGasLimit;
unchecked {
// handleOps was called with gas limit too low. abort entire bundle.
if ((gasleft() * 63) / 64 < callGasLimit + mUserOp.paymasterPostOpGasLimit + INNER_GAS_OVERHEAD) {
revert FailedOp(0, "AA95 out of gas");
}
}
IPaymaster.PostOpMode mode = IPaymaster.PostOpMode.opSucceeded;
if (callData.length > 0) {
bool success = Exec.call(mUserOp.sender, 0, callData, callGasLimit);
if (!success) {
bytes memory result = Exec.getReturnData(REVERT_REASON_MAX_LEN);
if (result.length > 0) {
emit UserOperationRevertReason(opInfo.userOpHash, mUserOp.sender, mUserOp.nonce, result);
}
mode = IPaymaster.PostOpMode.opReverted;
}
}
unchecked {
uint256 actualGas = preGas - gasleft() + opInfo.preOpGas;
return _postExecution(mode, opInfo, context, actualGas);
}
}
/// @inheritdoc IEntryPoint
function getUserOpHash(PackedUserOperation calldata userOp) public view returns (bytes32) {
return keccak256(abi.encode(userOp.hash(), address(this), block.chainid));
}
/**
* Copy general fields from userOp into the memory opInfo structure.
* @param userOp - The user operation.
* @param mUserOp - The memory user operation.
*/
function _copyUserOpToMemory(PackedUserOperation calldata userOp, MemoryUserOp memory mUserOp) internal pure {
mUserOp.sender = userOp.sender;
mUserOp.nonce = userOp.nonce;
(mUserOp.verificationGasLimit, mUserOp.callGasLimit) = UserOperationLib.unpackUints(userOp.accountGasLimits);
mUserOp.preVerificationGas = userOp.preVerificationGas;
(mUserOp.maxPriorityFeePerGas, mUserOp.maxFeePerGas) = UserOperationLib.unpackUints(userOp.gasFees);
bytes calldata paymasterAndData = userOp.paymasterAndData;
if (paymasterAndData.length > 0) {
require(paymasterAndData.length >= UserOperationLib.PAYMASTER_DATA_OFFSET, "AA93 invalid paymasterAndData");
(mUserOp.paymaster, mUserOp.paymasterVerificationGasLimit, mUserOp.paymasterPostOpGasLimit) =
UserOperationLib.unpackPaymasterStaticFields(paymasterAndData);
} else {
mUserOp.paymaster = address(0);
mUserOp.paymasterVerificationGasLimit = 0;
mUserOp.paymasterPostOpGasLimit = 0;
}
}
/**
* Get the required prefunded gas fee amount for an operation.
* @param mUserOp - The user operation in memory.
*/
function _getRequiredPrefund(MemoryUserOp memory mUserOp) internal pure returns (uint256 requiredPrefund) {
unchecked {
uint256 requiredGas = mUserOp.verificationGasLimit + mUserOp.callGasLimit
+ mUserOp.paymasterVerificationGasLimit + mUserOp.paymasterPostOpGasLimit + mUserOp.preVerificationGas;
requiredPrefund = requiredGas * mUserOp.maxFeePerGas;
}
}
/**
* Create sender smart contract account if init code is provided.
* @param opIndex - The operation index.
* @param opInfo - The operation info.
* @param initCode - The init code for the smart contract account.
*/
function _createSenderIfNeeded(uint256 opIndex, UserOpInfo memory opInfo, bytes calldata initCode) internal {
if (initCode.length != 0) {
address sender = opInfo.mUserOp.sender;
if (sender.code.length != 0) {
revert FailedOp(opIndex, "AA10 sender already constructed");
}
address sender1 = senderCreator().createSender{gas: opInfo.mUserOp.verificationGasLimit}(initCode);
if (sender1 == address(0)) {
revert FailedOp(opIndex, "AA13 initCode failed or OOG");
}
if (sender1 != sender) {
revert FailedOp(opIndex, "AA14 initCode must return sender");
}
if (sender1.code.length == 0) {
revert FailedOp(opIndex, "AA15 initCode must create sender");
}
address factory = address(bytes20(initCode[0:20]));
emit AccountDeployed(opInfo.userOpHash, sender, factory, opInfo.mUserOp.paymaster);
}
}
/// @inheritdoc IEntryPoint
// function getSenderAddress(bytes calldata initCode) public {
// address sender = senderCreator().createSender(initCode);
// revert SenderAddressResult(sender);
// }
/**
* Call account.validateUserOp.
* Revert (with FailedOp) in case validateUserOp reverts, or account didn't send required prefund.
* Decrement account's deposit if needed.
* @param opIndex - The operation index.
* @param op - The user operation.
* @param opInfo - The operation info.
* @param requiredPrefund - The required prefund amount.
*/
function _validateAccountPrepayment(
uint256 opIndex,
PackedUserOperation calldata op,
UserOpInfo memory opInfo,
uint256 requiredPrefund,
uint256 verificationGasLimit
) internal returns (uint256 validationData) {
unchecked {
MemoryUserOp memory mUserOp = opInfo.mUserOp;
address sender = mUserOp.sender;
_createSenderIfNeeded(opIndex, opInfo, op.initCode);
address paymaster = mUserOp.paymaster;
uint256 missingAccountFunds = 0;
if (paymaster == address(0)) {
uint256 bal = balanceOf(sender);
missingAccountFunds = bal > requiredPrefund ? 0 : requiredPrefund - bal;
}
try IAccount(sender).validateUserOp{gas: verificationGasLimit}(op, opInfo.userOpHash, missingAccountFunds)
returns (uint256 _validationData) {
validationData = _validationData;
} catch {
revert FailedOpWithRevert(opIndex, "AA23 reverted", Exec.getReturnData(REVERT_REASON_MAX_LEN));
}
if (paymaster == address(0)) {
DepositInfo storage senderInfo = deposits[sender];
uint256 deposit = senderInfo.deposit;
if (requiredPrefund > deposit) {
revert FailedOp(opIndex, "AA21 didn't pay prefund");
}
senderInfo.deposit = deposit - requiredPrefund;
}
}
}
/**
* In case the request has a paymaster:
* - Validate paymaster has enough deposit.
* - Call paymaster.validatePaymasterUserOp.
* - Revert with proper FailedOp in case paymaster reverts.
* - Decrement paymaster's deposit.
* @param opIndex - The operation index.
* @param op - The user operation.
* @param opInfo - The operation info.
* @param requiredPreFund - The required prefund amount.
*/
function _validatePaymasterPrepayment(
uint256 opIndex,
PackedUserOperation calldata op,
UserOpInfo memory opInfo,
uint256 requiredPreFund
) internal returns (bytes memory context, uint256 validationData) {
unchecked {
uint256 preGas = gasleft();
MemoryUserOp memory mUserOp = opInfo.mUserOp;
address paymaster = mUserOp.paymaster;
DepositInfo storage paymasterInfo = deposits[paymaster];
uint256 deposit = paymasterInfo.deposit;
if (deposit < requiredPreFund) {
revert FailedOp(opIndex, "AA31 paymaster deposit too low");
}
paymasterInfo.deposit = deposit - requiredPreFund;
uint256 pmVerificationGasLimit = mUserOp.paymasterVerificationGasLimit;
try IPaymaster(paymaster).validatePaymasterUserOp{gas: pmVerificationGasLimit}(
op, opInfo.userOpHash, requiredPreFund
) returns (bytes memory _context, uint256 _validationData) {
context = _context;
validationData = _validationData;
} catch {
revert FailedOpWithRevert(opIndex, "AA33 reverted", Exec.getReturnData(REVERT_REASON_MAX_LEN));
}
if (preGas - gasleft() > pmVerificationGasLimit) {
revert FailedOp(opIndex, "AA36 over paymasterVerificationGasLimit");
}
}
}
/**
* Revert if either account validationData or paymaster validationData is expired.
* @param opIndex - The operation index.
* @param validationData - The account validationData.
* @param paymasterValidationData - The paymaster validationData.
* @param expectedAggregator - The expected aggregator.
*/
function _validateAccountAndPaymasterValidationData(
uint256 opIndex,
uint256 validationData,
uint256 paymasterValidationData,
address expectedAggregator
) internal view {
(address aggregator, bool outOfTimeRange) = _getValidationData(validationData);
if (expectedAggregator != aggregator) {
revert FailedOp(opIndex, "AA24 signature error");
}
if (outOfTimeRange) {
revert FailedOp(opIndex, "AA22 expired or not due");
}
// pmAggregator is not a real signature aggregator: we don't have logic to handle it as address.
// Non-zero address means that the paymaster fails due to some signature check (which is ok only during estimation).
address pmAggregator;
(pmAggregator, outOfTimeRange) = _getValidationData(paymasterValidationData);
if (pmAggregator != address(0)) {
revert FailedOp(opIndex, "AA34 signature error");
}
// * NOTE: We ignore the expiry check as this is done on bundler side.
//if (outOfTimeRange) {
// revert FailedOp(opIndex, "AA32 paymaster expired or not due");
//}
}
/**
* Parse validationData into its components.
* @param validationData - The packed validation data (sigFailed, validAfter, validUntil).
* @return aggregator the aggregator of the validationData
* @return outOfTimeRange true if current time is outside the time range of this validationData.
*/
function _getValidationData(uint256 validationData)
internal
view
returns (address aggregator, bool outOfTimeRange)
{
if (validationData == 0) {
return (address(0), false);
}
ValidationData memory data = _parseValidationData(validationData);
// solhint-disable-next-line not-rely-on-time
outOfTimeRange = block.timestamp > data.validUntil || block.timestamp < data.validAfter;
aggregator = data.aggregator;
}
/**
* Validate account and paymaster (if defined) and
* also make sure total validation doesn't exceed verificationGasLimit.
* This method is called off-chain (simulateValidation()) and on-chain (from handleOps)
* @param opIndex - The index of this userOp into the "opInfos" array.
* @param userOp - The userOp to validate.
*/
function _validatePrepayment(uint256 opIndex, PackedUserOperation calldata userOp, UserOpInfo memory outOpInfo)
internal
returns (uint256 validationData, uint256 paymasterValidationData, uint256 paymasterVerificationGasLimit)
{
uint256 preGas = gasleft();
MemoryUserOp memory mUserOp = outOpInfo.mUserOp;
_copyUserOpToMemory(userOp, mUserOp);
outOpInfo.userOpHash = getUserOpHash(userOp);
// Validate all numeric values in userOp are well below 128 bit, so they can safely be added
// and multiplied without causing overflow.
uint256 verificationGasLimit = mUserOp.verificationGasLimit;
uint256 maxGasValues = mUserOp.preVerificationGas | verificationGasLimit | mUserOp.callGasLimit
| mUserOp.paymasterVerificationGasLimit | mUserOp.paymasterPostOpGasLimit | mUserOp.maxFeePerGas
| mUserOp.maxPriorityFeePerGas;
require(maxGasValues <= type(uint120).max, "AA94 gas values overflow");
uint256 requiredPreFund = _getRequiredPrefund(mUserOp);
validationData = _validateAccountPrepayment(opIndex, userOp, outOpInfo, requiredPreFund, verificationGasLimit);
if (!_validateAndUpdateNonce(mUserOp.sender, mUserOp.nonce)) {
revert FailedOp(opIndex, "AA25 invalid account nonce");
}
unchecked {
if (preGas - gasleft() > verificationGasLimit) {
revert FailedOp(opIndex, "AA26 over verificationGasLimit");
}
}
bytes memory context;
uint256 remainingGas = gasleft();
if (mUserOp.paymaster != address(0)) {
(context, paymasterValidationData) =
_validatePaymasterPrepayment(opIndex, userOp, outOpInfo, requiredPreFund);
}
unchecked {
outOpInfo.prefund = requiredPreFund;
outOpInfo.contextOffset = getOffsetOfMemoryBytes(context);
outOpInfo.preOpGas = preGas - gasleft() + userOp.preVerificationGas;
}
paymasterVerificationGasLimit = ((remainingGas - gasleft()) * 115) / 100;
}
/**
* Process post-operation, called just after the callData is executed.
* If a paymaster is defined and its validation returned a non-empty context, its postOp is called.
* The excess amount is refunded to the account (or paymaster - if it was used in the request).
* @param mode - Whether is called from innerHandleOp, or outside (postOpReverted).
* @param opInfo - UserOp fields and info collected during validation.
* @param context - The context returned in validatePaymasterUserOp.
* @param actualGas - The gas used so far by this user operation.
*/
function _postExecution(
IPaymaster.PostOpMode mode,
UserOpInfo memory opInfo,
bytes memory context,
uint256 actualGas
) private returns (uint256 actualGasCost, uint256 paymasterPostOpGasLimit) {
uint256 preGas = gasleft();
unchecked {
address refundAddress;
MemoryUserOp memory mUserOp = opInfo.mUserOp;
uint256 gasPrice = getUserOpGasPrice(mUserOp);
address paymaster = mUserOp.paymaster;
if (paymaster == address(0)) {
refundAddress = mUserOp.sender;
} else {
refundAddress = paymaster;
if (context.length > 0) {
actualGasCost = actualGas * gasPrice;
if (mode != IPaymaster.PostOpMode.postOpReverted) {
uint256 remainingGas = gasleft();
try IPaymaster(paymaster).postOp{gas: mUserOp.paymasterPostOpGasLimit}(
mode, context, actualGasCost, gasPrice
) {
// solhint-disable-next-line no-empty-blocks
} catch {
revert FailedOpWithRevert(
0, "AA50 postOp reverted", Exec.getReturnData(REVERT_REASON_MAX_LEN)
);
//emit PostOpRevertReason(
// opInfo.userOpHash,
// opInfo.mUserOp.sender,
// opInfo.mUserOp.nonce,
// Exec.getReturnData(REVERT_REASON_MAX_LEN)
//);
//actualGas = preGas - gasleft() + opInfo.preOpGas;
//(
// actualGasCost,
// paymasterPostOpGasLimit
//) = _postExecution(
// IPaymaster.PostOpMode.postOpReverted,
// opInfo,
// context,
// actualGas
//);
}
paymasterPostOpGasLimit = remainingGas - gasleft();
}
}
}
actualGas += preGas - gasleft();
// Calculating a penalty for unused execution gas
{
uint256 executionGasLimit = mUserOp.callGasLimit + mUserOp.paymasterPostOpGasLimit;
uint256 executionGasUsed = actualGas - opInfo.preOpGas;
// this check is required for the gas used within EntryPoint and not covered by explicit gas limits
if (executionGasLimit > executionGasUsed) {
uint256 unusedGas = executionGasLimit - executionGasUsed;
uint256 unusedGasPenalty = (unusedGas * PENALTY_PERCENT) / 100;
actualGas += unusedGasPenalty;
}
}
actualGasCost = actualGas * gasPrice;
uint256 prefund = opInfo.prefund;
if (prefund < actualGasCost) {
if (mode == IPaymaster.PostOpMode.postOpReverted) {
actualGasCost = prefund;
emitPrefundTooLow(opInfo);
emitUserOperationEvent(opInfo, false, actualGasCost, actualGas);
} else {
actualGas = preGas - gasleft() + opInfo.preOpGas;
actualGasCost = opInfo.prefund;
emitPrefundTooLow(opInfo);
emitUserOperationEvent(opInfo, false, actualGasCost, actualGas);
}
} else {
uint256 refund = prefund - actualGasCost;
_incrementDeposit(refundAddress, refund);
bool success = mode == IPaymaster.PostOpMode.opSucceeded;
emitUserOperationEvent(opInfo, success, actualGasCost, actualGas);
}
} // unchecked
}
/**
* The gas price this UserOp agrees to pay.
* Relayer/block builder might submit the TX with higher priorityFee, but the user should not.
* @param mUserOp - The userOp to get the gas price from.
*/
function getUserOpGasPrice(MemoryUserOp memory mUserOp) internal view returns (uint256) {
unchecked {
uint256 maxFeePerGas = mUserOp.maxFeePerGas;
uint256 maxPriorityFeePerGas = mUserOp.maxPriorityFeePerGas;
if (maxFeePerGas == maxPriorityFeePerGas) {
//legacy mode (for networks that don't support basefee opcode)
return maxFeePerGas;
}
return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee);
}
}
/**
* The offset of the given bytes in memory.
* @param data - The bytes to get the offset of.
*/
function getOffsetOfMemoryBytes(bytes memory data) internal pure returns (uint256 offset) {
assembly {
offset := data
}
}
/**
* The bytes in memory at the given offset.
* @param offset - The offset to get the bytes from.
*/
function getMemoryBytesFromOffset(uint256 offset) internal pure returns (bytes memory data) {
assembly ("memory-safe") {
data := offset
}
}
/// @inheritdoc IEntryPoint
// function delegateAndRevert(address target, bytes calldata data) external {
// (bool success, bytes memory ret) = target.delegatecall(data);
// revert DelegateAndRevert(success, ret);
// }
}// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.5;
import "account-abstraction/interfaces/PackedUserOperation.sol";
import "./IEntryPoint.sol";
interface IEntryPointSimulations is IEntryPoint {
struct TargetCallResult {
uint256 gasUsed;
bool success;
bytes returnData;
}
struct PaymasterDataResult {
uint256 paymasterVerificationGasLimit;
uint256 paymasterPostOpGasLimit;
}
// Return value of simulateHandleOp.
struct ExecutionResult {
uint256 preOpGas;
uint256 paid;
uint256 accountValidationData;
uint256 paymasterValidationData;
uint256 paymasterVerificationGasLimit;
uint256 paymasterPostOpGasLimit;
bool targetSuccess;
bytes targetResult;
}
/**
* Successful result from simulateValidation.
* If the account returns a signature aggregator the "aggregatorInfo" struct is filled in as well.
* @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.
*/
struct ValidationResult {
ReturnInfo returnInfo;
StakeInfo senderInfo;
StakeInfo factoryInfo;
StakeInfo paymasterInfo;
AggregatorStakeInfo aggregatorInfo;
}
/**
* Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp.
* @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.
* @return the validation result structure
*/
function simulateValidation(
PackedUserOperation calldata userOp
) external returns (ValidationResult memory);
/**
* Simulate full execution of a UserOperation (including both validation and target execution)
* 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.
* @return the execution result structure
*/
function simulateHandleOp(
PackedUserOperation calldata op
) external returns (ExecutionResult memory);
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.23;
/* solhint-disable no-inline-assembly */
import "../interfaces/PackedUserOperation.sol";
import {calldataKeccak, min} from "./Helpers.sol";
/**
* Utility functions helpful when working with UserOperation structs.
*/
library UserOperationLib {
uint256 public constant PAYMASTER_VALIDATION_GAS_OFFSET = 20;
uint256 public constant PAYMASTER_POSTOP_GAS_OFFSET = 36;
uint256 public constant PAYMASTER_DATA_OFFSET = 52;
/**
* Get sender from user operation data.
* @param userOp - The user operation data.
*/
function getSender(
PackedUserOperation 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.
* @param userOp - The user operation data.
*/
function gasPrice(
PackedUserOperation calldata userOp
) internal view returns (uint256) {
unchecked {
(uint256 maxPriorityFeePerGas, uint256 maxFeePerGas) = unpackUints(userOp.gasFees);
if (maxFeePerGas == maxPriorityFeePerGas) {
//legacy mode (for networks that don't support basefee opcode)
return maxFeePerGas;
}
return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee);
}
}
/**
* Pack the user operation data into bytes for hashing.
* @param userOp - The user operation data.
*/
function encode(
PackedUserOperation 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);
bytes32 accountGasLimits = userOp.accountGasLimits;
uint256 preVerificationGas = userOp.preVerificationGas;
bytes32 gasFees = userOp.gasFees;
bytes32 hashPaymasterAndData = calldataKeccak(userOp.paymasterAndData);
return abi.encode(
sender, nonce,
hashInitCode, hashCallData,
accountGasLimits, preVerificationGas, gasFees,
hashPaymasterAndData
);
}
function unpackUints(
bytes32 packed
) internal pure returns (uint256 high128, uint256 low128) {
return (uint128(bytes16(packed)), uint128(uint256(packed)));
}
//unpack just the high 128-bits from a packed value
function unpackHigh128(bytes32 packed) internal pure returns (uint256) {
return uint256(packed) >> 128;
}
// unpack just the low 128-bits from a packed value
function unpackLow128(bytes32 packed) internal pure returns (uint256) {
return uint128(uint256(packed));
}
function unpackMaxPriorityFeePerGas(PackedUserOperation calldata userOp)
internal pure returns (uint256) {
return unpackHigh128(userOp.gasFees);
}
function unpackMaxFeePerGas(PackedUserOperation calldata userOp)
internal pure returns (uint256) {
return unpackLow128(userOp.gasFees);
}
function unpackVerificationGasLimit(PackedUserOperation calldata userOp)
internal pure returns (uint256) {
return unpackHigh128(userOp.accountGasLimits);
}
function unpackCallGasLimit(PackedUserOperation calldata userOp)
internal pure returns (uint256) {
return unpackLow128(userOp.accountGasLimits);
}
function unpackPaymasterVerificationGasLimit(PackedUserOperation calldata userOp)
internal pure returns (uint256) {
return uint128(bytes16(userOp.paymasterAndData[PAYMASTER_VALIDATION_GAS_OFFSET : PAYMASTER_POSTOP_GAS_OFFSET]));
}
function unpackPostOpGasLimit(PackedUserOperation calldata userOp)
internal pure returns (uint256) {
return uint128(bytes16(userOp.paymasterAndData[PAYMASTER_POSTOP_GAS_OFFSET : PAYMASTER_DATA_OFFSET]));
}
function unpackPaymasterStaticFields(
bytes calldata paymasterAndData
) internal pure returns (address paymaster, uint256 validationGasLimit, uint256 postOpGasLimit) {
return (
address(bytes20(paymasterAndData[: PAYMASTER_VALIDATION_GAS_OFFSET])),
uint128(bytes16(paymasterAndData[PAYMASTER_VALIDATION_GAS_OFFSET : PAYMASTER_POSTOP_GAS_OFFSET])),
uint128(bytes16(paymasterAndData[PAYMASTER_POSTOP_GAS_OFFSET : PAYMASTER_DATA_OFFSET]))
);
}
/**
* Hash the user operation data.
* @param userOp - The user operation data.
*/
function hash(
PackedUserOperation calldata userOp
) internal pure returns (bytes32) {
return keccak256(encode(userOp));
}
}/**
** Account-Abstraction (EIP-4337) singleton EntryPoint implementation.
** Only one instance required on each chain.
**/
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.5;
/* solhint-disable avoid-low-level-calls */
/* solhint-disable no-inline-assembly */
/* solhint-disable reason-string */
import "./PackedUserOperation.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 if the UserOperation Paymaster's "postOp" call 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 PostOpRevertReason(
bytes32 indexed userOpHash,
address indexed sender,
uint256 nonce,
bytes revertReason
);
/**
* UserOp consumed more than prefund. The UserOperation is reverted, and no refund is made.
* @param userOpHash - The request unique identifier.
* @param sender - The sender of this request.
* @param nonce - The nonce used in the request.
*/
event UserOperationPrefundTooLow(
bytes32 indexed userOpHash,
address indexed sender,
uint256 nonce
);
/**
* 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.
* @param aggregator - The aggregator used for the following UserOperationEvents.
*/
event SignatureAggregatorChanged(address indexed aggregator);
/**
* A custom revert error of handleOps, to identify the offending op.
* 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.
* 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.
*/
error FailedOp(uint256 opIndex, string reason);
/**
* A custom revert error of handleOps, to report a revert by account or paymaster.
* @param opIndex - Index into the array of ops to the failed one (in simulateValidation, this is always zero).
* @param reason - Revert reason. see FailedOp(uint256,string), above
* @param inner - data from inner cought revert reason
* @dev note that inner is truncated to 2048 bytes
*/
error FailedOpWithRevert(uint256 opIndex, string reason, bytes inner);
error PostOpReverted(bytes returnData);
/**
* Error case when a signature aggregator fails to verify the aggregated signature it had created.
* @param aggregator The aggregator that failed to verify the signature
*/
error SignatureValidationFailed(address aggregator);
// Return value of getSenderAddress.
error SenderAddressResult(address sender);
// UserOps handled, per aggregator.
struct UserOpsPerAggregator {
PackedUserOperation[] userOps;
// Aggregator address
IAggregator aggregator;
// Aggregated signature
bytes signature;
}
/**
* Execute a batch of UserOperations.
* 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(
PackedUserOperation[] 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.
* @param userOp - The user operation to generate the request ID for.
* @return hash the hash of this UserOperation
*/
function getUserOpHash(
PackedUserOperation calldata userOp
) external view returns (bytes32);
/**
* Gas and return values during simulation.
* @param preOpGas - The gas used for validation (including preValidationGas)
* @param prefund - The required prefund for this operation
* @param accountValidationData - returned validationData from account.
* @param paymasterValidationData - return validationData from paymaster.
* @param paymasterContext - Returned by validatePaymasterUserOp (to be passed into postOp)
*/
struct ReturnInfo {
uint256 preOpGas;
uint256 prefund;
uint256 accountValidationData;
uint256 paymasterValidationData;
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;
error DelegateAndRevert(bool success, bytes ret);
/**
* Helper method for dry-run testing.
* @dev calling this method, the EntryPoint will make a delegatecall to the given data, and report (via revert) the result.
* The method always revert, so is only useful off-chain for dry run calls, in cases where state-override to replace
* actual EntryPoint code is less convenient.
* @param target a target contract to make a delegatecall from entrypoint
* @param data data to pass to target in a delegatecall
*/
function delegateAndRevert(address target, bytes calldata data) external;
}// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.5;
import "./PackedUserOperation.sol";
interface IAccount {
/**
* Validate user's signature and nonce
* the entryPoint will make the call to the recipient only if this validation call returns successfully.
* signature failure should be reported by returning SIG_VALIDATION_FAILED (1).
* This allows making a "simulation call" without a valid signature
* Other failures (e.g. nonce mismatch, or invalid signature format) should still revert to signal failure.
*
* @dev Must validate caller is the entryPoint.
* Must validate the signature and nonce
* @param userOp - The operation that is about to be executed.
* @param userOpHash - Hash of the user's request data. can be used as the basis for signature.
* @param missingAccountFunds - Missing funds on the account's deposit in the entrypoint.
* This is the minimum amount to transfer to the sender(entryPoint) to be
* able to make the call. The excess is left as a deposit in the entrypoint
* for future calls. Can be withdrawn anytime using "entryPoint.withdrawTo()".
* In case there is a paymaster in the request (or the current deposit is high
* enough), this value will be zero.
* @return validationData - Packaged ValidationData structure. use `_packValidationData` and
* `_unpackValidationData` to encode and decode.
* <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure,
* otherwise, an address of an "authorizer" contract.
* <6-byte> validUntil - Last timestamp this operation is valid. 0 for "indefinite"
* <6-byte> validAfter - First timestamp this operation is valid
* If an account doesn't use time-range, it is enough to
* return SIG_VALIDATION_FAILED value (1) for signature failure.
* Note that the validation code cannot use block.timestamp (or block.number) directly.
*/
function validateUserOp(
PackedUserOperation calldata userOp,
bytes32 userOpHash,
uint256 missingAccountFunds
) external returns (uint256 validationData);
}// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.5;
import "./PackedUserOperation.sol";
interface IAccountExecute {
/**
* Account may implement this execute method.
* passing this methodSig at the beginning of callData will cause the entryPoint to pass the full UserOp (and hash)
* to the account.
* The account should skip the methodSig, and use the callData (and optionally, other UserOp fields)
*
* @param userOp - The operation that was just validated.
* @param userOpHash - Hash of the user's request data.
*/
function executeUserOp(
PackedUserOperation calldata userOp,
bytes32 userOpHash
) external;
}// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.5;
import "./PackedUserOperation.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 {
// User op succeeded.
opSucceeded,
// User op reverted. Still has to pay for gas.
opReverted,
// Only used internally in the EntryPoint (cleanup after postOp reverts). Never calling paymaster with this value
postOpReverted
}
/**
* 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,
* other values are invalid for paymaster.
* <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(
PackedUserOperation 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. The paymaster still has to pay for gas.
* postOpReverted - never passed in a call to postOp().
* @param context - The context value returned by validatePaymasterUserOp
* @param actualGasCost - Actual gas used so far (without this postOp call).
* @param actualUserOpFeePerGas - the gas price this UserOp pays. This value is based on the UserOp's maxFeePerGas
* and maxPriorityFee (and basefee)
* It is not the same as tx.gasprice, which is what the bundler pays.
*/
function postOp(
PostOpMode mode,
bytes calldata context,
uint256 actualGasCost,
uint256 actualUserOpFeePerGas
) external;
}/**
** Account-Abstraction (EIP-4337) singleton EntryPoint implementation.
** Only one instance required on each chain.
**/
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.5;
/* solhint-disable avoid-low-level-calls */
/* solhint-disable no-inline-assembly */
/* solhint-disable reason-string */
import "account-abstraction/interfaces/PackedUserOperation.sol";
import "account-abstraction/interfaces/IStakeManager.sol";
import "account-abstraction/interfaces/IAggregator.sol";
import "account-abstraction/interfaces/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 if the UserOperation Paymaster's "postOp" call 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 PostOpRevertReason(
bytes32 indexed userOpHash,
address indexed sender,
uint256 nonce,
bytes revertReason
);
/**
* UserOp consumed more than prefund. The UserOperation is reverted, and no refund is made.
* @param userOpHash - The request unique identifier.
* @param sender - The sender of this request.
* @param nonce - The nonce used in the request.
*/
event UserOperationPrefundTooLow(
bytes32 indexed userOpHash,
address indexed sender,
uint256 nonce
);
/**
* 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.
* @param aggregator - The aggregator used for the following UserOperationEvents.
*/
event SignatureAggregatorChanged(address indexed aggregator);
/**
* A custom revert error of handleOps, to identify the offending op.
* 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.
* 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.
*/
error FailedOp(uint256 opIndex, string reason);
/**
* A custom revert error of handleOps, to report a revert by account or paymaster.
* @param opIndex - Index into the array of ops to the failed one (in simulateValidation, this is always zero).
* @param reason - Revert reason. see FailedOp(uint256,string), above
* @param inner - data from inner cought revert reason
* @dev note that inner is truncated to 2048 bytes
*/
error FailedOpWithRevert(uint256 opIndex, string reason, bytes inner);
error PostOpReverted(bytes returnData);
/**
* Error case when a signature aggregator fails to verify the aggregated signature it had created.
* @param aggregator The aggregator that failed to verify the signature
*/
error SignatureValidationFailed(address aggregator);
// Return value of getSenderAddress.
error SenderAddressResult(address sender);
// UserOps handled, per aggregator.
struct UserOpsPerAggregator {
PackedUserOperation[] userOps;
// Aggregator address
IAggregator aggregator;
// Aggregated signature
bytes signature;
}
/**
* Execute a batch of UserOperations.
* 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(
// PackedUserOperation[] 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.
* @param userOp - The user operation to generate the request ID for.
* @return hash the hash of this UserOperation
*/
function getUserOpHash(
PackedUserOperation calldata userOp
) external view returns (bytes32);
/**
* Gas and return values during simulation.
* @param preOpGas - The gas used for validation (including preValidationGas)
* @param prefund - The required prefund for this operation
* @param accountValidationData - returned validationData from account.
* @param paymasterValidationData - return validationData from paymaster.
* @param paymasterContext - Returned by validatePaymasterUserOp (to be passed into postOp)
*/
struct ReturnInfo {
uint256 preOpGas;
uint256 prefund;
uint256 accountValidationData;
uint256 paymasterValidationData;
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;
// error DelegateAndRevert(bool success, bytes ret);
/**
* Helper method for dry-run testing.
* @dev calling this method, the EntryPoint will make a delegatecall to the given data, and report (via revert) the result.
* The method always revert, so is only useful off-chain for dry run calls, in cases where state-override to replace
* actual EntryPoint code is less convenient.
* @param target a target contract to make a delegatecall from entrypoint
* @param data data to pass to target in a delegatecall
*/
// function delegateAndRevert(address target, bytes calldata data) external;
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity ^0.8.23;
// solhint-disable no-inline-assembly
/**
* Utility functions helpful when making different kinds of contract calls in Solidity.
*/
library Exec {
function call(
address to,
uint256 value,
bytes memory data,
uint256 txGas
) internal returns (bool success) {
assembly ("memory-safe") {
success := call(txGas, to, value, add(data, 0x20), mload(data), 0, 0)
}
}
function staticcall(
address to,
bytes memory data,
uint256 txGas
) internal view returns (bool success) {
assembly ("memory-safe") {
success := staticcall(txGas, to, add(data, 0x20), mload(data), 0, 0)
}
}
function delegateCall(
address to,
bytes memory data,
uint256 txGas
) internal returns (bool success) {
assembly ("memory-safe") {
success := delegatecall(txGas, to, add(data, 0x20), mload(data), 0, 0)
}
}
// get returned data from last call or calldelegate
function getReturnData(uint256 maxLen) internal pure returns (bytes memory returnData) {
assembly ("memory-safe") {
let len := returndatasize()
if gt(len, maxLen) {
len := maxLen
}
let ptr := mload(0x40)
mstore(0x40, add(ptr, add(len, 0x20)))
mstore(ptr, len)
returndatacopy(add(ptr, 0x20), 0, len)
returnData := ptr
}
}
// revert with explicit byte array (probably reverted info from call)
function revertWithData(bytes memory returnData) internal pure {
assembly ("memory-safe") {
revert(add(returnData, 32), mload(returnData))
}
}
function callAndRevert(address to, bytes memory data, uint256 maxLen) internal {
bool success = call(to,0,data,gasleft());
if (!success) {
revertWithData(getReturnData(maxLen));
}
}
}// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.23;
import "../interfaces/IStakeManager.sol";
/* solhint-disable avoid-low-level-calls */
/* solhint-disable not-rely-on-time */
/**
* 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 a paymaster.
*/
abstract contract StakeManager is IStakeManager {
/// maps paymaster to their deposits and stakes
mapping(address => DepositInfo) public deposits;
/// @inheritdoc IStakeManager
function getDepositInfo(
address account
) public view returns (DepositInfo memory info) {
return deposits[account];
}
/**
* Internal method to return just the stake info.
* @param addr - The account to query.
*/
function _getStakeInfo(
address addr
) internal view returns (StakeInfo memory info) {
DepositInfo storage depositInfo = deposits[addr];
info.stake = depositInfo.stake;
info.unstakeDelaySec = depositInfo.unstakeDelaySec;
}
/// @inheritdoc IStakeManager
function balanceOf(address account) public view returns (uint256) {
return deposits[account].deposit;
}
receive() external payable {
depositTo(msg.sender);
}
/**
* Increments an account's deposit.
* @param account - The account to increment.
* @param amount - The amount to increment by.
* @return the updated deposit of this account
*/
function _incrementDeposit(address account, uint256 amount) internal returns (uint256) {
DepositInfo storage info = deposits[account];
uint256 newAmount = info.deposit + amount;
info.deposit = newAmount;
return newAmount;
}
/**
* Add to the deposit of the given account.
* @param account - The account to add to.
*/
function depositTo(address account) public virtual payable {
uint256 newDeposit = _incrementDeposit(account, msg.value);
emit Deposited(account, newDeposit);
}
/**
* 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) public payable {
DepositInfo storage info = deposits[msg.sender];
require(unstakeDelaySec > 0, "must specify unstake delay");
require(
unstakeDelaySec >= info.unstakeDelaySec,
"cannot decrease unstake time"
);
uint256 stake = info.stake + msg.value;
require(stake > 0, "no stake specified");
require(stake <= type(uint112).max, "stake overflow");
deposits[msg.sender] = DepositInfo(
info.deposit,
true,
uint112(stake),
unstakeDelaySec,
0
);
emit StakeLocked(msg.sender, stake, unstakeDelaySec);
}
/**
* Attempt to unlock the stake.
* The value can be withdrawn (using withdrawStake) after the unstake delay.
*/
function unlockStake() external {
DepositInfo storage info = deposits[msg.sender];
require(info.unstakeDelaySec != 0, "not staked");
require(info.staked, "already unstaking");
uint48 withdrawTime = uint48(block.timestamp) + info.unstakeDelaySec;
info.withdrawTime = withdrawTime;
info.staked = false;
emit StakeUnlocked(msg.sender, withdrawTime);
}
/**
* 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 {
DepositInfo storage info = deposits[msg.sender];
uint256 stake = info.stake;
require(stake > 0, "No stake to withdraw");
require(info.withdrawTime > 0, "must call unlockStake() first");
require(
info.withdrawTime <= block.timestamp,
"Stake withdrawal is not due"
);
info.unstakeDelaySec = 0;
info.withdrawTime = 0;
info.stake = 0;
emit StakeWithdrawn(msg.sender, withdrawAddress, stake);
(bool success,) = withdrawAddress.call{value: stake}("");
require(success, "failed to withdraw stake");
}
/**
* 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 {
DepositInfo storage info = deposits[msg.sender];
require(withdrawAmount <= info.deposit, "Withdraw amount too large");
info.deposit = info.deposit - withdrawAmount;
emit Withdrawn(msg.sender, withdrawAddress, withdrawAmount);
(bool success,) = withdrawAddress.call{value: withdrawAmount}("");
require(success, "failed to withdraw");
}
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.23;
/**
* Helper contract for EntryPoint, to call userOp.initCode from a "neutral" address,
* which is explicitly not the entryPoint itself.
*/
contract SenderCreator {
/**
* Call the "initCode" factory to create and return the sender account address.
* @param initCode - The initCode value from a UserOp. contains 20 bytes of factory address,
* followed by calldata.
* @return sender - The returned address of the created account, or zero address on failure.
*/
function createSender(
bytes calldata initCode
) external returns (address sender) {
address factory = address(bytes20(initCode[0:20]));
bytes memory initCallData = initCode[20:];
bool success;
/* solhint-disable no-inline-assembly */
assembly ("memory-safe") {
success := call(
gas(),
factory,
0,
add(initCallData, 0x20),
mload(initCallData),
0,
32
)
sender := mload(0)
}
if (!success) {
sender = address(0);
}
}
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.23;
/* solhint-disable no-inline-assembly */
/*
* For simulation purposes, validateUserOp (and validatePaymasterUserOp)
* must return this value in case of signature failure, instead of revert.
*/
uint256 constant SIG_VALIDATION_FAILED = 1;
/*
* For simulation purposes, validateUserOp (and validatePaymasterUserOp)
* return this value on success.
*/
uint256 constant SIG_VALIDATION_SUCCESS = 0;
/**
* Returned data from validateUserOp.
* validateUserOp returns a uint256, which 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.
* @param validationData - The packed validation data.
*/
function _parseValidationData(
uint256 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);
}
/**
* 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 ("memory-safe") {
let mem := mload(0x40)
let len := data.length
calldatacopy(mem, data.offset, len)
ret := keccak256(mem, len)
}
}
/**
* The minimum of two numbers.
* @param a - First number.
* @param b - Second number.
*/
function min(uint256 a, uint256 b) pure returns (uint256) {
return a < b ? a : b;
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.23;
import "../interfaces/INonceManager.sol";
/**
* nonce management functionality
*/
abstract contract NonceManager is INonceManager {
/**
* The next valid sequence number for a given nonce key.
*/
mapping(address => mapping(uint192 => uint256)) public nonceSequenceNumber;
/// @inheritdoc INonceManager
function getNonce(address sender, uint192 key)
public view override returns (uint256 nonce) {
return nonceSequenceNumber[sender][key] | (uint256(key) << 64);
}
// allow an account to manually increment its own nonce.
// (mainly so that during construction nonce can be made non-zero,
// to "absorb" the gas cost of first nonce increment to 1st transaction (construction),
// not to 2nd transaction)
function incrementNonce(uint192 key) public override {
nonceSequenceNumber[msg.sender][key]++;
}
/**
* validate nonce uniqueness for this account.
* called just after validateUserOp()
* @return true if the nonce was incremented successfully.
* false if the current nonce doesn't match the given one.
*/
function _validateAndUpdateNonce(address sender, uint256 nonce) internal returns (bool) {
uint192 key = uint192(nonce >> 64);
uint64 seq = uint64(nonce);
return nonceSequenceNumber[sender][key]++ == seq;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)
pragma solidity ^0.8.20;
import {IERC165} from "./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol)
pragma solidity ^0.8.20;
/**
* @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;
/**
* @dev Unauthorized reentrant call.
*/
error ReentrancyGuardReentrantCall();
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
if (_status == ENTERED) {
revert ReentrancyGuardReentrantCall();
}
// 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;
}
/**
* @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
* `nonReentrant` function in the call stack.
*/
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == ENTERED;
}
}// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.5;
/**
* 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 accountGasLimits - Packed gas limits for validateUserOp and gas limit passed to the callData method call.
* @param preVerificationGas - Gas not calculated by the handleOps method, but added to the gas paid.
* Covers batch overhead.
* @param gasFees - packed gas fields maxPriorityFeePerGas and maxFeePerGas - Same as EIP-1559 gas parameters.
* @param paymasterAndData - If set, this field holds the paymaster address, verification gas limit, postOp gas limit and paymaster-specific extra 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 PackedUserOperation {
address sender;
uint256 nonce;
bytes initCode;
bytes callData;
bytes32 accountGasLimits;
uint256 preVerificationGas;
bytes32 gasFees;
bytes paymasterAndData;
bytes signature;
}// SPDX-License-Identifier: GPL-3.0-only
pragma solidity >=0.7.5;
/**
* 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 fits into one cell (used during handleOp)
* and the rest fit into a 2nd cell (used during stake/unstake)
* - 112 bit allows for 10^15 eth
* - 48 bit for full timestamp
* - 32 bit allows 150 years for unstake delay
*/
struct DepositInfo {
uint256 deposit;
bool staked;
uint112 stake;
uint32 unstakeDelaySec;
uint48 withdrawTime;
}
// API struct used by getStakeInfo and simulateValidation.
struct StakeInfo {
uint256 stake;
uint256 unstakeDelaySec;
}
/**
* Get deposit info.
* @param account - The account to query.
* @return info - Full deposit information of given account.
*/
function getDepositInfo(
address account
) external view returns (DepositInfo memory info);
/**
* Get account balance.
* @param account - The account to query.
* @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.
* @param account - The account to add to.
*/
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.7.5;
import "./PackedUserOperation.sol";
/**
* Aggregated Signatures validator.
*/
interface IAggregator {
/**
* Validate aggregated signature.
* Revert if the aggregated signature does not match the given list of operations.
* @param userOps - Array of UserOperations to validate the signature for.
* @param signature - The aggregated signature.
*/
function validateSignatures(
PackedUserOperation[] calldata userOps,
bytes calldata signature
) external view;
/**
* Validate signature of a single userOp.
* This method should be called by bundler after EntryPointSimulation.simulateValidation() returns
* the aggregator this account uses.
* 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(
PackedUserOperation 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(
PackedUserOperation[] calldata userOps
) external view returns (bytes memory aggregatedSignature);
}// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.5;
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: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}{
"remappings": [
"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
"account-abstraction-v6/=lib/account-abstraction-v6/contracts/",
"account-abstraction/=lib/account-abstraction/contracts/",
"ds-test/=lib/openzeppelin-contracts/lib/forge-std/lib/ds-test/src/",
"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
"forge-std/=lib/forge-std/src/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"evmVersion": "london",
"viaIR": true,
"libraries": {},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"opIndex","type":"uint256"},{"internalType":"string","name":"reason","type":"string"}],"name":"FailedOp","type":"error"},{"inputs":[{"internalType":"uint256","name":"opIndex","type":"uint256"},{"internalType":"string","name":"reason","type":"string"},{"internalType":"bytes","name":"inner","type":"bytes"}],"name":"FailedOpWithRevert","type":"error"},{"inputs":[{"internalType":"bytes","name":"returnData","type":"bytes"}],"name":"PostOpReverted","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"SenderAddressResult","type":"error"},{"inputs":[{"internalType":"address","name":"aggregator","type":"address"}],"name":"SignatureValidationFailed","type":"error"},{"inputs":[{"internalType":"uint256","name":"optimalGas","type":"uint256"},{"internalType":"uint256","name":"minGas","type":"uint256"},{"internalType":"uint256","name":"maxGas","type":"uint256"}],"name":"SimulationOutOfGas","type":"error"},{"inputs":[{"internalType":"uint256","name":"remainingGas","type":"uint256"}],"name":"innerCallResult","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"userOpHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"address","name":"factory","type":"address"},{"indexed":false,"internalType":"address","name":"paymaster","type":"address"}],"name":"AccountDeployed","type":"event"},{"anonymous":false,"inputs":[],"name":"BeforeExecution","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"totalDeposit","type":"uint256"}],"name":"Deposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"userOpHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"nonce","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"revertReason","type":"bytes"}],"name":"PostOpRevertReason","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"aggregator","type":"address"}],"name":"SignatureAggregatorChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"totalStaked","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"unstakeDelaySec","type":"uint256"}],"name":"StakeLocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"withdrawTime","type":"uint256"}],"name":"StakeUnlocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"address","name":"withdrawAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"StakeWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"userOpHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"paymaster","type":"address"},{"indexed":false,"internalType":"uint256","name":"nonce","type":"uint256"},{"indexed":false,"internalType":"bool","name":"success","type":"bool"},{"indexed":false,"internalType":"uint256","name":"actualGasCost","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"actualGasUsed","type":"uint256"}],"name":"UserOperationEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"userOpHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"UserOperationPrefundTooLow","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"userOpHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"nonce","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"revertReason","type":"bytes"}],"name":"UserOperationRevertReason","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"address","name":"withdrawAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdrawn","type":"event"},{"inputs":[{"internalType":"uint32","name":"unstakeDelaySec","type":"uint32"}],"name":"addStake","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"depositTo","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"deposits","outputs":[{"internalType":"uint256","name":"deposit","type":"uint256"},{"internalType":"bool","name":"staked","type":"bool"},{"internalType":"uint112","name":"stake","type":"uint112"},{"internalType":"uint32","name":"unstakeDelaySec","type":"uint32"},{"internalType":"uint48","name":"withdrawTime","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getDepositInfo","outputs":[{"components":[{"internalType":"uint256","name":"deposit","type":"uint256"},{"internalType":"bool","name":"staked","type":"bool"},{"internalType":"uint112","name":"stake","type":"uint112"},{"internalType":"uint32","name":"unstakeDelaySec","type":"uint32"},{"internalType":"uint48","name":"withdrawTime","type":"uint48"}],"internalType":"struct IStakeManager.DepositInfo","name":"info","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint192","name":"key","type":"uint192"}],"name":"getNonce","outputs":[{"internalType":"uint256","name":"nonce","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":"bytes32","name":"accountGasLimits","type":"bytes32"},{"internalType":"uint256","name":"preVerificationGas","type":"uint256"},{"internalType":"bytes32","name":"gasFees","type":"bytes32"},{"internalType":"bytes","name":"paymasterAndData","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct PackedUserOperation","name":"userOp","type":"tuple"}],"name":"getUserOpHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint192","name":"key","type":"uint192"}],"name":"incrementNonce","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"callData","type":"bytes"},{"components":[{"components":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"verificationGasLimit","type":"uint256"},{"internalType":"uint256","name":"callGasLimit","type":"uint256"},{"internalType":"uint256","name":"paymasterVerificationGasLimit","type":"uint256"},{"internalType":"uint256","name":"paymasterPostOpGasLimit","type":"uint256"},{"internalType":"uint256","name":"preVerificationGas","type":"uint256"},{"internalType":"address","name":"paymaster","type":"address"},{"internalType":"uint256","name":"maxFeePerGas","type":"uint256"},{"internalType":"uint256","name":"maxPriorityFeePerGas","type":"uint256"}],"internalType":"struct EntryPoint.MemoryUserOp","name":"mUserOp","type":"tuple"},{"internalType":"bytes32","name":"userOpHash","type":"bytes32"},{"internalType":"uint256","name":"prefund","type":"uint256"},{"internalType":"uint256","name":"contextOffset","type":"uint256"},{"internalType":"uint256","name":"preOpGas","type":"uint256"}],"internalType":"struct EntryPoint.UserOpInfo","name":"opInfo","type":"tuple"},{"internalType":"bytes","name":"context","type":"bytes"},{"internalType":"uint256","name":"preGas","type":"uint256"}],"name":"innerHandleOp","outputs":[{"internalType":"uint256","name":"actualGasCost","type":"uint256"},{"internalType":"uint256","name":"paymasterPostOpGasLimit","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint192","name":"","type":"uint192"}],"name":"nonceSequenceNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"entryPoint","type":"address"},{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"gas","type":"uint256"}],"name":"simulateCall","outputs":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"bytes","name":"result","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"gas","type":"uint256"}],"name":"simulateCallAndRevert","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"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":"bytes32","name":"accountGasLimits","type":"bytes32"},{"internalType":"uint256","name":"preVerificationGas","type":"uint256"},{"internalType":"bytes32","name":"gasFees","type":"bytes32"},{"internalType":"bytes","name":"paymasterAndData","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct PackedUserOperation","name":"op","type":"tuple"},{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"targetCallData","type":"bytes"}],"internalType":"struct SimulationArgs[]","name":"queuedUserOps","type":"tuple[]"},{"components":[{"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":"bytes32","name":"accountGasLimits","type":"bytes32"},{"internalType":"uint256","name":"preVerificationGas","type":"uint256"},{"internalType":"bytes32","name":"gasFees","type":"bytes32"},{"internalType":"bytes","name":"paymasterAndData","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct PackedUserOperation","name":"op","type":"tuple"},{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"targetCallData","type":"bytes"}],"internalType":"struct SimulationArgs","name":"targetUserOp","type":"tuple"},{"internalType":"address","name":"entryPoint","type":"address"},{"internalType":"uint256","name":"initialMinGas","type":"uint256"},{"internalType":"uint256","name":"toleranceDelta","type":"uint256"},{"internalType":"uint256","name":"gasAllowance","type":"uint256"}],"name":"simulateCallData","outputs":[{"components":[{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"internalType":"bool","name":"success","type":"bool"},{"internalType":"bytes","name":"returnData","type":"bytes"}],"internalType":"struct IEntryPointSimulations.TargetCallResult","name":"","type":"tuple"}],"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":"bytes32","name":"accountGasLimits","type":"bytes32"},{"internalType":"uint256","name":"preVerificationGas","type":"uint256"},{"internalType":"bytes32","name":"gasFees","type":"bytes32"},{"internalType":"bytes","name":"paymasterAndData","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct PackedUserOperation","name":"op","type":"tuple"}],"name":"simulateHandleOp","outputs":[{"components":[{"internalType":"uint256","name":"preOpGas","type":"uint256"},{"internalType":"uint256","name":"paid","type":"uint256"},{"internalType":"uint256","name":"accountValidationData","type":"uint256"},{"internalType":"uint256","name":"paymasterValidationData","type":"uint256"},{"internalType":"uint256","name":"paymasterVerificationGasLimit","type":"uint256"},{"internalType":"uint256","name":"paymasterPostOpGasLimit","type":"uint256"},{"internalType":"bool","name":"targetSuccess","type":"bool"},{"internalType":"bytes","name":"targetResult","type":"bytes"}],"internalType":"struct IEntryPointSimulations.ExecutionResult","name":"","type":"tuple"}],"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":"bytes32","name":"accountGasLimits","type":"bytes32"},{"internalType":"uint256","name":"preVerificationGas","type":"uint256"},{"internalType":"bytes32","name":"gasFees","type":"bytes32"},{"internalType":"bytes","name":"paymasterAndData","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct PackedUserOperation[]","name":"ops","type":"tuple[]"}],"name":"simulateHandleOpBulk","outputs":[{"components":[{"internalType":"uint256","name":"preOpGas","type":"uint256"},{"internalType":"uint256","name":"paid","type":"uint256"},{"internalType":"uint256","name":"accountValidationData","type":"uint256"},{"internalType":"uint256","name":"paymasterValidationData","type":"uint256"},{"internalType":"uint256","name":"paymasterVerificationGasLimit","type":"uint256"},{"internalType":"uint256","name":"paymasterPostOpGasLimit","type":"uint256"},{"internalType":"bool","name":"targetSuccess","type":"bool"},{"internalType":"bytes","name":"targetResult","type":"bytes"}],"internalType":"struct IEntryPointSimulations.ExecutionResult[]","name":"","type":"tuple[]"}],"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":"bytes32","name":"accountGasLimits","type":"bytes32"},{"internalType":"uint256","name":"preVerificationGas","type":"uint256"},{"internalType":"bytes32","name":"gasFees","type":"bytes32"},{"internalType":"bytes","name":"paymasterAndData","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct PackedUserOperation[]","name":"ops","type":"tuple[]"}],"name":"simulateHandleOpLast","outputs":[{"components":[{"internalType":"uint256","name":"preOpGas","type":"uint256"},{"internalType":"uint256","name":"paid","type":"uint256"},{"internalType":"uint256","name":"accountValidationData","type":"uint256"},{"internalType":"uint256","name":"paymasterValidationData","type":"uint256"},{"internalType":"uint256","name":"paymasterVerificationGasLimit","type":"uint256"},{"internalType":"uint256","name":"paymasterPostOpGasLimit","type":"uint256"},{"internalType":"bool","name":"targetSuccess","type":"bool"},{"internalType":"bytes","name":"targetResult","type":"bytes"}],"internalType":"struct IEntryPointSimulations.ExecutionResult","name":"","type":"tuple"}],"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":"bytes32","name":"accountGasLimits","type":"bytes32"},{"internalType":"uint256","name":"preVerificationGas","type":"uint256"},{"internalType":"bytes32","name":"gasFees","type":"bytes32"},{"internalType":"bytes","name":"paymasterAndData","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct PackedUserOperation","name":"userOp","type":"tuple"}],"name":"simulateValidation","outputs":[{"components":[{"components":[{"internalType":"uint256","name":"preOpGas","type":"uint256"},{"internalType":"uint256","name":"prefund","type":"uint256"},{"internalType":"uint256","name":"accountValidationData","type":"uint256"},{"internalType":"uint256","name":"paymasterValidationData","type":"uint256"},{"internalType":"bytes","name":"paymasterContext","type":"bytes"}],"internalType":"struct IEntryPoint.ReturnInfo","name":"returnInfo","type":"tuple"},{"components":[{"internalType":"uint256","name":"stake","type":"uint256"},{"internalType":"uint256","name":"unstakeDelaySec","type":"uint256"}],"internalType":"struct IStakeManager.StakeInfo","name":"senderInfo","type":"tuple"},{"components":[{"internalType":"uint256","name":"stake","type":"uint256"},{"internalType":"uint256","name":"unstakeDelaySec","type":"uint256"}],"internalType":"struct IStakeManager.StakeInfo","name":"factoryInfo","type":"tuple"},{"components":[{"internalType":"uint256","name":"stake","type":"uint256"},{"internalType":"uint256","name":"unstakeDelaySec","type":"uint256"}],"internalType":"struct IStakeManager.StakeInfo","name":"paymasterInfo","type":"tuple"},{"components":[{"internalType":"address","name":"aggregator","type":"address"},{"components":[{"internalType":"uint256","name":"stake","type":"uint256"},{"internalType":"uint256","name":"unstakeDelaySec","type":"uint256"}],"internalType":"struct IStakeManager.StakeInfo","name":"stakeInfo","type":"tuple"}],"internalType":"struct IEntryPoint.AggregatorStakeInfo","name":"aggregatorInfo","type":"tuple"}],"internalType":"struct IEntryPointSimulations.ValidationResult","name":"","type":"tuple"}],"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":"bytes32","name":"accountGasLimits","type":"bytes32"},{"internalType":"uint256","name":"preVerificationGas","type":"uint256"},{"internalType":"bytes32","name":"gasFees","type":"bytes32"},{"internalType":"bytes","name":"paymasterAndData","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct PackedUserOperation[]","name":"userOps","type":"tuple[]"}],"name":"simulateValidationBulk","outputs":[{"components":[{"components":[{"internalType":"uint256","name":"preOpGas","type":"uint256"},{"internalType":"uint256","name":"prefund","type":"uint256"},{"internalType":"uint256","name":"accountValidationData","type":"uint256"},{"internalType":"uint256","name":"paymasterValidationData","type":"uint256"},{"internalType":"bytes","name":"paymasterContext","type":"bytes"}],"internalType":"struct IEntryPoint.ReturnInfo","name":"returnInfo","type":"tuple"},{"components":[{"internalType":"uint256","name":"stake","type":"uint256"},{"internalType":"uint256","name":"unstakeDelaySec","type":"uint256"}],"internalType":"struct IStakeManager.StakeInfo","name":"senderInfo","type":"tuple"},{"components":[{"internalType":"uint256","name":"stake","type":"uint256"},{"internalType":"uint256","name":"unstakeDelaySec","type":"uint256"}],"internalType":"struct IStakeManager.StakeInfo","name":"factoryInfo","type":"tuple"},{"components":[{"internalType":"uint256","name":"stake","type":"uint256"},{"internalType":"uint256","name":"unstakeDelaySec","type":"uint256"}],"internalType":"struct IStakeManager.StakeInfo","name":"paymasterInfo","type":"tuple"},{"components":[{"internalType":"address","name":"aggregator","type":"address"},{"components":[{"internalType":"uint256","name":"stake","type":"uint256"},{"internalType":"uint256","name":"unstakeDelaySec","type":"uint256"}],"internalType":"struct IStakeManager.StakeInfo","name":"stakeInfo","type":"tuple"}],"internalType":"struct IEntryPoint.AggregatorStakeInfo","name":"aggregatorInfo","type":"tuple"}],"internalType":"struct IEntryPointSimulations.ValidationResult[]","name":"","type":"tuple[]"}],"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":"bytes32","name":"accountGasLimits","type":"bytes32"},{"internalType":"uint256","name":"preVerificationGas","type":"uint256"},{"internalType":"bytes32","name":"gasFees","type":"bytes32"},{"internalType":"bytes","name":"paymasterAndData","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct PackedUserOperation[]","name":"userOps","type":"tuple[]"}],"name":"simulateValidationLast","outputs":[{"components":[{"components":[{"internalType":"uint256","name":"preOpGas","type":"uint256"},{"internalType":"uint256","name":"prefund","type":"uint256"},{"internalType":"uint256","name":"accountValidationData","type":"uint256"},{"internalType":"uint256","name":"paymasterValidationData","type":"uint256"},{"internalType":"bytes","name":"paymasterContext","type":"bytes"}],"internalType":"struct IEntryPoint.ReturnInfo","name":"returnInfo","type":"tuple"},{"components":[{"internalType":"uint256","name":"stake","type":"uint256"},{"internalType":"uint256","name":"unstakeDelaySec","type":"uint256"}],"internalType":"struct IStakeManager.StakeInfo","name":"senderInfo","type":"tuple"},{"components":[{"internalType":"uint256","name":"stake","type":"uint256"},{"internalType":"uint256","name":"unstakeDelaySec","type":"uint256"}],"internalType":"struct IStakeManager.StakeInfo","name":"factoryInfo","type":"tuple"},{"components":[{"internalType":"uint256","name":"stake","type":"uint256"},{"internalType":"uint256","name":"unstakeDelaySec","type":"uint256"}],"internalType":"struct IStakeManager.StakeInfo","name":"paymasterInfo","type":"tuple"},{"components":[{"internalType":"address","name":"aggregator","type":"address"},{"components":[{"internalType":"uint256","name":"stake","type":"uint256"},{"internalType":"uint256","name":"unstakeDelaySec","type":"uint256"}],"internalType":"struct IStakeManager.StakeInfo","name":"stakeInfo","type":"tuple"}],"internalType":"struct IEntryPoint.AggregatorStakeInfo","name":"aggregatorInfo","type":"tuple"}],"internalType":"struct IEntryPointSimulations.ValidationResult","name":"","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unlockStake","outputs":[],"stateMutability":"nonpayable","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":"withdrawAmount","type":"uint256"}],"name":"withdrawTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
60c080604052346100cc5760016002556101888181016001600160401b038111838210176100b6578291613994833903906000f080156100aa576080523060a0526100486100d1565b600081526020810190600082528060206100606100d1565b600081520152600380546001600160a01b031916905551600455516005556040516138a390816100f1823960805181505060a0518181816108ef01528181611d460152611ebd0152f35b6040513d6000823e3d90fd5b634e487b7160e01b600052604160045260246000fd5b600080fd5b60408051919082016001600160401b038111838210176100b65760405256fe60806040526004361015610023575b361561001957600080fd5b61002161252b565b005b60003560e01c80630396cb60146101835780630bd28e3b1461017e5780630da82661146101795780630dbfc6bd146101745780630f019dea1461016f5780631b2e01b81461016a578063205c28781461016557806322cdde4c14610160578063263934db1461015b57806330ec25d11461015657806335567e1a14610151578063444034731461014c5780635287ce12146101475780635787f48b146101425780635895273b1461013d57806370a0823114610138578063b760faf914610133578063bb9fe6bf1461012e578063c23a5cea14610129578063c3bce00914610124578063fc7e286d1461011f5763fe2171cb0361000e5761130b565b611280565b611253565b611151565b61104f565b611024565b610fe7565b610fba565b610f35565b610df7565b610d7a565b610d11565b610c93565b610b7c565b610b5c565b610a3e565b6109db565b61083d565b610779565b610554565b610360565b60203660031901126103455760043563ffffffff811690818103610345576103407fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c01916103226102436102336101eb3360018060a01b03166000526000602052604060002090565b966101f781151561135b565b61022460018901549161021d6102148463ffffffff9060781c1690565b63ffffffff1690565b11156113a7565b60081c6001600160701b031690565b6001600160701b03349116611426565b9461024f861515611433565b6102626001600160701b03871115611474565b5461026b61045e565b908152600160208201526001600160701b038616604082015263ffffffff8316606082015260006080820181905233815260208190526040902081518155602082015160019091018054604084015160608501516080909501516001600160c81b031990921660ff941515949094169390931760089390931b6effffffffffffffffffffffffffff00169290921760789390931b63ffffffff60781b169290921760989190911b65ffffffffffff60981b16179055565b6040805194855263ffffffff90911660208501523393918291820190565b0390a2005b600080fd5b602435906001600160c01b038216820361034557565b34610345576020366003190112610345576004356001600160c01b0381168103610345573360009081526001602090815260408083206001600160c01b039094168352929052206103b181546114b1565b9055005b634e487b7160e01b600052604160045260246000fd5b60a081019081106001600160401b038211176103e657604052565b6103b5565b604081019081106001600160401b038211176103e657604052565b606081019081106001600160401b038211176103e657604052565b61014081019081106001600160401b038211176103e657604052565b90601f801991011681019081106001600160401b038211176103e657604052565b6040519061046d60a08361043d565b565b6040519061046d6101408361043d565b6040519061046d60608361043d565b6040519061046d6101008361043d565b6040519061046d60408361043d565b6001600160401b0381116103e657601f01601f191660200190565b9291926104d4826104ad565b916104e2604051938461043d565b829481845281830111610345578281602093846000960137010152565b9080601f830112156103455781602061051a933591016104c8565b90565b6001600160a01b0381160361034557565b6024359061046d8261051d565b610104359061046d8261051d565b359061046d8261051d565b3461034557610220366003190112610345576004356001600160401b038111610345576105859036906004016104ff565b3660231901906101c0821261034557610140604051926105a4846103cb565b12610345576105b161046f565b6105b961052e565b815260443560208201526064356040820152608435606082015260a435608082015260c43560a082015260e43560c08201526105f361053b565b60e0820152610124356101008201526101443561012082015282526101643560208301526101843560408301526101a43560608301526101c43560808301526101e435916001600160401b038311610345576106566106619336906004016104ff565b9061020435926114d7565b60408051928352602083019190915290f35b0390f35b9181601f84011215610345578235916001600160401b038311610345576020808501948460051b01011161034557565b602060031982011261034557600435906001600160401b038211610345576106d191600401610677565b9091565b60005b8381106106e85750506000910152565b81810151838201526020016106d8565b90602091610711815180928185528580860191016106d5565b601f01601f1916010190565b9061010060e061051a93805184526020810151602085015260408101516040850152606081015160608501526080810151608085015260a081015160a085015260c0810151151560c08501520151918160e082015201906106f8565b346103455761079061078a366106a7565b90611719565b6040518091602082016020835281518091526040830190602060408260051b8601019301916000905b8282106107c857505050500390f35b919360019193955060206107e78192603f198a8203018652885161071d565b96019201920185949391926107b9565b9181601f84011215610345578235916001600160401b038311610345576020838186019501011161034557565b60409061051a93921515815281602082015201906106f8565b346103455760803660031901126103455760043561085a8161051d565b6024356108668161051d565b6044356001600160401b038111610345576108859036906004016107f7565b926108c0606435936108b2600095606097604051968794634440347360e01b602087015260248601611781565b03601f19810184528361043d565b6001600160a01b0316803b156103455760405163428557b160e11b8152916000918391829084908290610920907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316600484016117ac565b03925af190816109c0575b506109bb57505061093a6117ef565b61094c610947825161181f565b611866565b9060045b8151811015610995578061097761096960019385611898565b516001600160f81b03191690565b61098e6109838361181f565b9160001a9186611898565b5301610950565b50506109aa90602080825183010191016118eb565b905b61067360405192839283610824565b6109ac565b806109cf60006109d59361043d565b80611044565b3861092b565b34610345576040366003190112610345576020610a356004356109fd8161051d565b610a0561034a565b6001600160a01b0390911660009081526001845260408082206001600160c01b0390931682526020929092522090565b54604051908152f35b3461034557604036600319011261034557600435610a5b8161051d565b602435336000526000602052604060002091825492838311610ae3576000808481948294610a8c610021988a61183d565b9055604080516001600160a01b03831681526020810184905233917fd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb91a26001600160a01b03165af1610add6117ef565b50611921565b60405162461bcd60e51b815260206004820152601960248201527f576974686472617720616d6f756e7420746f6f206c61726765000000000000006044820152606490fd5b602060031982011261034557600435906001600160401b038211610345576101209082900360031901126103455760040190565b34610345576020610b74610b6f36610b28565b611962565b604051908152f35b3461034557610ba8610b8d366106a7565b809291610b98611619565b50610ba28261166d565b50611719565b6000198201918211610bd65761067391610bc191611705565b5160405191829160208352602083019061071d565b6113f3565b9061051a9060e06080610c2d818651610140865280516101408701526020810151610160870152604081015161018087015260608101516101a0870152015160a06101c08601526101e08501906106f8565b60208087015180518683015201516040850152946040810151805160608601526020015160808501526060810151805160a08601526020015160c0850152015191019080516001600160a01b031682526020908101518051828401520151604090910152565b3461034557610caa610ca4366106a7565b90611af3565b6040518091602082016020835281518091526040830190602060408260051b8601019301916000905b828210610ce257505050500390f35b91936001919395506020610d018192603f198a82030186528851610bdb565b9601920192018594939192610cd3565b34610345576040366003190112610345576020600435610d308161051d565b610d3861034a565b6001600160a01b0390911660009081526001835260408082206001600160c01b03841683526020529020546040805192901b67ffffffffffffffff1916178152f35b3461034557606036600319011261034557600435610d978161051d565b6024356001600160401b0381116103455760009182610dbb819336906004016107f7565b919092610dc760443590565b9383604051948592833781018381520393f1610de16117ef565b9015610de957005b805190811561034557602001fd5b3461034557602036600319011261034557600435610e148161051d565b60006080604051610e24816103cb565b828152826020820152826040820152826060820152015260018060a01b031660005260006020526106736040600020610eb365ffffffffffff600160405193610e6c856103cb565b80548552015460ff8116151560208501526001600160701b038160081c16604085015263ffffffff8160781c16606085015260981c16608083019065ffffffffffff169052565b60405191829182919091608065ffffffffffff8160a0840195805185526020810151151560208601526001600160701b03604082015116604086015263ffffffff6060820151166060860152015116910152565b6080604061051a936020845280516020850152602081015115158285015201519160608082015201906106f8565b346103455760c0366003190112610345576004356001600160401b03811161034557610f65903690600401610677565b906024356001600160401b03811161034557606060031982360301126103455761067392610fae92604435610f998161051d565b606435916084359360a4359560040191611ca8565b60405191829182610f07565b3461034557610673610fd3610fce36610b28565b612027565b60405191829160208352602083019061071d565b34610345576020366003190112610345576004356110048161051d565b60018060a01b031660005260006020526020604060002054604051908152f35b60203660031901126103455761002160043561103f8161051d565b612162565b600091031261034557565b34610345576000366003190112610345573360005260006020526001604060002001805463ffffffff8160781c161561111f576110bb6110ad610214836110a161109c6110e29660ff1690565b6121b8565b60781c63ffffffff1690565b65ffffffffffff42166121f8565b825460ff65ffffffffffff60981b01191665ffffffffffff60981b609883901b1617909255565b60405165ffffffffffff909116815233907ffa9b3c14cc825c412c9ed81b3ba365a5b459439403f18829e572ed53a4180f0a908060208101610340565b60405162461bcd60e51b815260206004820152600a6024820152691b9bdd081cdd185ad95960b21b6044820152606490fd5b346103455760203660031901126103455761002160008080806004356111768161051d565b336000908152602081905260409020600101906111fe8254926111ed65ffffffffffff6111d96111bf6111b3886001600160701b039060081c1690565b6001600160701b031690565b966111cb881515612216565b60981c65ffffffffffff1690565b166111e5811515612259565b4210156122a5565b8054610100600160c81b0319169055565b604080516001600160a01b03831681526020810184905233917fb7c918e0e249f999e965cafeb6c664271b3f4317d296461500e71da39f0cbda391a26001600160a01b03165af161124d6117ef565b506122f1565b346103455761067361126c61126736610b28565b6123c5565b604051918291602083526020830190610bdb565b346103455760203660031901126103455760043561129d8161051d565b6001600160a01b031660009081526020818152604091829020805460019190910154835191825260ff8116151592820192909252600882901c6001600160701b031692810192909252607881901c63ffffffff16606083015260981c65ffffffffffff16608082015260a090f35b346103455761132d61131c366106a7565b809291611327611a6c565b50611af3565b6000198201918211610bd6576106739161134691611705565b51604051918291602083526020830190610bdb565b1561136257565b60405162461bcd60e51b815260206004820152601a60248201527f6d757374207370656369667920756e7374616b652064656c61790000000000006044820152606490fd5b156113ae57565b60405162461bcd60e51b815260206004820152601c60248201527f63616e6e6f7420646563726561736520756e7374616b652074696d65000000006044820152606490fd5b634e487b7160e01b600052601160045260246000fd5b906113888201809211610bd657565b9060018201809211610bd657565b91908201809211610bd657565b1561143a57565b60405162461bcd60e51b81526020600482015260126024820152711b9bc81cdd185ad9481cdc1958da599a595960721b6044820152606490fd5b1561147b57565b60405162461bcd60e51b815260206004820152600e60248201526d7374616b65206f766572666c6f7760901b6044820152606490fd5b6000198114610bd65760010190565b60409061051a9392815281602082015201906106f8565b91908051936060850151946114ef603f5a0260061c90565b61271060a0830151880101116115bd576106d195600095805161151f575b5050505a900360808201510192612609565b825161153d926115399290916001600160a01b0316612534565b1590565b611549575b808061150d565b909350611554612546565b8051611566575b505060019238611542565b602083810151835193909101516040516001600160a01b039094169391927f1c4fada7374c0a9ee8841fc38afe82932dc0f8e69012e927f061a8bae611a201929182916115b391836114c0565b0390a3388061155b565b60408051631101335b60e11b8152600060048201526024810191909152600f60448201526e41413935206f7574206f662067617360881b6064820152608490fd5b0390fd5b6001600160401b0381116103e65760051b60200190565b6040519061010082018281106001600160401b038211176103e657604052606060e08360008152600060208201526000604082015260008382015260006080820152600060a0820152600060c08201520152565b9061167782611602565b611684604051918261043d565b8281528092611695601f1991611602565b019060005b8281106116a657505050565b6020906116b1611619565b8282850101520161169a565b634e487b7160e01b600052603260045260246000fd5b90359061011e1981360301821215610345570190565b908210156117005761051a9160051b8101906116d3565b6116bd565b80518210156117005760209160051b010190565b6117228261166d565b9160005b8181106117335750505090565b80611744610fce60019385876116e9565b61174e8287611705565b526117598186611705565b5001611726565b908060209392818452848401376000828201840152601f01601f1916010190565b949392916040926117a79260018060a01b03168752606060208801526060870191611760565b930152565b6001600160a01b03909116815260406020820181905261051a929101906106f8565b6040513d6000823e3d90fd5b604051906117e960208361043d565b60008252565b3d1561181a573d90611800826104ad565b9161180e604051938461043d565b82523d6000602084013e565b606090565b600319810191908211610bd657565b600019810191908211610bd657565b91908203918211610bd657565b6040519061185960208361043d565b6000808352366020840137565b90611870826104ad565b61187d604051918261043d565b828152809261188e601f19916104ad565b0190602036910137565b908151811015611700570160200190565b81601f820112156103455780516118bf816104ad565b926118cd604051948561043d565b818452602082840101116103455761051a91602080850191016106d5565b9190916040818403126103455780518015158103610345579260208201516001600160401b0381116103455761051a92016118a9565b1561192857565b60405162461bcd60e51b81526020600482015260126024820152716661696c656420746f20776974686472617760701b6044820152606490fd5b6020810135611a246119776040840184611c45565b90816040519182372091611a166119916060860186611c45565b90816040519182372060c086013560a087013560808801356119bf6119b960e08b018b611c45565b9061359a565b604080519a356001600160a01b031660208c01908152908b019790975260608a0198909852608089019390935260a088019290925260c087019190915260e086015261010085019390935292918290610120820190565b03601f19810183528261043d565b51902060408051602081019283523091810191909152466060820152611a4d8160808101611a16565b51902090565b60405190611a60826103eb565b60006020838281520152565b60405190611a79826103cb565b81604051611a86816103cb565b60008152600060208201526000604082015260006060820152606060808201528152611ab0611a53565b6020820152611abd611a53565b6040820152611aca611a53565b6060820152608060405191611ade836103eb565b60008352611aea611a53565b60208401520152565b611afc82611602565b91611b0a604051938461043d565b808352601f19611b1982611602565b0160005b818110611b6357505060005b818110611b365750505090565b80611b4761126760019385876116e9565b611b518287611705565b52611b5c8186611705565b5001611b29565b602090611b6e611a6c565b82828801015201611b1d565b908092918237016000815290565b60405190611b9582610406565b606060408360008152600060208201520152565b60405190611bb6826103cb565b6000608083604051611bc781610421565b83815283602082015283604082015283606082015283838201528360a08201528360c08201528360e0820152836101008201528361012082015281528260208201528260408201528260608201520152565b91908110156117005760051b81013590605e1981360301821215610345570190565b3561051a8161051d565b903590601e198136030182121561034557018035906001600160401b0382116103455760200191813603831361034557565b6001600160a01b03918216815291166020820152608060408201819052909392916060916117a791908601906106f8565b9694969591939295611cb8611b88565b5060005b828110611f6457505050611cd083806116d3565b93611d10611cf8611cf1611ce660208801611c3b565b966040810190611c45565b36916104c8565b95611d01611ba9565b90611d0b816127ce565b6128df565b5050506001600160a01b03841615611f395760008315611e915750600190611d44611d396117da565b989291935b85611426565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169881905b84611d7d888561183d565b10611e66575a611d8c88611409565b11611e465791869593918a95938c8b611da6858d9c611426565b60011c9a8b996040519c8d938493630780cef560e11b85526004850193611dcc94611c77565b03815a6000948591f1988915611e4157600090819a611e1b575b5015611e0657505050611df88461182e565b95915b939092949591611d72565b93965094611e15919750611418565b94611dfb565b90611e39929a503d8091833e611e31818361043d565b8101906118eb565b989038611de6565b6117ce565b637162685f60e11b60005260048290526024879052604483905260646000fd5b97509750509250509450611e899150611e7d61047f565b93845215156020840152565b604082015290565b92505a9085848689611eb85a604051630780cef560e11b8152958694859460048601611c77565b0381837f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165af1908115611e4157858092611f12575b5050611f08611d449195935a9061183d565b9498929193611d3e565b611f089650611d44925090611f30913d8091833e611e31818361043d565b95909591611ef6565b95505050505050611f4861184a565b611f5061047f565b906000825260006020830152604082015290565b600190611f6f611ba9565b611f9a611f7d838787611c19565b91611f90611f8b84806116d3565b6127ce565b611d0b83806116d3565b50505060208101611fb9611fad82611c3b565b6001600160a01b031690565b156120005760009182611fda611fcf8294611c3b565b926040810190611c45565b9190611feb60405180948193611b7a565b03925af150611ff86117ef565b505b01611cbc565b5050611ffa565b6040519061201660408361043d565b6002825261060f60f31b6020830152565b61202f611619565b50600280541461215157600280556080612047611ba9565b91612051816127ce565b61205b83826128df565b9260009291925a90876060810151916120776060860186611c45565b909160038211612149575b6001600160e01b031916638dd7712f60e01b036121305750506120ce6120e26120e7956020840151604051938492638dd7712f60e01b6020850152604060248501526064840190612b03565b90604483015203601f19810183528261043d565b6114d7565b9490955b0151946120f661048e565b958652602086015260408501526060840152608083015260a0820152600060c0820152612121612007565b60e082015261051a6001600255565b6121419550906120e29136916104c8565b9490956120eb565b508135612082565b633ee5aeb560e01b60005260046000fd5b60015b600581106121b057507f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c4602061219b3484612d3e565b6040519081526001600160a01b0390931692a2565b600101612165565b156121bf57565b60405162461bcd60e51b8152602060048201526011602482015270616c726561647920756e7374616b696e6760781b6044820152606490fd5b9065ffffffffffff8091169116019065ffffffffffff8211610bd657565b1561221d57565b60405162461bcd60e51b81526020600482015260146024820152734e6f207374616b6520746f20776974686472617760601b6044820152606490fd5b1561226057565b60405162461bcd60e51b815260206004820152601d60248201527f6d7573742063616c6c20756e6c6f636b5374616b6528292066697273740000006044820152606490fd5b156122ac57565b60405162461bcd60e51b815260206004820152601b60248201527f5374616b65207769746864726177616c206973206e6f742064756500000000006044820152606490fd5b156122f857565b60405162461bcd60e51b815260206004820152601860248201527f6661696c656420746f207769746864726177207374616b6500000000000000006044820152606490fd5b906014116103455790601490565b356bffffffffffffffffffffffff1981169291906014821061236b575050565b6bffffffffffffffffffffffff1960149290920360031b82901b16169150565b60405190612398826103eb565b6003546001600160a01b031682526040516020836123b5836103eb565b6004548352600554828401520152565b6123cd611a6c565b506123d6611ba9565b906123e0816127ce565b6123ea82826128df565b509190926123f88385612bc6565b805160e00151612415906001600160a01b0316612cd2565b612cd2565b81515190929061244590612431906001600160a01b0316612cd2565b9161243a611a53565b506040810190611c45565b906014821061251f5761246761246161246d936124109361233d565b9061234b565b60601c90565b9160018060a01b03861694608082015196606060408401519301519261249161045e565b98895260208901526040880152606087015260808601526124b061238b565b9380151580612514575b6124e2575b506124c861045e565b948552602085015260408401526060830152608082015290565b9093506124ee81612cd2565b6125086124f961049e565b6001600160a01b039093168352565b602082015292386124bf565b5060018114156124ba565b505061246d6000612cd2565b61046d33612162565b9060009283809360208451940192f190565b3d610800811161256b575b604051906020818301016040528082526000602083013e90565b50610800612551565b6003111561257e57565b634e487b7160e01b600052602160045260246000fd5b9094939294600381101561257e576060926125bc9183526080602084015260808301906106f8565b9460408201520152565b9060a061051a926000815260606020820152601460608201527310504d4c081c1bdcdd13dc081c995d995c9d195960621b608082015281604082015201906106f8565b9093916000935a9286519261261d84612d14565b60e08501519091906001600160a01b0316808061270357505084516001600160a01b03169050925b5a8603019360a060608201519101510190608089019182518603908181116126ee575b505084029160408901928351948186106000146126c45750508061268d600292612574565b036126a957505061046d925080956126a481612e30565b612d65565b9150915061046d925a90039051019051856126a48297612e30565b9061046d9750809a94506126dd92935080950390612d3e565b506126e781612574565b1590612dcb565b9195916064919003600a020401933880612668565b94918051612713575b5050612645565b61271c85612574565b600285031561270c57909198505a9160a087015191813b1561034557859285600080948e61276384604051998a9889978895637c627b2160e01b8752029160048601612594565b0393f190816127a1575b50612796576115fe61277d612546565b6040516365c8fd4d60e01b8152918291600483016125c6565b5a900396388061270c565b806109cf60006127b09361043d565b3861276d565b90604061051a926000815281602082015201906106f8565b6040516135a560f21b602082019081523060601b6022830152600160f81b60368301526017825261285792919061280660378361043d565b60018060a01b0391519020166bffffffffffffffffffffffff60a01b60065416176006556128376040820182611c45565b9161284f61284482611c3b565b9160e0810190611c45565b939092612e72565b80516128605750565b604051631101335b60e11b81529081906115fe90600483016127b6565b1561288457565b60405162461bcd60e51b815260206004820152601860248201527f41413934206761732076616c756573206f766572666c6f7700000000000000006044820152606490fd5b90607382029180830460731490151715610bd657565b90916000915a938051916128f38382612f7d565b6128fc81611962565b60208301526040830151956129486effffffffffffffffffffffffffffff8860c08701511760608701511760808701511760a0870151176101008701511761012087015117111561287d565b61297384610100604082015160608301510160808301510160a08301510160c0830151019101510290565b6129818882868660006130c1565b85519098906129a290611539906001600160a01b0316602089015190613279565b612a83575a830311612a34576060905a60e096909601516001600160a01b0316612a01575b6129f59360a061051a9794879460809460406129fa9a015260608601525a9003910135019101525a9061183d565b6128c9565b6064900490565b965050928260808360a061051a97612a228b6129fa996129f5996000613324565b9b9095985093509497505093506129c7565b60408051631101335b60e11b8152600060048201526024810191909152601e60448201527f41413236206f76657220766572696669636174696f6e4761734c696d697400006064820152608490fd5b60408051631101335b60e11b8152600060048201526024810191909152601a60448201527f4141323520696e76616c6964206163636f756e74206e6f6e63650000000000006064820152608490fd5b9035601e19823603018112156103455701602081359101916001600160401b03821161034557813603831361034557565b61051a91612b2181612b1484610549565b6001600160a01b03169052565b60208201356020820152612bb7612bab612b72612b57612b446040870187612ad2565b6101206040880152610120870191611760565b612b646060870187612ad2565b908683036060880152611760565b6080850135608085015260a085013560a085015260c085013560c0850152612b9d60e0860186612ad2565b9085830360e0870152611760565b92610100810190612ad2565b91610100818503910152611760565b612bcf906134b5565b906001600160a01b0316612c8f57612c4057612bea906134b5565b506001600160a01b0316612bfa57565b60408051631101335b60e11b8152600060048201526024810191909152601460448201527320a0999a1039b4b3b730ba3ab9329032b93937b960611b6064820152608490fd5b60408051631101335b60e11b8152600060048201526024810191909152601760448201527f414132322065787069726564206f72206e6f74206475650000000000000000006064820152608490fd5b6084604051631101335b60e11b81526000600482015260406024820152601460448201527320a0991a1039b4b3b730ba3ab9329032b93937b960611b6064820152fd5b90612cdb611a53565b9160018060a01b0316600052600060205263ffffffff6001604060002001546001600160701b038160081c16845260781c166020830152565b610120610100820151910151808214612d3a57480180821015612d35575090565b905090565b5090565b60018060a01b0316600052600060205260406000208054918201809211610bd65781905590565b9190917f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f6080602083015192519460018060a01b0386511694602060018060a01b0360e089015116970151916040519283526000602084015260408301526060820152a4565b9060807f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f91602084015193519560018060a01b0387511695602060018060a01b0360e08a015116980151926040519384521515602084015260408301526060820152a4565b60208101519051907f67b4fa9642f42120bf031f3051d1824b0fe25627945b27b8a6a65d5761d5482e60208060018060a01b03855116940151604051908152a3565b50929192159081612f27575b50612eea576014811015612e97575b505061051a6117da565b601411610345573560601c3b15612eaf573880612e8d565b604051612ebd60408261043d565b601b81527f41413330207061796d6173746572206e6f74206465706c6f7965640000000000602082015290565b5050604051612efa60408261043d565b601981527f41413230206163636f756e74206e6f74206465706c6f79656400000000000000602082015290565b90503b1538612e7e565b15612f3857565b60405162461bcd60e51b815260206004820152601d60248201527f4141393320696e76616c6964207061796d6173746572416e64446174610000006044820152606490fd5b61300290612f9a612f8d82611c3b565b6001600160a01b03168452565b60208101356020840152612fbe6080820135906001600160801b038260801c921690565b6060850152604084015260a081013560c0840152612fec60c0820135906001600160801b038260801c921690565b61010085015261012084015260e0810190611c45565b90811561303e576130268260e092613021603461046d97961015612f31565b6135a5565b60a085015260808401526001600160a01b0316910152565b505060a081600060e0819401528260808201520152565b90816020910312610345575190565b61307c60409295949395606083526060830190612b03565b9460208201520152565b60a09061051a9392815260606020820152600d60608201526c10504c8cc81c995d995c9d1959609a1b608082015281604082015201906106f8565b949291939060206131479186519361310d60e06130e4875160018060a01b031690565b966130ff8b8d6130f76040890189611c45565b929091613603565b01516001600160a01b031690565b6001600160a01b03161597600092908961323b575b8401516040516306608bdf60e21b815295869485936000938593929160048501613064565b03926001600160a01b03881690f16000918161320a575b50613189578561316c612546565b6040516365c8fd4d60e01b81529182916115fe9160048401613086565b94929361319557505050565b6001600160a01b03166000908152602081905260409020918254908183116131bd5750039055565b60408051631101335b60e11b815260048101929092526024820152601760448201527f41413231206469646e2774207061792070726566756e640000000000000000006064820152608490fd5b61322d91925060203d602011613234575b613225818361043d565b810190613055565b903861315e565b503d61321b565b6001600160a01b0387166000908152602081905260409020909350548781111561326e5750600084815b94915050613122565b846000918903613265565b6001600160a01b0316600090815260016020908152604080832084821c845290915290208054916001600160401b03916132b2846114b1565b9055161490565b91906040838203126103455782516001600160401b038111610345576020916132e39185016118a9565b92015190565b60a09061051a9392815260606020820152600d60608201526c10504cccc81c995d995c9d1959609a1b608082015281604082015201906106f8565b929390915a815160e08101516001600160a01b031660008181526020819052604090209295909290919080548981106134665760206080600096948c969461338f9c9d8995039055015196015191604051998a95869485936314add44b60e21b855260048501613064565b03926001600160a01b031686f1938460009160009661343f575b506133d457856133b7612546565b6040516365c8fd4d60e01b81529182916115fe91600484016132e9565b9491925a9003116133e25750565b60408051631101335b60e11b815260048101929092526024820152602760448201527f41413336206f766572207061796d6173746572566572696669636174696f6e47606482015266185cd31a5b5a5d60ca1b608482015260a490fd5b90955061345f91503d806000833e613457818361043d565b8101906132b9565b94386133a9565b60408051631101335b60e11b8152600481018b90526024810191909152601e60448201527f41413331207061796d6173746572206465706f73697420746f6f206c6f7700006064820152608490fd5b8015613591576000604080516134ca81610406565b828152826020820152015265ffffffffffff8160a01c168015613584575b6135669061354d6134ff61350a6134ff8660d01c90565b65ffffffffffff1690565b9261352561351661047f565b6001600160a01b039097168752565b61353b6020870194859065ffffffffffff169052565b65ffffffffffff166040860181905290565b4211908115613569575b5091516001600160a01b031690565b91565b5161357c915065ffffffffffff166134ff565b421038613557565b5065ffffffffffff6134e8565b50600090600090565b816040519182372090565b9091826014116103455781359183602411610345576014810135936034116103455760609290921c92608090811c9260240135901c90565b90816020910312610345575161051a8161051d565b91602061051a938181520191611760565b92909181613612575b50505050565b8251516001600160a01b031693843b61382057600654600090602090613640906001600160a01b0316611fad565b60408751015160405180948193632b870d1b60e11b8352826136668b8b600484016135f2565b0393f1908115611e41576000916137f1575b506001600160a01b0381169586156137a2576001600160a01b031695869003613753573b1561370657506124676124617fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d936136d39361233d565b602083810151935160e00151604080516001600160a01b039485168152939091169183019190915290a33880808061360c565b60408051631101335b60e11b815260048101929092526024820152602060448201527f4141313520696e6974436f6465206d757374206372656174652073656e6465726064820152608490fd5b60408051631101335b60e11b8152600481018490526024810191909152602060448201527f4141313420696e6974436f6465206d7573742072657475726e2073656e6465726064820152608490fd5b60408051631101335b60e11b8152600481018590526024810191909152601b60448201527f4141313320696e6974436f6465206661696c6564206f72204f4f4700000000006064820152608490fd5b613813915060203d602011613819575b61380b818361043d565b8101906135dd565b38613678565b503d613801565b60408051631101335b60e11b815260048101929092526024820152601f60448201527f414131302073656e64657220616c726561647920636f6e7374727563746564006064820152608490fdfea2646970667358221220acbd8be1ea62c3ab5f653b3d7179466c115357e2ef9a32f72cf4bc2cab8d80c764736f6c634300081a00336080806040523460155761016d908161001b8239f35b600080fdfe6080600436101561000f57600080fd5b60003560e01c63570e1a361461002457600080fd5b346101325760203660031901126101325760043567ffffffffffffffff8111610132573660238201121561013257806004013567ffffffffffffffff8111610132573660248284010111610132576000928160141161012e5760131982019167ffffffffffffffff831161011a57600b8101601f19908116603f0116820167ffffffffffffffff8111838210176101065760246020959387600c819795829560405286845289840196603889018837830101525193013560601c5af1905190156100fe575b6040516001600160a01b039091168152602090f35b5060006100e9565b634e487b7160e01b86526041600452602486fd5b634e487b7160e01b85526041600452602485fd5b8380fd5b600080fdfea2646970667358221220f470d74e6d005a2169bacb1af7de20718b289144fe53c238995a95a34c36d0f764736f6c634300081a0033
Deployed Bytecode
0x60806040526004361015610023575b361561001957600080fd5b61002161252b565b005b60003560e01c80630396cb60146101835780630bd28e3b1461017e5780630da82661146101795780630dbfc6bd146101745780630f019dea1461016f5780631b2e01b81461016a578063205c28781461016557806322cdde4c14610160578063263934db1461015b57806330ec25d11461015657806335567e1a14610151578063444034731461014c5780635287ce12146101475780635787f48b146101425780635895273b1461013d57806370a0823114610138578063b760faf914610133578063bb9fe6bf1461012e578063c23a5cea14610129578063c3bce00914610124578063fc7e286d1461011f5763fe2171cb0361000e5761130b565b611280565b611253565b611151565b61104f565b611024565b610fe7565b610fba565b610f35565b610df7565b610d7a565b610d11565b610c93565b610b7c565b610b5c565b610a3e565b6109db565b61083d565b610779565b610554565b610360565b60203660031901126103455760043563ffffffff811690818103610345576103407fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c01916103226102436102336101eb3360018060a01b03166000526000602052604060002090565b966101f781151561135b565b61022460018901549161021d6102148463ffffffff9060781c1690565b63ffffffff1690565b11156113a7565b60081c6001600160701b031690565b6001600160701b03349116611426565b9461024f861515611433565b6102626001600160701b03871115611474565b5461026b61045e565b908152600160208201526001600160701b038616604082015263ffffffff8316606082015260006080820181905233815260208190526040902081518155602082015160019091018054604084015160608501516080909501516001600160c81b031990921660ff941515949094169390931760089390931b6effffffffffffffffffffffffffff00169290921760789390931b63ffffffff60781b169290921760989190911b65ffffffffffff60981b16179055565b6040805194855263ffffffff90911660208501523393918291820190565b0390a2005b600080fd5b602435906001600160c01b038216820361034557565b34610345576020366003190112610345576004356001600160c01b0381168103610345573360009081526001602090815260408083206001600160c01b039094168352929052206103b181546114b1565b9055005b634e487b7160e01b600052604160045260246000fd5b60a081019081106001600160401b038211176103e657604052565b6103b5565b604081019081106001600160401b038211176103e657604052565b606081019081106001600160401b038211176103e657604052565b61014081019081106001600160401b038211176103e657604052565b90601f801991011681019081106001600160401b038211176103e657604052565b6040519061046d60a08361043d565b565b6040519061046d6101408361043d565b6040519061046d60608361043d565b6040519061046d6101008361043d565b6040519061046d60408361043d565b6001600160401b0381116103e657601f01601f191660200190565b9291926104d4826104ad565b916104e2604051938461043d565b829481845281830111610345578281602093846000960137010152565b9080601f830112156103455781602061051a933591016104c8565b90565b6001600160a01b0381160361034557565b6024359061046d8261051d565b610104359061046d8261051d565b359061046d8261051d565b3461034557610220366003190112610345576004356001600160401b038111610345576105859036906004016104ff565b3660231901906101c0821261034557610140604051926105a4846103cb565b12610345576105b161046f565b6105b961052e565b815260443560208201526064356040820152608435606082015260a435608082015260c43560a082015260e43560c08201526105f361053b565b60e0820152610124356101008201526101443561012082015282526101643560208301526101843560408301526101a43560608301526101c43560808301526101e435916001600160401b038311610345576106566106619336906004016104ff565b9061020435926114d7565b60408051928352602083019190915290f35b0390f35b9181601f84011215610345578235916001600160401b038311610345576020808501948460051b01011161034557565b602060031982011261034557600435906001600160401b038211610345576106d191600401610677565b9091565b60005b8381106106e85750506000910152565b81810151838201526020016106d8565b90602091610711815180928185528580860191016106d5565b601f01601f1916010190565b9061010060e061051a93805184526020810151602085015260408101516040850152606081015160608501526080810151608085015260a081015160a085015260c0810151151560c08501520151918160e082015201906106f8565b346103455761079061078a366106a7565b90611719565b6040518091602082016020835281518091526040830190602060408260051b8601019301916000905b8282106107c857505050500390f35b919360019193955060206107e78192603f198a8203018652885161071d565b96019201920185949391926107b9565b9181601f84011215610345578235916001600160401b038311610345576020838186019501011161034557565b60409061051a93921515815281602082015201906106f8565b346103455760803660031901126103455760043561085a8161051d565b6024356108668161051d565b6044356001600160401b038111610345576108859036906004016107f7565b926108c0606435936108b2600095606097604051968794634440347360e01b602087015260248601611781565b03601f19810184528361043d565b6001600160a01b0316803b156103455760405163428557b160e11b8152916000918391829084908290610920907f000000000000000000000000c8f3cb18eb164dc3297d1f41af6c1521f1e561706001600160a01b0316600484016117ac565b03925af190816109c0575b506109bb57505061093a6117ef565b61094c610947825161181f565b611866565b9060045b8151811015610995578061097761096960019385611898565b516001600160f81b03191690565b61098e6109838361181f565b9160001a9186611898565b5301610950565b50506109aa90602080825183010191016118eb565b905b61067360405192839283610824565b6109ac565b806109cf60006109d59361043d565b80611044565b3861092b565b34610345576040366003190112610345576020610a356004356109fd8161051d565b610a0561034a565b6001600160a01b0390911660009081526001845260408082206001600160c01b0390931682526020929092522090565b54604051908152f35b3461034557604036600319011261034557600435610a5b8161051d565b602435336000526000602052604060002091825492838311610ae3576000808481948294610a8c610021988a61183d565b9055604080516001600160a01b03831681526020810184905233917fd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb91a26001600160a01b03165af1610add6117ef565b50611921565b60405162461bcd60e51b815260206004820152601960248201527f576974686472617720616d6f756e7420746f6f206c61726765000000000000006044820152606490fd5b602060031982011261034557600435906001600160401b038211610345576101209082900360031901126103455760040190565b34610345576020610b74610b6f36610b28565b611962565b604051908152f35b3461034557610ba8610b8d366106a7565b809291610b98611619565b50610ba28261166d565b50611719565b6000198201918211610bd65761067391610bc191611705565b5160405191829160208352602083019061071d565b6113f3565b9061051a9060e06080610c2d818651610140865280516101408701526020810151610160870152604081015161018087015260608101516101a0870152015160a06101c08601526101e08501906106f8565b60208087015180518683015201516040850152946040810151805160608601526020015160808501526060810151805160a08601526020015160c0850152015191019080516001600160a01b031682526020908101518051828401520151604090910152565b3461034557610caa610ca4366106a7565b90611af3565b6040518091602082016020835281518091526040830190602060408260051b8601019301916000905b828210610ce257505050500390f35b91936001919395506020610d018192603f198a82030186528851610bdb565b9601920192018594939192610cd3565b34610345576040366003190112610345576020600435610d308161051d565b610d3861034a565b6001600160a01b0390911660009081526001835260408082206001600160c01b03841683526020529020546040805192901b67ffffffffffffffff1916178152f35b3461034557606036600319011261034557600435610d978161051d565b6024356001600160401b0381116103455760009182610dbb819336906004016107f7565b919092610dc760443590565b9383604051948592833781018381520393f1610de16117ef565b9015610de957005b805190811561034557602001fd5b3461034557602036600319011261034557600435610e148161051d565b60006080604051610e24816103cb565b828152826020820152826040820152826060820152015260018060a01b031660005260006020526106736040600020610eb365ffffffffffff600160405193610e6c856103cb565b80548552015460ff8116151560208501526001600160701b038160081c16604085015263ffffffff8160781c16606085015260981c16608083019065ffffffffffff169052565b60405191829182919091608065ffffffffffff8160a0840195805185526020810151151560208601526001600160701b03604082015116604086015263ffffffff6060820151166060860152015116910152565b6080604061051a936020845280516020850152602081015115158285015201519160608082015201906106f8565b346103455760c0366003190112610345576004356001600160401b03811161034557610f65903690600401610677565b906024356001600160401b03811161034557606060031982360301126103455761067392610fae92604435610f998161051d565b606435916084359360a4359560040191611ca8565b60405191829182610f07565b3461034557610673610fd3610fce36610b28565b612027565b60405191829160208352602083019061071d565b34610345576020366003190112610345576004356110048161051d565b60018060a01b031660005260006020526020604060002054604051908152f35b60203660031901126103455761002160043561103f8161051d565b612162565b600091031261034557565b34610345576000366003190112610345573360005260006020526001604060002001805463ffffffff8160781c161561111f576110bb6110ad610214836110a161109c6110e29660ff1690565b6121b8565b60781c63ffffffff1690565b65ffffffffffff42166121f8565b825460ff65ffffffffffff60981b01191665ffffffffffff60981b609883901b1617909255565b60405165ffffffffffff909116815233907ffa9b3c14cc825c412c9ed81b3ba365a5b459439403f18829e572ed53a4180f0a908060208101610340565b60405162461bcd60e51b815260206004820152600a6024820152691b9bdd081cdd185ad95960b21b6044820152606490fd5b346103455760203660031901126103455761002160008080806004356111768161051d565b336000908152602081905260409020600101906111fe8254926111ed65ffffffffffff6111d96111bf6111b3886001600160701b039060081c1690565b6001600160701b031690565b966111cb881515612216565b60981c65ffffffffffff1690565b166111e5811515612259565b4210156122a5565b8054610100600160c81b0319169055565b604080516001600160a01b03831681526020810184905233917fb7c918e0e249f999e965cafeb6c664271b3f4317d296461500e71da39f0cbda391a26001600160a01b03165af161124d6117ef565b506122f1565b346103455761067361126c61126736610b28565b6123c5565b604051918291602083526020830190610bdb565b346103455760203660031901126103455760043561129d8161051d565b6001600160a01b031660009081526020818152604091829020805460019190910154835191825260ff8116151592820192909252600882901c6001600160701b031692810192909252607881901c63ffffffff16606083015260981c65ffffffffffff16608082015260a090f35b346103455761132d61131c366106a7565b809291611327611a6c565b50611af3565b6000198201918211610bd6576106739161134691611705565b51604051918291602083526020830190610bdb565b1561136257565b60405162461bcd60e51b815260206004820152601a60248201527f6d757374207370656369667920756e7374616b652064656c61790000000000006044820152606490fd5b156113ae57565b60405162461bcd60e51b815260206004820152601c60248201527f63616e6e6f7420646563726561736520756e7374616b652074696d65000000006044820152606490fd5b634e487b7160e01b600052601160045260246000fd5b906113888201809211610bd657565b9060018201809211610bd657565b91908201809211610bd657565b1561143a57565b60405162461bcd60e51b81526020600482015260126024820152711b9bc81cdd185ad9481cdc1958da599a595960721b6044820152606490fd5b1561147b57565b60405162461bcd60e51b815260206004820152600e60248201526d7374616b65206f766572666c6f7760901b6044820152606490fd5b6000198114610bd65760010190565b60409061051a9392815281602082015201906106f8565b91908051936060850151946114ef603f5a0260061c90565b61271060a0830151880101116115bd576106d195600095805161151f575b5050505a900360808201510192612609565b825161153d926115399290916001600160a01b0316612534565b1590565b611549575b808061150d565b909350611554612546565b8051611566575b505060019238611542565b602083810151835193909101516040516001600160a01b039094169391927f1c4fada7374c0a9ee8841fc38afe82932dc0f8e69012e927f061a8bae611a201929182916115b391836114c0565b0390a3388061155b565b60408051631101335b60e11b8152600060048201526024810191909152600f60448201526e41413935206f7574206f662067617360881b6064820152608490fd5b0390fd5b6001600160401b0381116103e65760051b60200190565b6040519061010082018281106001600160401b038211176103e657604052606060e08360008152600060208201526000604082015260008382015260006080820152600060a0820152600060c08201520152565b9061167782611602565b611684604051918261043d565b8281528092611695601f1991611602565b019060005b8281106116a657505050565b6020906116b1611619565b8282850101520161169a565b634e487b7160e01b600052603260045260246000fd5b90359061011e1981360301821215610345570190565b908210156117005761051a9160051b8101906116d3565b6116bd565b80518210156117005760209160051b010190565b6117228261166d565b9160005b8181106117335750505090565b80611744610fce60019385876116e9565b61174e8287611705565b526117598186611705565b5001611726565b908060209392818452848401376000828201840152601f01601f1916010190565b949392916040926117a79260018060a01b03168752606060208801526060870191611760565b930152565b6001600160a01b03909116815260406020820181905261051a929101906106f8565b6040513d6000823e3d90fd5b604051906117e960208361043d565b60008252565b3d1561181a573d90611800826104ad565b9161180e604051938461043d565b82523d6000602084013e565b606090565b600319810191908211610bd657565b600019810191908211610bd657565b91908203918211610bd657565b6040519061185960208361043d565b6000808352366020840137565b90611870826104ad565b61187d604051918261043d565b828152809261188e601f19916104ad565b0190602036910137565b908151811015611700570160200190565b81601f820112156103455780516118bf816104ad565b926118cd604051948561043d565b818452602082840101116103455761051a91602080850191016106d5565b9190916040818403126103455780518015158103610345579260208201516001600160401b0381116103455761051a92016118a9565b1561192857565b60405162461bcd60e51b81526020600482015260126024820152716661696c656420746f20776974686472617760701b6044820152606490fd5b6020810135611a246119776040840184611c45565b90816040519182372091611a166119916060860186611c45565b90816040519182372060c086013560a087013560808801356119bf6119b960e08b018b611c45565b9061359a565b604080519a356001600160a01b031660208c01908152908b019790975260608a0198909852608089019390935260a088019290925260c087019190915260e086015261010085019390935292918290610120820190565b03601f19810183528261043d565b51902060408051602081019283523091810191909152466060820152611a4d8160808101611a16565b51902090565b60405190611a60826103eb565b60006020838281520152565b60405190611a79826103cb565b81604051611a86816103cb565b60008152600060208201526000604082015260006060820152606060808201528152611ab0611a53565b6020820152611abd611a53565b6040820152611aca611a53565b6060820152608060405191611ade836103eb565b60008352611aea611a53565b60208401520152565b611afc82611602565b91611b0a604051938461043d565b808352601f19611b1982611602565b0160005b818110611b6357505060005b818110611b365750505090565b80611b4761126760019385876116e9565b611b518287611705565b52611b5c8186611705565b5001611b29565b602090611b6e611a6c565b82828801015201611b1d565b908092918237016000815290565b60405190611b9582610406565b606060408360008152600060208201520152565b60405190611bb6826103cb565b6000608083604051611bc781610421565b83815283602082015283604082015283606082015283838201528360a08201528360c08201528360e0820152836101008201528361012082015281528260208201528260408201528260608201520152565b91908110156117005760051b81013590605e1981360301821215610345570190565b3561051a8161051d565b903590601e198136030182121561034557018035906001600160401b0382116103455760200191813603831361034557565b6001600160a01b03918216815291166020820152608060408201819052909392916060916117a791908601906106f8565b9694969591939295611cb8611b88565b5060005b828110611f6457505050611cd083806116d3565b93611d10611cf8611cf1611ce660208801611c3b565b966040810190611c45565b36916104c8565b95611d01611ba9565b90611d0b816127ce565b6128df565b5050506001600160a01b03841615611f395760008315611e915750600190611d44611d396117da565b989291935b85611426565b7f000000000000000000000000c8f3cb18eb164dc3297d1f41af6c1521f1e561706001600160a01b03169881905b84611d7d888561183d565b10611e66575a611d8c88611409565b11611e465791869593918a95938c8b611da6858d9c611426565b60011c9a8b996040519c8d938493630780cef560e11b85526004850193611dcc94611c77565b03815a6000948591f1988915611e4157600090819a611e1b575b5015611e0657505050611df88461182e565b95915b939092949591611d72565b93965094611e15919750611418565b94611dfb565b90611e39929a503d8091833e611e31818361043d565b8101906118eb565b989038611de6565b6117ce565b637162685f60e11b60005260048290526024879052604483905260646000fd5b97509750509250509450611e899150611e7d61047f565b93845215156020840152565b604082015290565b92505a9085848689611eb85a604051630780cef560e11b8152958694859460048601611c77565b0381837f000000000000000000000000c8f3cb18eb164dc3297d1f41af6c1521f1e561706001600160a01b03165af1908115611e4157858092611f12575b5050611f08611d449195935a9061183d565b9498929193611d3e565b611f089650611d44925090611f30913d8091833e611e31818361043d565b95909591611ef6565b95505050505050611f4861184a565b611f5061047f565b906000825260006020830152604082015290565b600190611f6f611ba9565b611f9a611f7d838787611c19565b91611f90611f8b84806116d3565b6127ce565b611d0b83806116d3565b50505060208101611fb9611fad82611c3b565b6001600160a01b031690565b156120005760009182611fda611fcf8294611c3b565b926040810190611c45565b9190611feb60405180948193611b7a565b03925af150611ff86117ef565b505b01611cbc565b5050611ffa565b6040519061201660408361043d565b6002825261060f60f31b6020830152565b61202f611619565b50600280541461215157600280556080612047611ba9565b91612051816127ce565b61205b83826128df565b9260009291925a90876060810151916120776060860186611c45565b909160038211612149575b6001600160e01b031916638dd7712f60e01b036121305750506120ce6120e26120e7956020840151604051938492638dd7712f60e01b6020850152604060248501526064840190612b03565b90604483015203601f19810183528261043d565b6114d7565b9490955b0151946120f661048e565b958652602086015260408501526060840152608083015260a0820152600060c0820152612121612007565b60e082015261051a6001600255565b6121419550906120e29136916104c8565b9490956120eb565b508135612082565b633ee5aeb560e01b60005260046000fd5b60015b600581106121b057507f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c4602061219b3484612d3e565b6040519081526001600160a01b0390931692a2565b600101612165565b156121bf57565b60405162461bcd60e51b8152602060048201526011602482015270616c726561647920756e7374616b696e6760781b6044820152606490fd5b9065ffffffffffff8091169116019065ffffffffffff8211610bd657565b1561221d57565b60405162461bcd60e51b81526020600482015260146024820152734e6f207374616b6520746f20776974686472617760601b6044820152606490fd5b1561226057565b60405162461bcd60e51b815260206004820152601d60248201527f6d7573742063616c6c20756e6c6f636b5374616b6528292066697273740000006044820152606490fd5b156122ac57565b60405162461bcd60e51b815260206004820152601b60248201527f5374616b65207769746864726177616c206973206e6f742064756500000000006044820152606490fd5b156122f857565b60405162461bcd60e51b815260206004820152601860248201527f6661696c656420746f207769746864726177207374616b6500000000000000006044820152606490fd5b906014116103455790601490565b356bffffffffffffffffffffffff1981169291906014821061236b575050565b6bffffffffffffffffffffffff1960149290920360031b82901b16169150565b60405190612398826103eb565b6003546001600160a01b031682526040516020836123b5836103eb565b6004548352600554828401520152565b6123cd611a6c565b506123d6611ba9565b906123e0816127ce565b6123ea82826128df565b509190926123f88385612bc6565b805160e00151612415906001600160a01b0316612cd2565b612cd2565b81515190929061244590612431906001600160a01b0316612cd2565b9161243a611a53565b506040810190611c45565b906014821061251f5761246761246161246d936124109361233d565b9061234b565b60601c90565b9160018060a01b03861694608082015196606060408401519301519261249161045e565b98895260208901526040880152606087015260808601526124b061238b565b9380151580612514575b6124e2575b506124c861045e565b948552602085015260408401526060830152608082015290565b9093506124ee81612cd2565b6125086124f961049e565b6001600160a01b039093168352565b602082015292386124bf565b5060018114156124ba565b505061246d6000612cd2565b61046d33612162565b9060009283809360208451940192f190565b3d610800811161256b575b604051906020818301016040528082526000602083013e90565b50610800612551565b6003111561257e57565b634e487b7160e01b600052602160045260246000fd5b9094939294600381101561257e576060926125bc9183526080602084015260808301906106f8565b9460408201520152565b9060a061051a926000815260606020820152601460608201527310504d4c081c1bdcdd13dc081c995d995c9d195960621b608082015281604082015201906106f8565b9093916000935a9286519261261d84612d14565b60e08501519091906001600160a01b0316808061270357505084516001600160a01b03169050925b5a8603019360a060608201519101510190608089019182518603908181116126ee575b505084029160408901928351948186106000146126c45750508061268d600292612574565b036126a957505061046d925080956126a481612e30565b612d65565b9150915061046d925a90039051019051856126a48297612e30565b9061046d9750809a94506126dd92935080950390612d3e565b506126e781612574565b1590612dcb565b9195916064919003600a020401933880612668565b94918051612713575b5050612645565b61271c85612574565b600285031561270c57909198505a9160a087015191813b1561034557859285600080948e61276384604051998a9889978895637c627b2160e01b8752029160048601612594565b0393f190816127a1575b50612796576115fe61277d612546565b6040516365c8fd4d60e01b8152918291600483016125c6565b5a900396388061270c565b806109cf60006127b09361043d565b3861276d565b90604061051a926000815281602082015201906106f8565b6040516135a560f21b602082019081523060601b6022830152600160f81b60368301526017825261285792919061280660378361043d565b60018060a01b0391519020166bffffffffffffffffffffffff60a01b60065416176006556128376040820182611c45565b9161284f61284482611c3b565b9160e0810190611c45565b939092612e72565b80516128605750565b604051631101335b60e11b81529081906115fe90600483016127b6565b1561288457565b60405162461bcd60e51b815260206004820152601860248201527f41413934206761732076616c756573206f766572666c6f7700000000000000006044820152606490fd5b90607382029180830460731490151715610bd657565b90916000915a938051916128f38382612f7d565b6128fc81611962565b60208301526040830151956129486effffffffffffffffffffffffffffff8860c08701511760608701511760808701511760a0870151176101008701511761012087015117111561287d565b61297384610100604082015160608301510160808301510160a08301510160c0830151019101510290565b6129818882868660006130c1565b85519098906129a290611539906001600160a01b0316602089015190613279565b612a83575a830311612a34576060905a60e096909601516001600160a01b0316612a01575b6129f59360a061051a9794879460809460406129fa9a015260608601525a9003910135019101525a9061183d565b6128c9565b6064900490565b965050928260808360a061051a97612a228b6129fa996129f5996000613324565b9b9095985093509497505093506129c7565b60408051631101335b60e11b8152600060048201526024810191909152601e60448201527f41413236206f76657220766572696669636174696f6e4761734c696d697400006064820152608490fd5b60408051631101335b60e11b8152600060048201526024810191909152601a60448201527f4141323520696e76616c6964206163636f756e74206e6f6e63650000000000006064820152608490fd5b9035601e19823603018112156103455701602081359101916001600160401b03821161034557813603831361034557565b61051a91612b2181612b1484610549565b6001600160a01b03169052565b60208201356020820152612bb7612bab612b72612b57612b446040870187612ad2565b6101206040880152610120870191611760565b612b646060870187612ad2565b908683036060880152611760565b6080850135608085015260a085013560a085015260c085013560c0850152612b9d60e0860186612ad2565b9085830360e0870152611760565b92610100810190612ad2565b91610100818503910152611760565b612bcf906134b5565b906001600160a01b0316612c8f57612c4057612bea906134b5565b506001600160a01b0316612bfa57565b60408051631101335b60e11b8152600060048201526024810191909152601460448201527320a0999a1039b4b3b730ba3ab9329032b93937b960611b6064820152608490fd5b60408051631101335b60e11b8152600060048201526024810191909152601760448201527f414132322065787069726564206f72206e6f74206475650000000000000000006064820152608490fd5b6084604051631101335b60e11b81526000600482015260406024820152601460448201527320a0991a1039b4b3b730ba3ab9329032b93937b960611b6064820152fd5b90612cdb611a53565b9160018060a01b0316600052600060205263ffffffff6001604060002001546001600160701b038160081c16845260781c166020830152565b610120610100820151910151808214612d3a57480180821015612d35575090565b905090565b5090565b60018060a01b0316600052600060205260406000208054918201809211610bd65781905590565b9190917f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f6080602083015192519460018060a01b0386511694602060018060a01b0360e089015116970151916040519283526000602084015260408301526060820152a4565b9060807f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f91602084015193519560018060a01b0387511695602060018060a01b0360e08a015116980151926040519384521515602084015260408301526060820152a4565b60208101519051907f67b4fa9642f42120bf031f3051d1824b0fe25627945b27b8a6a65d5761d5482e60208060018060a01b03855116940151604051908152a3565b50929192159081612f27575b50612eea576014811015612e97575b505061051a6117da565b601411610345573560601c3b15612eaf573880612e8d565b604051612ebd60408261043d565b601b81527f41413330207061796d6173746572206e6f74206465706c6f7965640000000000602082015290565b5050604051612efa60408261043d565b601981527f41413230206163636f756e74206e6f74206465706c6f79656400000000000000602082015290565b90503b1538612e7e565b15612f3857565b60405162461bcd60e51b815260206004820152601d60248201527f4141393320696e76616c6964207061796d6173746572416e64446174610000006044820152606490fd5b61300290612f9a612f8d82611c3b565b6001600160a01b03168452565b60208101356020840152612fbe6080820135906001600160801b038260801c921690565b6060850152604084015260a081013560c0840152612fec60c0820135906001600160801b038260801c921690565b61010085015261012084015260e0810190611c45565b90811561303e576130268260e092613021603461046d97961015612f31565b6135a5565b60a085015260808401526001600160a01b0316910152565b505060a081600060e0819401528260808201520152565b90816020910312610345575190565b61307c60409295949395606083526060830190612b03565b9460208201520152565b60a09061051a9392815260606020820152600d60608201526c10504c8cc81c995d995c9d1959609a1b608082015281604082015201906106f8565b949291939060206131479186519361310d60e06130e4875160018060a01b031690565b966130ff8b8d6130f76040890189611c45565b929091613603565b01516001600160a01b031690565b6001600160a01b03161597600092908961323b575b8401516040516306608bdf60e21b815295869485936000938593929160048501613064565b03926001600160a01b03881690f16000918161320a575b50613189578561316c612546565b6040516365c8fd4d60e01b81529182916115fe9160048401613086565b94929361319557505050565b6001600160a01b03166000908152602081905260409020918254908183116131bd5750039055565b60408051631101335b60e11b815260048101929092526024820152601760448201527f41413231206469646e2774207061792070726566756e640000000000000000006064820152608490fd5b61322d91925060203d602011613234575b613225818361043d565b810190613055565b903861315e565b503d61321b565b6001600160a01b0387166000908152602081905260409020909350548781111561326e5750600084815b94915050613122565b846000918903613265565b6001600160a01b0316600090815260016020908152604080832084821c845290915290208054916001600160401b03916132b2846114b1565b9055161490565b91906040838203126103455782516001600160401b038111610345576020916132e39185016118a9565b92015190565b60a09061051a9392815260606020820152600d60608201526c10504cccc81c995d995c9d1959609a1b608082015281604082015201906106f8565b929390915a815160e08101516001600160a01b031660008181526020819052604090209295909290919080548981106134665760206080600096948c969461338f9c9d8995039055015196015191604051998a95869485936314add44b60e21b855260048501613064565b03926001600160a01b031686f1938460009160009661343f575b506133d457856133b7612546565b6040516365c8fd4d60e01b81529182916115fe91600484016132e9565b9491925a9003116133e25750565b60408051631101335b60e11b815260048101929092526024820152602760448201527f41413336206f766572207061796d6173746572566572696669636174696f6e47606482015266185cd31a5b5a5d60ca1b608482015260a490fd5b90955061345f91503d806000833e613457818361043d565b8101906132b9565b94386133a9565b60408051631101335b60e11b8152600481018b90526024810191909152601e60448201527f41413331207061796d6173746572206465706f73697420746f6f206c6f7700006064820152608490fd5b8015613591576000604080516134ca81610406565b828152826020820152015265ffffffffffff8160a01c168015613584575b6135669061354d6134ff61350a6134ff8660d01c90565b65ffffffffffff1690565b9261352561351661047f565b6001600160a01b039097168752565b61353b6020870194859065ffffffffffff169052565b65ffffffffffff166040860181905290565b4211908115613569575b5091516001600160a01b031690565b91565b5161357c915065ffffffffffff166134ff565b421038613557565b5065ffffffffffff6134e8565b50600090600090565b816040519182372090565b9091826014116103455781359183602411610345576014810135936034116103455760609290921c92608090811c9260240135901c90565b90816020910312610345575161051a8161051d565b91602061051a938181520191611760565b92909181613612575b50505050565b8251516001600160a01b031693843b61382057600654600090602090613640906001600160a01b0316611fad565b60408751015160405180948193632b870d1b60e11b8352826136668b8b600484016135f2565b0393f1908115611e41576000916137f1575b506001600160a01b0381169586156137a2576001600160a01b031695869003613753573b1561370657506124676124617fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d936136d39361233d565b602083810151935160e00151604080516001600160a01b039485168152939091169183019190915290a33880808061360c565b60408051631101335b60e11b815260048101929092526024820152602060448201527f4141313520696e6974436f6465206d757374206372656174652073656e6465726064820152608490fd5b60408051631101335b60e11b8152600481018490526024810191909152602060448201527f4141313420696e6974436f6465206d7573742072657475726e2073656e6465726064820152608490fd5b60408051631101335b60e11b8152600481018590526024810191909152601b60448201527f4141313320696e6974436f6465206661696c6564206f72204f4f4700000000006064820152608490fd5b613813915060203d602011613819575b61380b818361043d565b8101906135dd565b38613678565b503d613801565b60408051631101335b60e11b815260048101929092526024820152601f60448201527f414131302073656e64657220616c726561647920636f6e7374727563746564006064820152608490fdfea2646970667358221220acbd8be1ea62c3ab5f653b3d7179466c115357e2ef9a32f72cf4bc2cab8d80c764736f6c634300081a0033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in FRAX
0
Token Allocations
FRAX
100.00%
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| FRAXTAL | 100.00% | $0.866582 | 0.000000020111 | <$0.000001 |
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
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.