Overview
APE Balance
0 APE
APE Value
$0.00More Info
Private Name Tags
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 2 internal transactions
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
6527110 | 51 days ago | Contract Creation | 0 APE | |||
6527110 | 51 days ago | Contract Creation | 0 APE |
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
EntryPointSimulations
Compiler Version
v0.8.23+commit.f704f362
Optimization Enabled:
Yes with 10000 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
//Imported from alto contracts //https://github.com/pimlicolabs/alto/blob/main/contracts/src/PimlicoEntryPointSimulations/EntryPointSimulations.sol //Itself was imported from eth-infinitism (main change is alto makes the contract deployable) //https://github.com/eth-infinitism/account-abstraction/blob/develop/contracts/core/EntryPointSimulations.sol // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.20; /* solhint-disable avoid-low-level-calls */ /* solhint-disable no-inline-assembly */ import "@account-abstraction/contracts/core/EntryPoint.sol"; import "./IEntryPointSimulations.sol"; /* * 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. * * Edit (Leo Vigna): Actually it SHOULD be deployed now that EntryPointV07 is designed for modular gas estimations without the need for * state overrides thanks to the addition of `delegateAndRevert` to the EntryPoint contract. The change below is from the * alto bundler contract but comments were not updated to reflect this. * Also see bottom section ("What's new v0.7") in this article for more info * https://blog.smart-contracts-developer.com/entrypoint-v0-7-0-the-new-era-of-account-abstraction-854f9f82912e */ contract EntryPointSimulations is EntryPoint, IEntryPointSimulations { // solhint-disable-next-line var-name-mixedcase AggregatorStakeInfo private NOT_AGGREGATED = AggregatorStakeInfo(address(0), StakeInfo(0, 0)); SenderCreator private _senderCreator; 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 * * Edit (Leo Vigna): Actually it SHOULD be deployed now that EntryPointV07 is designed for modular gas estimations without the need for * state overrides thanks to the addition of `delegateAndRevert` to the EntryPoint contract. The change below is from the * alto bundler contract but comments were not updated to reflect this. * Also see bottom section ("What's new v0.7") in this article for more info * https://blog.smart-contracts-developer.com/entrypoint-v0-7-0-the-new-era-of-account-abstraction-854f9f82912e */ constructor() { // require(block.number < 100, "should not be deployed"); } /// @inheritdoc IEntryPointSimulations function simulateValidation(PackedUserOperation calldata userOp) external returns (ValidationResult memory) { UserOpInfo memory outOpInfo; _simulationOnlyValidations(userOp); (uint256 validationData, uint256 paymasterValidationData) = _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 simulateCallData( PackedUserOperation calldata op, address target, bytes calldata targetCallData ) external returns (TargetCallResult memory) { UserOpInfo memory opInfo; _simulationOnlyValidations(op); _validatePrepayment(0, op, opInfo); bool targetSuccess; bytes memory targetResult; uint256 usedGas; if (target != address(0)) { uint256 remainingGas = gasleft(); (targetSuccess, targetResult) = target.call(targetCallData); usedGas = remainingGas - gasleft(); } return TargetCallResult(usedGas, targetSuccess, targetResult); } /// @inheritdoc IEntryPointSimulations function simulateHandleOp(PackedUserOperation calldata op) external nonReentrant returns (ExecutionResult memory) { UserOpInfo memory opInfo; _simulationOnlyValidations(op); (uint256 validationData, uint256 paymasterValidationData) = _validatePrepayment(0, op, opInfo); uint256 paid = _executeUserOp(0, op, opInfo); return ExecutionResult(opInfo.preOpGas, paid, validationData, paymasterValidationData, false, "0x"); } 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); } } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.23; /* solhint-disable avoid-low-level-calls */ /* solhint-disable no-inline-assembly */ import "../interfaces/IAccount.sol"; import "../interfaces/IAccountExecute.sol"; import "../interfaces/IPaymaster.sol"; import "../interfaces/IEntryPoint.sol"; import "../utils/Exec.sol"; import "./StakeManager.sol"; import "./SenderCreator.sol"; import "./Helpers.sol"; import "./NonceManager.sol"; import "./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 opIndex - Index into the opInfo array. * @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( uint256 opIndex, PackedUserOperation calldata userOp, UserOpInfo memory opInfo ) internal returns (uint256 collected) { uint256 preGas = gasleft(); bytes memory context = getMemoryBytesFromOffset(opInfo.contextOffset); bool success; { uint256 saveFreePtr; assembly ("memory-safe") { saveFreePtr := mload(0x40) } bytes calldata callData = userOp.callData; bytes memory innerCall; 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)); innerCall = abi.encodeCall(this.innerHandleOp, (executeUserOp, opInfo, context)); } else { innerCall = abi.encodeCall(this.innerHandleOp, (callData, opInfo, context)); } assembly ("memory-safe") { success := call(gas(), address(), 0, add(innerCall, 0x20), mload(innerCall), 0, 32) collected := mload(0) mstore(0x40, saveFreePtr) } } if (!success) { bytes32 innerRevertCode; assembly ("memory-safe") { let len := returndatasize() if eq(32,len) { returndatacopy(0, 0, 32) innerRevertCode := mload(0) } } if (innerRevertCode == INNER_OUT_OF_GAS) { // handleOps was called with gas limit too low. abort entire bundle. //can only be caused by bundler (leaving not enough gas for inner call) revert FailedOp(opIndex, "AA95 out of gas"); } else if (innerRevertCode == INNER_REVERT_LOW_PREFUND) { // innerCall reverted on prefund too low. treat entire prefund as "gas cost" uint256 actualGas = preGas - gasleft() + opInfo.preOpGas; uint256 actualGasCost = opInfo.prefund; emitPrefundTooLow(opInfo); emitUserOperationEvent(opInfo, false, actualGasCost, actualGas); collected = actualGasCost; } else { emit PostOpRevertReason( opInfo.userOpHash, opInfo.mUserOp.sender, opInfo.mUserOp.nonce, Exec.getReturnData(REVERT_REASON_MAX_LEN) ); uint256 actualGas = preGas - gasleft() + opInfo.preOpGas; collected = _postExecution( IPaymaster.PostOpMode.postOpReverted, opInfo, context, actualGas ); } } } 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 ) = _validatePrepayment(i, ops[i], opInfo); _validateAccountAndPaymasterValidationData( i, validationData, pmValidationData, address(0) ); } uint256 collected = 0; emit BeforeExecution(); for (uint256 i = 0; i < opslen; i++) { collected += _executeUserOp(i, ops[i], opInfos[i]); } _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 ) = _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++) { collected += _executeUserOp(opIndex, ops[i], opInfos[opIndex]); 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 calldata context ) external returns (uint256 actualGasCost) { uint256 preGas = gasleft(); require(msg.sender == address(this), "AA92 internal call only"); 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 ) { assembly ("memory-safe") { mstore(0, INNER_OUT_OF_GAS) revert(0, 32) } } } 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"); } 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 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; 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; } } /** * 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 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) { try IPaymaster(paymaster).postOp{ gas: mUserOp.paymasterPostOpGasLimit }(mode, context, actualGasCost, gasPrice) // solhint-disable-next-line no-empty-blocks {} catch { bytes memory reason = Exec.getReturnData(REVERT_REASON_MAX_LEN); revert PostOpReverted(reason); } } } } 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 { assembly ("memory-safe") { mstore(0, INNER_REVERT_LOW_PREFUND) revert(0, 32) } } } 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.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: 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-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; /* 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)); } }
// 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"; /** * 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); }
/** ** 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; interface INonceManager { /** * Return the next nonce for this sender. * Within a given key, the nonce values are sequenced (starting with zero, and incremented by one on each userop) * But UserOp with different keys can come with arbitrary order. * * @param sender the account address * @param key the high 192 bit of the nonce * @return nonce a full nonce to pass for next UserOp with this sender. */ function getNonce(address sender, uint192 key) external view returns (uint256 nonce); /** * Manually increment the nonce of the sender. * This method is exposed just for completeness.. * Account does NOT need to call it, neither during validation, nor elsewhere, * as the EntryPoint will update the nonce regardless. * Possible use-case is call it with various keys to "initialize" their nonces to one, so that future * UserOperations will not pay extra for the first transaction with a given key. */ function incrementNonce(uint192 key) external; }
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.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; }
// 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; /** * 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: 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: 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: 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/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); }
//Imported from alto contracts //https://github.com/pimlicolabs/alto/blob/main/contracts/src/PimlicoEntryPointSimulations/IEntryPointSimulations.sol // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.20; import "@account-abstraction/contracts/interfaces/PackedUserOperation.sol"; import "@account-abstraction/contracts/interfaces/IEntryPoint.sol"; interface IEntryPointSimulations is IEntryPoint { struct TargetCallResult { uint256 gasUsed; bool success; bytes returnData; } // Return value of simulateHandleOp. struct ExecutionResult { uint256 preOpGas; uint256 paid; uint256 accountValidationData; uint256 paymasterValidationData; 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); }
{ "evmVersion": "paris", "viaIR": true, "optimizer": { "enabled": true, "runs": 10000, "details": { "yul": true } }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"bytes","name":"ret","type":"bytes"}],"name":"DelegateAndRevert","type":"error"},{"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"},{"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":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"delegateAndRevert","outputs":[],"stateMutability":"nonpayable","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":[{"internalType":"bytes","name":"initCode","type":"bytes"}],"name":"getSenderAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes","name":"initCode","type":"bytes"},{"internalType":"bytes","name":"callData","type":"bytes"},{"internalType":"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":[{"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":"userOps","type":"tuple[]"},{"internalType":"contract IAggregator","name":"aggregator","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct IEntryPoint.UserOpsPerAggregator[]","name":"opsPerAggregator","type":"tuple[]"},{"internalType":"address payable","name":"beneficiary","type":"address"}],"name":"handleAggregatedOps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes","name":"initCode","type":"bytes"},{"internalType":"bytes","name":"callData","type":"bytes"},{"internalType":"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[]"},{"internalType":"address payable","name":"beneficiary","type":"address"}],"name":"handleOps","outputs":[],"stateMutability":"nonpayable","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"}],"name":"innerHandleOp","outputs":[{"internalType":"uint256","name":"actualGasCost","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":[{"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"}],"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":"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":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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
60a08060405234620000ba5760016002556101df8181016001600160401b03811183821017620000a457829162005aff833903906000f0801562000098576080526200004a620000bf565b6000815260208101906000825280602062000064620000bf565b600081520152600380546001600160a01b03191690555160045551600555604051615a1f9081620000e08239608051815050f35b6040513d6000823e3d90fd5b634e487b7160e01b600052604160045260246000fd5b600080fd5b60408051919082016001600160401b03811183821017620000a45760405256fe60806040526004361015610024575b361561001957600080fd5b610022336143a4565b005b60003560e01c806242dc531461385057806301ffc9a71461371c5780630396cb601461346a5780630bd28e3b1461340c5780631b2e01b8146133a3578063205c28781461327a57806322cdde4c1461325a57806335567e1a146131cd5780635287ce12146130ea5780635895273b146124c757806370a082311461248d578063765e827f14612240578063850aaf62146121a35780639b249f69146120b7578063b760faf91461209b578063bb9fe6bf14611f1b578063c23a5cea14611d17578063c3bce00914611223578063c5f996e6146106f7578063dbed18e0146101975763fc7e286d0361000e5734610192576020600319360112610192576001600160a01b03610130613f68565b16600052600060205260a0604060002065ffffffffffff6001825492015460405192835260ff8116151560208401526dffffffffffffffffffffffffffff8160081c16604084015263ffffffff8160781c16606084015260981c166080820152f35b600080fd5b34610192576101a53661404e565b906101ae614700565b60009160005b8281106104e757506101c68493614292565b6000805b8481106102e55750507fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f972600080a16000809360005b81811061023d57610236868660007f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d8180a2615668565b6001600255005b61028b61024b82848a61444b565b6001600160a01b0361025f602083016144df565b167f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d600080a28061448b565b906000915b8083106102a2575050506001016101ff565b909194976102dc6102d66001926102d08c8b6102c9826102c38e8b8d614324565b926142e1565b51916151ac565b906140af565b996140bc565b95019190610290565b60206102f282878961444b565b6103086102ff828061448b565b939092016144df565b916000926001600160a01b038091165b82851061032c5750505050506001016101ca565b909192939561035b83610354610342848c6142e1565b5161034e8b898b614324565b8561483c565b9290615960565b9116840361049b5761044f576103718491615960565b911661040357610391576103866001916140bc565b960193929190610318565b60a48760405190631101335b60e11b8252600482015260406024820152602160448201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560648201527f65000000000000000000000000000000000000000000000000000000000000006084820152fd5b60848860405190631101335b60e11b8252600482015260406024820152601460448201527f41413334207369676e6174757265206572726f720000000000000000000000006064820152fd5b60848860405190631101335b60e11b8252600482015260406024820152601760448201527f414132322065787069726564206f72206e6f74206475650000000000000000006064820152fd5b60848960405190631101335b60e11b8252600482015260406024820152601460448201527f41413234207369676e6174757265206572726f720000000000000000000000006064820152fd5b6104f281848761444b565b936104fd858061448b565b91909560206001600160a01b036105158284016144df565b1697600192838a146106b35789610545575b50505050600192939495509061053c916140af565b939291016101b4565b8060406105539201906143fa565b918a3b1561019257929391906040519485937f2dd8113300000000000000000000000000000000000000000000000000000000855288604486016040600488015252606490818601918a60051b8701019680936000915b8c8310610633575050505050508383926105d1926003198560009803016024860152614383565b03818a5afa9081610624575b5061061357602486604051907f86a9f7500000000000000000000000000000000000000000000000000000000082526004820152fd5b939450849361053c60018980610527565b61062d90613ec8565b886105dd565b91939596977fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9c908a9294969a0301865288357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee18336030181121561019257836106a0879385839401614543565b9a019601930190918997969594926105aa565b6064836040519062461bcd60e51b82526004820152601760248201527f4141393620696e76616c69642061676772656761746f720000000000000000006044820152fd5b34610192576003196060813601126101925767ffffffffffffffff6004351161019257610120906004353603011261019257610731613f52565b60443567ffffffffffffffff811161019257610751903690600401613f7e565b909160606040805161076281613eac565b60008152600060208201520152610777614209565b610785600435600401614739565b5a8151906001600160a01b0361079f6004356004016144df565b168252600480356024810135602085015260848101356fffffffffffffffffffffffffffffffff8181166060870152608091821c604087015260a483013560c087015260c4830135908116610100870152901c6101208501526108079160e4820191016143fa565b801561120757603481106111c3578060141161019257806024116101925760341161019257602481013560801c60a0840152601481013560801c60808401523560601c60e08301525b61085e600435600401614126565b60208401526040820151916effffffffffffffffffffffffffffff8360c08301511760608301511760808301511760a08301511761010083015117610120830151171161117f57604081015160608201510160808201510160a08201510160c082015101610100820151029284516001600160a01b03815116906108ec6044600435016004356004016143fa565b80610f31575b505060e001516001600160a01b031660008115610ef9575b602061094e91818a015160405193849283927f19822f7c0000000000000000000000000000000000000000000000000000000084526004356004016004850161593e565b038160008789f19081610ece575b50610a09576109fd3d610800808211610a01575b50604051906020818301016040528082526000602083013e6040519182917f65c8fd4d0000000000000000000000000000000000000000000000000000000083526000600484015260606024840152600d60648401527f4141323320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a4830190614029565b0390fd5b905082610970565b15610e61575b506001600160a01b03825116602083015190600052600160205260406000208160401c60005260205267ffffffffffffffff604060002091825492610a53846140bc565b90551603610e15575a830311610dc9576001600160a01b0360e0606092015116610b3f575b6080926040850152606084015260a46004350135905a9003019101526000926060916000936001600160a01b038216610aff575b505050610afb9060405192610ac084613eac565b835260208301931515845260408301908152604051938493602085525160208501525115156040840152516060808401526080830190614029565b0390f35b9091945060008094508093505a95826040519384928337810182815203925af1610afb610b36610b2d6140f6565b92935a906140e9565b91908480610aac565b505a9183516001600160a01b0360e08201511690816000526000602052604060002090815491848310610d7d576080600092869283610bbf960390550151936020890151836040518096819582947f52b7512c0000000000000000000000000000000000000000000000000000000084526004356004016004850161593e565b039287f160009181610cf6575b50610c75576109fd3d610800808211610c6d575b50604051906020818301016040528082526000602083013e6040519182917f65c8fd4d0000000000000000000000000000000000000000000000000000000083526000600484015260606024840152600d60648401527f4141333320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a4830190614029565b905082610be0565b935a900311610c845791610a78565b60a4604051631101335b60e11b81526000600482015260406024820152602760448201527f41413336206f766572207061796d6173746572566572696669636174696f6e4760648201527f61734c696d6974000000000000000000000000000000000000000000000000006084820152fd5b9091503d90816000823e610d0a8282613edc565b60408183810103126101925780519067ffffffffffffffff821161019257828101601f838301011215610192578181015190610d4582613eff565b93610d536040519586613edc565b8285528101602083858401010111610192576020610d7693818601920101614006565b908a610bcc565b6084604051631101335b60e11b81526000600482015260406024820152601e60448201527f41413331207061796d6173746572206465706f73697420746f6f206c6f7700006064820152fd5b6084604051631101335b60e11b81526000600482015260406024820152601e60448201527f41413236206f76657220766572696669636174696f6e4761734c696d697400006064820152fd5b6084604051631101335b60e11b81526000600482015260406024820152601a60448201527f4141323520696e76616c6964206163636f756e74206e6f6e63650000000000006064820152fd5b600052600060205260406000208054808611610e8257859003905588610a0f565b6084604051631101335b60e11b81526000600482015260406024820152601760448201527f41413231206469646e2774207061792070726566756e640000000000000000006064820152fd5b602090813d8311610ef2575b610ee48183613edc565b81010312610192578b61095c565b503d610eda565b50816000526000602052604060002054868111600014610f24575061094e602060005b91505061090a565b602061094e918803610f1c565b833b61113357600060206001600160a01b036006541660408c510151604051809481937f570e1a3600000000000000000000000000000000000000000000000000000000835285600484015282610f8c602482018a8c614383565b0393f1908115611127576000916110f8575b506001600160a01b03811680156110ac578503611060573b1561101457601411610192576001600160a01b039183897fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d604060e0958787602086015195510151168251913560601c82526020820152a3916108f2565b6084604051631101335b60e11b81526000600482015260406024820152602060448201527f4141313520696e6974436f6465206d757374206372656174652073656e6465726064820152fd5b6084604051631101335b60e11b81526000600482015260406024820152602060448201527f4141313420696e6974436f6465206d7573742072657475726e2073656e6465726064820152fd5b6084604051631101335b60e11b81526000600482015260406024820152601b60448201527f4141313320696e6974436f6465206661696c6564206f72204f4f4700000000006064820152fd5b61111a915060203d602011611120575b6111128183613edc565b810190614364565b8d610f9e565b503d611108565b6040513d6000823e3d90fd5b6084604051631101335b60e11b81526000600482015260406024820152601f60448201527f414131302073656e64657220616c726561647920636f6e7374727563746564006064820152fd5b606460405162461bcd60e51b815260206004820152601860248201527f41413934206761732076616c756573206f766572666c6f7700000000000000006044820152fd5b606460405162461bcd60e51b815260206004820152601d60248201527f4141393320696e76616c6964207061796d6173746572416e64446174610000006044820152fd5b5050600060e083015260006080830152600060a0830152610850565b346101925761123136613fd3565b60405161123d81613e0c565b60405161124981613e0c565b6000815260006020820152600060408201526000606082015260606080820152815260405161127781613e90565b6000815260006020820152602082015260405161129381613e90565b600081526000602082015260408201526040516112af81613e90565b600081526000602082015260608201526080604051916112ce83613e90565b600083526040516112de81613e90565b6000815260006020820152602084015201526112f8614209565b9061130281614739565b6000905a928051936001600160a01b0361131b846144df565b168552602083013560208601526fffffffffffffffffffffffffffffffff6080840135166060860152608083013560801c604086015260a083013560c08601526fffffffffffffffffffffffffffffffff60c08401351661010086015260c083013560801c61012086015261139360e08401846143fa565b8015611cfb57603481106111c3578060141161019257806024116101925760341161019257602481013560801c60a0870152601481013560801c60808701523560601c60e08601525b6113e583614126565b60208301526040850151946effffffffffffffffffffffffffffff8660c08301511760608301511760808301511760a08301511761010083015117610120830151171161117f57604081015160608201510160808201510160a08201510160c082015101610100820151028351966001600160a01b038851169761146c60408801886143fa565b80611bf9575b505060e001516001600160a01b03169760008915611bc1575b60206114ca918189015160405193849283927f19822f7c0000000000000000000000000000000000000000000000000000000084528d6004850161593e565b038160008688f160009181611b8d575b5061157a576109fd3d610800808211610a015750604051906020818301016040528082526000602083013e6040519182917f65c8fd4d0000000000000000000000000000000000000000000000000000000083526000600484015260606024840152600d60648401527f4141323320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a4830190614029565b9815611b6c575b506001600160a01b03835116602084015190600052600160205260406000208160401c60005260205267ffffffffffffffff6040600020918254926115c5846140bc565b90551603610e15575a840311610dc9576001600160a01b0360e060609301511661199f575b6040840152606083015260a0830135905a90030160808201526001600160a01b0361161485615960565b911661195357611907576001600160a01b0361162f84615960565b91166118bb57611849576116506001600160a01b0360e08351015116615718565b916116886116686001600160a01b0384515116615718565b916000602060405161167981613e90565b828152015260408101906143fa565b6014811061183d57601411610192576116a4903560601c615718565b916001600160a01b038616946080820151966060604084015193015192604051986116ce8a613e0c565b895260208901526040880152606087015260808601526040516116f081613e90565b6001600160a01b0360035416815260405161170a81613e90565b6004548152600554602082015260208201529380151580611832575b61180b575b506040519461173986613e0c565b8552602085015260408401526060830152608082015260405180916020825260208060806117a78185516101408589015280516101608901528481015161018089015260408101516101a089015260608101516101c0890152015160a06101e0880152610200870190614029565b9382808201518051604089015201516060870152826040820151805184890152015160a0870152826060820151805160c0890152015160e087015201516001600160a01b038151166101008601520151805161012085015201516101408301520390f35b90935061181781615718565b6040519161182483613e90565b82526020820152928561172b565b506001811415611726565b50506116a46000615718565b60a4604051631101335b60e11b81526000600482015260406024820152602160448201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560648201527f65000000000000000000000000000000000000000000000000000000000000006084820152fd5b6084604051631101335b60e11b81526000600482015260406024820152601460448201527f41413334207369676e6174757265206572726f720000000000000000000000006064820152fd5b6084604051631101335b60e11b81526000600482015260406024820152601760448201527f414132322065787069726564206f72206e6f74206475650000000000000000006064820152fd5b6084604051631101335b60e11b81526000600482015260406024820152601460448201527f41413234207369676e6174757265206572726f720000000000000000000000006064820152fd5b9450505a938251946001600160a01b0360e087015116806000526000602052604060002096875497848910610d7d576080600092869283611a1d9c0390550151926020880151838a6040519c8d95869485937f52b7512c0000000000000000000000000000000000000000000000000000000085526004850161593e565b039286f19687600091600099611adf575b50611ace576109fd3d610800808211610c6d5750604051906020818301016040528082526000602083013e6040519182917f65c8fd4d0000000000000000000000000000000000000000000000000000000083526000600484015260606024840152600d60648401527f4141333320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a4830190614029565b96915a900311610c845794906115ea565b915097503d90816000823e611af48282613edc565b60408183810103126101925780519067ffffffffffffffff821161019257828101601f838301011215610192578181015191611b2f83613eff565b93611b3d6040519586613edc565b838552820160208483850101011161019257602092611b63918480870191850101614006565b0151978a611a2e565b600052600060205260406000208054808411610e8257839003905588611581565b9091506020813d602011611bb9575b81611ba960209383613edc565b810103126101925751908b6114da565b3d9150611b9c565b50806000526000602052604060002054838111600014611bec57506114ca602060005b91505061148b565b60206114ca918503611be4565b8a3b61113357600060206001600160a01b036006541660408b510151604051809481937f570e1a3600000000000000000000000000000000000000000000000000000000835285600484015282611c54602482018a8c614383565b0393f190811561112757600091611cdc575b506001600160a01b03811680156110ac578c03611060573b1561101457601411610192576001600160a01b03918a887fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d604060e0958787602086015195510151168251913560601c82526020820152a391611472565b611cf5915060203d602011611120576111128183613edc565b8c611c66565b5050600060e086015260006080860152600060a08601526113dc565b346101925760208060031936011261019257611d31613f68565b33600052600082526001604060002001908154916dffffffffffffffffffffffffffff8360081c16928315611ed75765ffffffffffff8160981c168015611e93574210611e4f576000936001600160a01b03859485947fffffffffffffff000000000000000000000000000000000000000000000000ff86951690556040517fb7c918e0e249f999e965cafeb6c664271b3f4317d296461500e71da39f0cbda3339180611df5878683602090939291936001600160a01b0360408201951681520152565b0390a2165af1611e036140f6565b5015611e0b57005b6064906040519062461bcd60e51b82526004820152601860248201527f6661696c656420746f207769746864726177207374616b6500000000000000006044820152fd5b6064856040519062461bcd60e51b82526004820152601b60248201527f5374616b65207769746864726177616c206973206e6f742064756500000000006044820152fd5b6064866040519062461bcd60e51b82526004820152601d60248201527f6d7573742063616c6c20756e6c6f636b5374616b6528292066697273740000006044820152fd5b6064856040519062461bcd60e51b82526004820152601460248201527f4e6f207374616b6520746f2077697468647261770000000000000000000000006044820152fd5b34610192576000600319360112610192573360005260006020526001604060002001805463ffffffff8160781c169081156120575760ff16156120135765ffffffffffff908142160191818311611fe45780547fffffffffffffff000000000000ffffffffffffffffffffffffffffffffffff001678ffffffffffff00000000000000000000000000000000000000609885901b161790556040519116815233907ffa9b3c14cc825c412c9ed81b3ba365a5b459439403f18829e572ed53a4180f0a90602090a2005b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b606460405162461bcd60e51b815260206004820152601160248201527f616c726561647920756e7374616b696e670000000000000000000000000000006044820152fd5b606460405162461bcd60e51b815260206004820152600a60248201527f6e6f74207374616b6564000000000000000000000000000000000000000000006044820152fd5b6020600319360112610192576100226120b2613f68565b6143a4565b346101925760206003193601126101925760043567ffffffffffffffff81116101925760206120ed61213c923690600401613f7e565b91906001600160a01b039283600654169060006040518097819582947f570e1a360000000000000000000000000000000000000000000000000000000084528860048501526024840191614383565b03925af190811561112757602492600092612182575b50604051917f6ca7b806000000000000000000000000000000000000000000000000000000008352166004820152fd5b61219c91925060203d602011611120576111128183613edc565b9083612152565b34610192576040600319360112610192576121bc613f68565b60243567ffffffffffffffff8111610192576000916121e083923690600401613f7e565b90816040519283928337810184815203915af46121fb6140f6565b906109fd6040519283927f9941055400000000000000000000000000000000000000000000000000000000845215156004840152604060248401526044830190614029565b346101925761224e3661404e565b612259929192614700565b61226283614292565b60005b8481106122da57506000927fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f972600080a16000915b8583106122aa576102368585615668565b9091936001906122d06122be878987614324565b6122c888866142e1565b5190886151ac565b0194019190612299565b6123056122fe6122ec838597956142e1565b516122f8848987614324565b8461483c565b9190615960565b6001600160a01b0392918316612441576123f55761232290615960565b91166123a95761233757600101929092612265565b60a49060405190631101335b60e11b8252600482015260406024820152602160448201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560648201527f65000000000000000000000000000000000000000000000000000000000000006084820152fd5b60848260405190631101335b60e11b8252600482015260406024820152601460448201527f41413334207369676e6174757265206572726f720000000000000000000000006064820152fd5b60848360405190631101335b60e11b8252600482015260406024820152601760448201527f414132322065787069726564206f72206e6f74206475650000000000000000006064820152fd5b60848460405190631101335b60e11b8252600482015260406024820152601460448201527f41413234207369676e6174757265206572726f720000000000000000000000006064820152fd5b34610192576020600319360112610192576001600160a01b036124ae613f68565b1660005260006020526020604060002054604051908152f35b34610192576124d536613fd3565b606060a06040516124e581613e74565b60008152600060208201526000604082015260008382015260006080820152015261250e614700565b612516614209565b61251f82614739565b6000905a9080516001600160a01b03612537866144df565b1681526020850135602082015260808501356fffffffffffffffffffffffffffffffff90818116606084015260801c604083015260a086013560c083015260c086013590811661010083015260801c61012082015261259960e08601866143fa565b80156130ce57603481106111c3578060141161019257806024116101925760341161019257602481013560801c60a0830152601481013560801c60808301523560601c60e08201525b6125eb85614126565b60208301526040810151926effffffffffffffffffffffffffffff8460c08401511760608401511760808401511760a08401511761010084015117610120840151171161117f57604082015160608301510160808301510160a08301510160c083015101610100830151028351946001600160a01b038651169561267260408a018a6143fa565b80612fcc575b505060e001516001600160a01b03169560008715612fa3575b6020808801518b6126cf60405194859384937f19822f7c0000000000000000000000000000000000000000000000000000000085526004850161593e565b038160008688f160009181612f6f575b5061277f576109fd3d610800808211610a015750604051906020818301016040528082526000602083013e6040519182917f65c8fd4d0000000000000000000000000000000000000000000000000000000083526000600484015260606024840152600d60648401527f4141323320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a4830190614029565b9615612f4e575b506001600160a01b03845116602085015190600052600160205260406000208160401c60005260205267ffffffffffffffff6040600020918254926127ca846140bc565b90551603610e15575a830311610dc9576001600160a01b0360e0606094015116612d8a575b604084015281606084015260a0860135905a90030160808301525a604051957fffffffff000000000000000000000000000000000000000000000000000000008761283d60608401846143fa565b600060038211612d82575b7f8dd7712f0000000000000000000000000000000000000000000000000000000094168403612c50575050506128fc6129da602093600093858901516128a260405193849389850152604060248501526064840190614543565b90604483015203906128bc601f1992838101835282613edc565b6129ce6040519485927e42dc5300000000000000000000000000000000000000000000000000000000898501526102006024850152610224840190614029565b61299d604484018c60806101a09180516001600160a01b03808251168652602082015160208701526040820151604087015260608201516060870152838201518487015260a082015160a087015260c082015160c087015260e08201511660e0860152610100808201519086015261012080910151908501526020810151610140850152604081015161016085015260608101516101808501520151910152565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc8382030161020484015289614029565b03908101835282613edc565b828151910182305af16000519660405215612aa6575b50506080015160405192610afb9291612a0885613e74565b845260208401948552604084019182526060840190815260808401906000825260405192612a3584613e90565b600284527f3078000000000000000000000000000000000000000000000000000000000000602085015260a0860193845260016002556040519687966020885251602088015251604087015251606086015251608085015251151560a08401525160c08084015260e0830190614029565b90929194506000903d602014612c3f575b7fdeaddead000000000000000000000000000000000000000000000000000000008203612b2a576084604051631101335b60e11b81526000600482015260406024820152600f60448201527f41413935206f7574206f662067617300000000000000000000000000000000006064820152fd5b610afb936080927fdeadaa510000000000000000000000000000000000000000000000000000000003612b925750612b66612b70915a906140e9565b82870151906140af565b612b89604087015191612b8288615825565b82886157c3565b945b91926129f0565b612c2a612c20612c319360208a01518a51907ff62676f440ff169a3a9afdbf812e89e7f95975ee8e5c31214ffdef631c5f479260206001600160a01b038451169301513d90610800808311612c37575b50604051916020818401016040528083526000602084013e612c166040519283928352604060208401526040830190614029565b0390a35a906140e9565b84890151906140af565b9087614607565b94612b8b565b91508f612be2565b905060206000803e60005190612ab7565b612d78945082935090612c98917e42dc53000000000000000000000000000000000000000000000000000000006020612d6a9501526102006024860152610224850191614383565b612d39604484018860806101a09180516001600160a01b03808251168652602082015160208701526040820151604087015260608201516060870152838201518487015260a082015160a087015260c082015160c087015260e08201511660e0860152610100808201519086015261012080910151908501526020810151610140850152604081015161016085015260608101516101808501520151910152565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc8382030161020484015285614029565b03601f198101885287613edc565b60206000876129da565b508135612848565b915093505a938251946001600160a01b0360e087015116806000526000602052604060002096875497858910610d7d576080600092879283612e099c0390550151926020880151838c6040519c8d95869485937f52b7512c0000000000000000000000000000000000000000000000000000000085526004850161593e565b039286f19687600091600099612ecb575b50612eba576109fd3d610800808211610c6d5750604051906020818301016040528082526000602083013e6040519182917f65c8fd4d0000000000000000000000000000000000000000000000000000000083526000600484015260606024840152600d60648401527f4141333320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a4830190614029565b96915a900311610c845794916127ef565b915097503d806000833e612edf8183613edc565b81019060408183031261019257805167ffffffffffffffff81116101925781019082601f8301121561019257815191612f1783613eff565b93612f256040519586613edc565b8385526020848301011161019257602092612f4591848087019101614006565b0151978a612e1a565b600052600060205260406000208054808411610e8257839003905588612786565b9091506020813d602011612f9b575b81612f8b60209383613edc565b810103126101925751908b6126df565b3d9150612f7e565b50806000526000602052604060002054838111600014612fc557506000612691565b8303612691565b883b61113357600060206001600160a01b036006541660408b510151604051809481937f570e1a3600000000000000000000000000000000000000000000000000000000835285600484015282613027602482018a8c614383565b0393f1908115611127576000916130af575b506001600160a01b03811680156110ac578a03611060573b1561101457601411610192576001600160a01b039188887fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d604060e0958787602086015195510151168251913560601c82526020820152a391612678565b6130c8915060203d602011611120576111128183613edc565b8c613039565b5050600060e082015260006080820152600060a08201526125e2565b34610192576020600319360112610192576001600160a01b0361310b613f68565b6000608060405161311b81613e0c565b828152826020820152826040820152826060820152015216600052600060205260a06040600020608060405161315081613e0c565b6001835493848352015490602081019060ff8316151582526dffffffffffffffffffffffffffff60408201818560081c16815263ffffffff936060840193858760781c16855265ffffffffffff978891019660981c1686526040519788525115156020880152511660408601525116606084015251166080820152f35b346101925760406003193601126101925760206131e8613f68565b6001600160a01b036131f8613fac565b911660005260018252604060002077ffffffffffffffffffffffffffffffffffffffffffffffff821660005282526040600020547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000006040519260401b16178152f35b3461019257602061327261326d36613fd3565b614126565b604051908152f35b3461019257604060031936011261019257613293613f68565b6024359033600052600060205260406000209081549182841161335f57600080856001600160a01b03829583956132ca848a6140e9565b9055604080516001600160a01b03831681526020810185905233917fd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb91a2165af16133136140f6565b501561331b57005b606460405162461bcd60e51b815260206004820152601260248201527f6661696c656420746f20776974686472617700000000000000000000000000006044820152fd5b606460405162461bcd60e51b815260206004820152601960248201527f576974686472617720616d6f756e7420746f6f206c61726765000000000000006044820152fd5b34610192576040600319360112610192576133bc613f68565b6001600160a01b036133cc613fac565b9116600052600160205277ffffffffffffffffffffffffffffffffffffffffffffffff604060002091166000526020526020604060002054604051908152f35b346101925760206003193601126101925760043577ffffffffffffffffffffffffffffffffffffffffffffffff811680910361019257336000526001602052604060002090600052602052604060002061346681546140bc565b9055005b6020806003193601126101925760043563ffffffff9182821680920361019257336000526000815260406000209282156136d8576001840154908160781c168310613694576134ce6dffffffffffffffffffffffffffff9182349160081c166140af565b9384156136505781851161360c579065ffffffffffff6135db9254604051906134f682613e0c565b8152848101926001845260408201908816815260608201878152600160808401936000855233600052600089526040600020905181550194511515917fffffffffffffffffffffffffff0000000000000000000000000000000000000060ff72ffffffff0000000000000000000000000000006effffffffffffffffffffffffffff008954945160081b16945160781b1694169116171717835551167fffffffffffffff000000000000ffffffffffffffffffffffffffffffffffffff78ffffffffffff0000000000000000000000000000000000000083549260981b169116179055565b6040519283528201527fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c0160403392a2005b6064836040519062461bcd60e51b82526004820152600e60248201527f7374616b65206f766572666c6f770000000000000000000000000000000000006044820152fd5b6064836040519062461bcd60e51b82526004820152601260248201527f6e6f207374616b652073706563696669656400000000000000000000000000006044820152fd5b6064826040519062461bcd60e51b82526004820152601c60248201527f63616e6e6f7420646563726561736520756e7374616b652074696d65000000006044820152fd5b6064826040519062461bcd60e51b82526004820152601a60248201527f6d757374207370656369667920756e7374616b652064656c61790000000000006044820152fd5b34610192576020600319360112610192576004357fffffffff00000000000000000000000000000000000000000000000000000000811680910361019257807f60fc6b6e0000000000000000000000000000000000000000000000000000000060209214908115613826575b81156137fc575b81156137d2575b81156137a8575b506040519015158152f35b7f01ffc9a7000000000000000000000000000000000000000000000000000000009150148261379d565b7f3e84f0210000000000000000000000000000000000000000000000000000000081149150613796565b7fcf28ef97000000000000000000000000000000000000000000000000000000008114915061378f565b7f915074d80000000000000000000000000000000000000000000000000000000081149150613788565b34610192576102006003193601126101925767ffffffffffffffff600435818111610192573660238201121561019257613894903690602481600401359101613f1b565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc3601906101c0821261019257610140604051926138d284613e0c565b12610192576040516138e381613e57565b6138eb613f52565b815260443560208201526064356040820152608435606082015260a435608082015260c43560a082015260e43560c0820152610104356001600160a01b03811681036101925760e0820152610124356101008201526101443561012082015282526101643560208301526101843560408301526101a43560608301526101c43560808301526101e43590811161019257613989903690600401613f7e565b91905a303303613dc8578251606081015195603f5a0260061c61271060a084015189010111613d9e5760009681519182613cd4575b50505050906139d8915a9003608084015101933691613f1b565b915a6000938351926139e984615772565b916001600160a01b0360e086015116908115600014613b895750506001600160a01b03845116925b5a9003019260a06060820151910151016080850151840390818111613b75575b50508202604084015191818310600014613ac55750506003851015613a9857602094600203613a70576132729293508093613a6b81615825565b6157c3565b5050507fdeadaa51000000000000000000000000000000000000000000000000000000008152fd5b6024847f4e487b710000000000000000000000000000000000000000000000000000000081526021600452fd5b81613ad59296979593039061579c565b506003831015613b4857602094507f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f6080868301519251946001600160a01b0386511694886001600160a01b0360e0890151169701519160405192835215898301528760408301526060820152a4613272565b6024857f4e487b710000000000000000000000000000000000000000000000000000000081526021600452fd5b6064919003600a0204909201918680613a31565b819491948151613b9b575b5050613a11565b60038a1015613ca55760028a0315613b945760a087015191813b1561019257613c05928b600080946040518097819682957f7c627b210000000000000000000000000000000000000000000000000000000084526004840152608060248401526084830190614029565b8b8b0260448301528b60648301520393f19081613c91575b50613c8a576109fd873d610800808211613c82575b5060405191602082840101604052818352602083013e6040519182917fad7954bc000000000000000000000000000000000000000000000000000000008352602060048401526024830190614029565b905083613c32565b8880613b94565b613c9c919850613ec8565b60009689613c1d565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b916000929183809360206001600160a01b03885116910192f115613cfb575b8080806139be565b6139d8929195503d610800808211613d96575b50604051906020818301016040528082526000602083013e8051613d39575b50506001949091613cf3565b7f1c4fada7374c0a9ee8841fc38afe82932dc0f8e69012e927f061a8bae611a20160208601519160206001600160a01b03855116940151613d8c6040519283928352604060208401526040830190614029565b0390a38580613d2d565b905087613d0e565b7fdeaddead0000000000000000000000000000000000000000000000000000000060005260206000fd5b606460405162461bcd60e51b815260206004820152601760248201527f4141393220696e7465726e616c2063616c6c206f6e6c790000000000000000006044820152fd5b60a0810190811067ffffffffffffffff821117613e2857604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b610140810190811067ffffffffffffffff821117613e2857604052565b60c0810190811067ffffffffffffffff821117613e2857604052565b6040810190811067ffffffffffffffff821117613e2857604052565b6060810190811067ffffffffffffffff821117613e2857604052565b67ffffffffffffffff8111613e2857604052565b90601f601f19910116810190811067ffffffffffffffff821117613e2857604052565b67ffffffffffffffff8111613e2857601f01601f191660200190565b929192613f2782613eff565b91613f356040519384613edc565b829481845281830111610192578281602093846000960137010152565b602435906001600160a01b038216820361019257565b600435906001600160a01b038216820361019257565b9181601f840112156101925782359167ffffffffffffffff8311610192576020838186019501011161019257565b6024359077ffffffffffffffffffffffffffffffffffffffffffffffff8216820361019257565b60031990602082820112610192576004359167ffffffffffffffff83116101925782610120920301126101925760040190565b60005b8381106140195750506000910152565b8181015183820152602001614009565b90601f19601f60209361404781518092818752878088019101614006565b0116010190565b9060406003198301126101925760043567ffffffffffffffff9283821161019257806023830112156101925781600401359384116101925760248460051b830101116101925760240191906024356001600160a01b03811681036101925790565b91908201809211611fe457565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114611fe45760010190565b91908203918211611fe457565b3d15614121573d9061410782613eff565b916141156040519384613edc565b82523d6000602084013e565b606090565b6040614134818301836143fa565b908183519182372061414960608401846143fa565b90818451918237209260c061416160e08301836143fa565b90818651918237209184519560208701946001600160a01b03833516865260208301358789015260608801526080870152608081013560a087015260a081013582870152013560e08501526101009081850152835261012083019167ffffffffffffffff9184841083851117613e2857838252845190206101408501908152306101608601524661018086015260608452936101a00191821183831017613e28575251902090565b6040519061421682613e0c565b60405160808361422583613e57565b60009283815283602082015283604082015283606082015283838201528360a08201528360c08201528360e0820152836101008201528361012082015281528260208201528260408201528260608201520152565b67ffffffffffffffff8111613e285760051b60200190565b9061429c8261427a565b6142a96040519182613edc565b828152601f196142b9829461427a565b019060005b8281106142ca57505050565b6020906142d5614209565b828285010152016142be565b80518210156142f55760209160051b010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b91908110156142f55760051b810135907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee181360301821215610192570190565b9081602091031261019257516001600160a01b03811681036101925790565b601f8260209493601f19938186528686013760008582860101520116010190565b6001805b600581106143f35750507f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c460206001600160a01b036143e7348561579c565b936040519485521692a2565b81016143a8565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610192570180359067ffffffffffffffff82116101925760200191813603831361019257565b91908110156142f55760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa181360301821215610192570190565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610192570180359067ffffffffffffffff821161019257602001918160051b3603831361019257565b356001600160a01b03811681036101925790565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18236030181121561019257016020813591019167ffffffffffffffff821161019257813603831361019257565b6101209181356001600160a01b038116809103610192576145ac614591614604956145e59385526020860135602086015261458160408701876144f3565b9091806040880152860191614383565b61459e60608601866144f3565b908583036060870152614383565b6080840135608084015260a084013560a084015260c084013560c08401526145d760e08501856144f3565b9084830360e0860152614383565b916145f661010091828101906144f3565b929091818503910152614383565b90565b9291905a9060009085519361461b85615772565b916001600160a01b03908160e08801511680156000146146ec575050855116935b5a9003019360a060608201519101510160808701518503908181116146d8575b505083026040860151928184106000146146b75750508061468a575090816146889294613a6b81615825565b565b807f4e487b7100000000000000000000000000000000000000000000000000000000602492526021600452fd5b6146c7908284939895039061579c565b5061468a57509083614688926157c3565b6064919003600a020490930192388061465c565b9095915094511561463c576000935061463c565b600280541461470f5760028055565b60046040517f3ee5aeb5000000000000000000000000000000000000000000000000000000008152fd5b614807906001600160a01b0360405160208101907fd69400000000000000000000000000000000000000000000000000000000000082523060601b60228201527f01000000000000000000000000000000000000000000000000000000000000006036820152601781526147ac81613e90565b519020167fffffffffffffffffffffffff000000000000000000000000000000000000000060065416176006556147e660408201826143fa565b90506147ff6147f4836144df565b9260e08101906143fa565b929091615868565b80516148105750565b6109fd90604051918291631101335b60e11b835260006004840152604060248401526044830190614029565b926000905a938051946001600160a01b03614856866144df565b1686526020850135602087015260808501356fffffffffffffffffffffffffffffffff90818116606089015260801c604088015260a086013560c088015260c086013590811661010088015260801c6101208701526148b860e08601866143fa565b801561519057603481106111c3578060141161019257806024116101925760341161019257602481013560801c60a0880152601481013560801c60808801523560601c60e08701525b61490a85614126565b60208301526040860151946effffffffffffffffffffffffffffff8660c08901511760608901511760808901511760a08901511761010089015117610120890151171161117f57604087015160608801510160808801510160a08801510160c088015101610100880151029683516001600160a01b038151169061499160408501856143fa565b80614f5e575b505060e001516001600160a01b03169060008215614f26575b60206149f5918b828a01516000868a604051978896879586937f19822f7c0000000000000000000000000000000000000000000000000000000085526004850161593e565b0393f160009181614ef2575b50614aa9573d8c610800808311614aa1575b50604051916020818401016040528083526000602084013e6109fd6040519283927f65c8fd4d000000000000000000000000000000000000000000000000000000008452600484015260606024840152600d60648401527f4141323320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a4830190614029565b915082614a13565b9a92939495969798999a9115614e85575b50976001600160a01b03835116602084015190600052600160205260406000208160401c60005260205267ffffffffffffffff604060002091825492614aff846140bc565b90551603614e39575a850311614ded576001600160a01b0360e0606093015116614b46575b509060a09184959697986040608096015260608601520135905a900301910152565b969550505a968351976001600160a01b0360e08a01511680600052600060205260406000208054848110614da1576080614bc49a9b9c600093878094039055015192602089015183604051809d819582947f52b7512c0000000000000000000000000000000000000000000000000000000084528c6004850161593e565b039286f1978860009160009a614d14575b50614c7d573d8b610800808311614c75575b50604051916020818401016040528083526000602084013e6109fd6040519283927f65c8fd4d000000000000000000000000000000000000000000000000000000008452600484015260606024840152600d60648401527f4141333320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a4830190614029565b915082614be7565b9991929394959697989998925a900311614ca257509096959094939291906080614b24565b60a49060405190631101335b60e11b8252600482015260406024820152602760448201527f41413336206f766572207061796d6173746572566572696669636174696f6e4760648201527f61734c696d6974000000000000000000000000000000000000000000000000006084820152fd5b915098503d90816000823e614d298282613edc565b60408183810103126101925780519067ffffffffffffffff821161019257828101601f838301011215610192578181015191614d6483613eff565b93614d726040519586613edc565b838552820160208483850101011161019257602092614d98918480870191850101614006565b01519838614bd5565b60848b60405190631101335b60e11b8252600482015260406024820152601e60448201527f41413331207061796d6173746572206465706f73697420746f6f206c6f7700006064820152fd5b60849060405190631101335b60e11b8252600482015260406024820152601e60448201527f41413236206f76657220766572696669636174696f6e4761734c696d697400006064820152fd5b60848260405190631101335b60e11b8252600482015260406024820152601a60448201527f4141323520696e76616c6964206163636f756e74206e6f6e63650000000000006064820152fd5b600052600060205260406000208054808c11614ea6578b9003905538614aba565b60848460405190631101335b60e11b8252600482015260406024820152601760448201527f41413231206469646e2774207061792070726566756e640000000000000000006064820152fd5b9091506020813d602011614f1e575b81614f0e60209383613edc565b8101031261019257519038614a01565b3d9150614f01565b508060005260006020526040600020548a8111600014614f5157506149f5602060005b9150506149b0565b60206149f5918c03614f49565b833b61514457600060206001600160a01b036006541660408b510151604051809481937f570e1a3600000000000000000000000000000000000000000000000000000000835285600484015282614fb9602482018a8c614383565b0393f190811561112757600091615125575b506001600160a01b03811680156150d957850361508d573b1561504157601411610192576001600160a01b039183887fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d604060e0958787602086015195510151168251913560601c82526020820152a391614997565b60848d60405190631101335b60e11b8252600482015260406024820152602060448201527f4141313520696e6974436f6465206d757374206372656174652073656e6465726064820152fd5b60848e60405190631101335b60e11b8252600482015260406024820152602060448201527f4141313420696e6974436f6465206d7573742072657475726e2073656e6465726064820152fd5b60848f60405190631101335b60e11b8252600482015260406024820152601b60448201527f4141313320696e6974436f6465206661696c6564206f72204f4f4700000000006064820152fd5b61513e915060203d602011611120576111128183613edc565b38614fcb565b60848d60405190631101335b60e11b8252600482015260406024820152601f60448201527f414131302073656e64657220616c726561647920636f6e7374727563746564006064820152fd5b5050600060e087015260006080870152600060a0870152614901565b9092915a6060820151916040928351967fffffffff00000000000000000000000000000000000000000000000000000000886151eb60608401846143fa565b600060038211615660575b7f8dd7712f00000000000000000000000000000000000000000000000000000000941684036155305750505061537a6000926152a892602087015161524e8a5193849360208501528b60248501526064840190614543565b9060448301520390615268601f1992838101835282613edc565b6129ce89519485927e42dc530000000000000000000000000000000000000000000000000000000060208501526102006024850152610224840190614029565b615349604484018a60806101a09180516001600160a01b03808251168652602082015160208701526040820151604087015260608201516060870152838201518487015260a082015160a087015260c082015160c087015260e08201511660e0860152610100808201519086015261012080910151908501526020810151610140850152604081015161016085015260608101516101808501520151910152565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc8382030161020484015287614029565b6020918183809351910182305af16000519886521561539c575b505050505050565b909192939495965060003d8214615526575b7fdeaddead00000000000000000000000000000000000000000000000000000000810361541f5760848787805191631101335b60e11b835260048301526024820152600f60448201527f41413935206f7574206f662067617300000000000000000000000000000000006064820152fd5b7fdeadaa5100000000000000000000000000000000000000000000000000000000919293959496501460001461548a57505061546e61546361547d93945a906140e9565b6080850151906140af565b9083015183613a6b8295615825565b905b388080808080615394565b615518946155129293827ff62676f440ff169a3a9afdbf812e89e7f95975ee8e5c31214ffdef631c5f47926155079488015191885193612c16826001600160a01b03875116960151913d9061080080831161551e575b508051918581840101825280835260008684013e8080519586958652850152830190614029565b6080840151906140af565b91614607565b9061547f565b9150386154e0565b8181803e516153ae565b615658945082935090615578917e42dc5300000000000000000000000000000000000000000000000000000000602061564a9501526102006024860152610224850191614383565b615619604484018760806101a09180516001600160a01b03808251168652602082015160208701526040820151604087015260608201516060870152838201518487015260a082015160a087015260c082015160c087015260e08201511660e0860152610100808201519086015261012080910151908501526020810151610140850152604081015161016085015260608101516101808501520151910152565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc8382030161020484015284614029565b03601f198101895288613edc565b60008761537a565b5081356151f6565b6001600160a01b031680156156d457600080809381935af16156886140f6565b501561569057565b606460405162461bcd60e51b815260206004820152601f60248201527f41413931206661696c65642073656e6420746f2062656e6566696369617279006044820152fd5b606460405162461bcd60e51b815260206004820152601860248201527f4141393020696e76616c69642062656e656669636961727900000000000000006044820152fd5b9060405161572581613e90565b6000815263ffffffff6020820191600083526001600160a01b038195166000526000602052600160406000200154906dffffffffffffffffffffffffffff8260081c16905260781c169052565b61012061010082015191015180821461579857480180821015615793575090565b905090565b5090565b6001600160a01b031660005260006020526157bd60406000209182546140af565b80915590565b9190917f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f608060208301519251946001600160a01b03946020868851169660e089015116970151916040519283526000602084015260408301526060820152a4565b60208101519051907f67b4fa9642f42120bf031f3051d1824b0fe25627945b27b8a6a65d5761d5482e6020806001600160a01b03855116940151604051908152a3565b929192159081615934575b506158f95760148110156158a8575b50506040516020810181811067ffffffffffffffff821117613e28576040526000815290565b601411610192573560601c3b156158c0573880615882565b6040516158cc81613e90565b601b81527f41413330207061796d6173746572206e6f74206465706c6f7965640000000000602082015290565b505060405161590781613e90565b601981527f41413230206163636f756e74206e6f74206465706c6f79656400000000000000602082015290565b90503b1538615873565b61595660409295949395606083526060830190614543565b9460208201520152565b80156159e05760006040805161597581613eac565b82815282602082015201526001600160a01b03811690604065ffffffffffff91828160a01c169081156159d8575b60d01c928251916159b383613eac565b85835284602084015216918291015242119081156159d057509091565b905042109091565b8391506159a3565b5060009060009056fea2646970667358221220ff50e144b2114e87648eb607446d6c8a47731100cd3d929a5196d752d300756e64736f6c6343000817003360808060405234610016576101c3908161001c8239f35b600080fdfe6080600436101561000f57600080fd5b6000803560e01c63570e1a361461002557600080fd5b3461018a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261018a576004359167ffffffffffffffff9081841161018657366023850112156101865783600401358281116101825736602482870101116101825780601411610182577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec810192808411610155577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f81600b8501160116830190838210908211176101555792846024819482600c60209a968b9960405286845289840196603889018837830101525193013560601c5af1908051911561014d575b5073ffffffffffffffffffffffffffffffffffffffff60405191168152f35b90503861012e565b6024857f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b8380fd5b8280fd5b80fdfea2646970667358221220834006958097793c64aad712548afd0d1ffbdec5111e4c78e81e3ea0219ebdd564736f6c63430008170033
Deployed Bytecode
0x60806040526004361015610024575b361561001957600080fd5b610022336143a4565b005b60003560e01c806242dc531461385057806301ffc9a71461371c5780630396cb601461346a5780630bd28e3b1461340c5780631b2e01b8146133a3578063205c28781461327a57806322cdde4c1461325a57806335567e1a146131cd5780635287ce12146130ea5780635895273b146124c757806370a082311461248d578063765e827f14612240578063850aaf62146121a35780639b249f69146120b7578063b760faf91461209b578063bb9fe6bf14611f1b578063c23a5cea14611d17578063c3bce00914611223578063c5f996e6146106f7578063dbed18e0146101975763fc7e286d0361000e5734610192576020600319360112610192576001600160a01b03610130613f68565b16600052600060205260a0604060002065ffffffffffff6001825492015460405192835260ff8116151560208401526dffffffffffffffffffffffffffff8160081c16604084015263ffffffff8160781c16606084015260981c166080820152f35b600080fd5b34610192576101a53661404e565b906101ae614700565b60009160005b8281106104e757506101c68493614292565b6000805b8481106102e55750507fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f972600080a16000809360005b81811061023d57610236868660007f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d8180a2615668565b6001600255005b61028b61024b82848a61444b565b6001600160a01b0361025f602083016144df565b167f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d600080a28061448b565b906000915b8083106102a2575050506001016101ff565b909194976102dc6102d66001926102d08c8b6102c9826102c38e8b8d614324565b926142e1565b51916151ac565b906140af565b996140bc565b95019190610290565b60206102f282878961444b565b6103086102ff828061448b565b939092016144df565b916000926001600160a01b038091165b82851061032c5750505050506001016101ca565b909192939561035b83610354610342848c6142e1565b5161034e8b898b614324565b8561483c565b9290615960565b9116840361049b5761044f576103718491615960565b911661040357610391576103866001916140bc565b960193929190610318565b60a48760405190631101335b60e11b8252600482015260406024820152602160448201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560648201527f65000000000000000000000000000000000000000000000000000000000000006084820152fd5b60848860405190631101335b60e11b8252600482015260406024820152601460448201527f41413334207369676e6174757265206572726f720000000000000000000000006064820152fd5b60848860405190631101335b60e11b8252600482015260406024820152601760448201527f414132322065787069726564206f72206e6f74206475650000000000000000006064820152fd5b60848960405190631101335b60e11b8252600482015260406024820152601460448201527f41413234207369676e6174757265206572726f720000000000000000000000006064820152fd5b6104f281848761444b565b936104fd858061448b565b91909560206001600160a01b036105158284016144df565b1697600192838a146106b35789610545575b50505050600192939495509061053c916140af565b939291016101b4565b8060406105539201906143fa565b918a3b1561019257929391906040519485937f2dd8113300000000000000000000000000000000000000000000000000000000855288604486016040600488015252606490818601918a60051b8701019680936000915b8c8310610633575050505050508383926105d1926003198560009803016024860152614383565b03818a5afa9081610624575b5061061357602486604051907f86a9f7500000000000000000000000000000000000000000000000000000000082526004820152fd5b939450849361053c60018980610527565b61062d90613ec8565b886105dd565b91939596977fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9c908a9294969a0301865288357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee18336030181121561019257836106a0879385839401614543565b9a019601930190918997969594926105aa565b6064836040519062461bcd60e51b82526004820152601760248201527f4141393620696e76616c69642061676772656761746f720000000000000000006044820152fd5b34610192576003196060813601126101925767ffffffffffffffff6004351161019257610120906004353603011261019257610731613f52565b60443567ffffffffffffffff811161019257610751903690600401613f7e565b909160606040805161076281613eac565b60008152600060208201520152610777614209565b610785600435600401614739565b5a8151906001600160a01b0361079f6004356004016144df565b168252600480356024810135602085015260848101356fffffffffffffffffffffffffffffffff8181166060870152608091821c604087015260a483013560c087015260c4830135908116610100870152901c6101208501526108079160e4820191016143fa565b801561120757603481106111c3578060141161019257806024116101925760341161019257602481013560801c60a0840152601481013560801c60808401523560601c60e08301525b61085e600435600401614126565b60208401526040820151916effffffffffffffffffffffffffffff8360c08301511760608301511760808301511760a08301511761010083015117610120830151171161117f57604081015160608201510160808201510160a08201510160c082015101610100820151029284516001600160a01b03815116906108ec6044600435016004356004016143fa565b80610f31575b505060e001516001600160a01b031660008115610ef9575b602061094e91818a015160405193849283927f19822f7c0000000000000000000000000000000000000000000000000000000084526004356004016004850161593e565b038160008789f19081610ece575b50610a09576109fd3d610800808211610a01575b50604051906020818301016040528082526000602083013e6040519182917f65c8fd4d0000000000000000000000000000000000000000000000000000000083526000600484015260606024840152600d60648401527f4141323320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a4830190614029565b0390fd5b905082610970565b15610e61575b506001600160a01b03825116602083015190600052600160205260406000208160401c60005260205267ffffffffffffffff604060002091825492610a53846140bc565b90551603610e15575a830311610dc9576001600160a01b0360e0606092015116610b3f575b6080926040850152606084015260a46004350135905a9003019101526000926060916000936001600160a01b038216610aff575b505050610afb9060405192610ac084613eac565b835260208301931515845260408301908152604051938493602085525160208501525115156040840152516060808401526080830190614029565b0390f35b9091945060008094508093505a95826040519384928337810182815203925af1610afb610b36610b2d6140f6565b92935a906140e9565b91908480610aac565b505a9183516001600160a01b0360e08201511690816000526000602052604060002090815491848310610d7d576080600092869283610bbf960390550151936020890151836040518096819582947f52b7512c0000000000000000000000000000000000000000000000000000000084526004356004016004850161593e565b039287f160009181610cf6575b50610c75576109fd3d610800808211610c6d575b50604051906020818301016040528082526000602083013e6040519182917f65c8fd4d0000000000000000000000000000000000000000000000000000000083526000600484015260606024840152600d60648401527f4141333320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a4830190614029565b905082610be0565b935a900311610c845791610a78565b60a4604051631101335b60e11b81526000600482015260406024820152602760448201527f41413336206f766572207061796d6173746572566572696669636174696f6e4760648201527f61734c696d6974000000000000000000000000000000000000000000000000006084820152fd5b9091503d90816000823e610d0a8282613edc565b60408183810103126101925780519067ffffffffffffffff821161019257828101601f838301011215610192578181015190610d4582613eff565b93610d536040519586613edc565b8285528101602083858401010111610192576020610d7693818601920101614006565b908a610bcc565b6084604051631101335b60e11b81526000600482015260406024820152601e60448201527f41413331207061796d6173746572206465706f73697420746f6f206c6f7700006064820152fd5b6084604051631101335b60e11b81526000600482015260406024820152601e60448201527f41413236206f76657220766572696669636174696f6e4761734c696d697400006064820152fd5b6084604051631101335b60e11b81526000600482015260406024820152601a60448201527f4141323520696e76616c6964206163636f756e74206e6f6e63650000000000006064820152fd5b600052600060205260406000208054808611610e8257859003905588610a0f565b6084604051631101335b60e11b81526000600482015260406024820152601760448201527f41413231206469646e2774207061792070726566756e640000000000000000006064820152fd5b602090813d8311610ef2575b610ee48183613edc565b81010312610192578b61095c565b503d610eda565b50816000526000602052604060002054868111600014610f24575061094e602060005b91505061090a565b602061094e918803610f1c565b833b61113357600060206001600160a01b036006541660408c510151604051809481937f570e1a3600000000000000000000000000000000000000000000000000000000835285600484015282610f8c602482018a8c614383565b0393f1908115611127576000916110f8575b506001600160a01b03811680156110ac578503611060573b1561101457601411610192576001600160a01b039183897fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d604060e0958787602086015195510151168251913560601c82526020820152a3916108f2565b6084604051631101335b60e11b81526000600482015260406024820152602060448201527f4141313520696e6974436f6465206d757374206372656174652073656e6465726064820152fd5b6084604051631101335b60e11b81526000600482015260406024820152602060448201527f4141313420696e6974436f6465206d7573742072657475726e2073656e6465726064820152fd5b6084604051631101335b60e11b81526000600482015260406024820152601b60448201527f4141313320696e6974436f6465206661696c6564206f72204f4f4700000000006064820152fd5b61111a915060203d602011611120575b6111128183613edc565b810190614364565b8d610f9e565b503d611108565b6040513d6000823e3d90fd5b6084604051631101335b60e11b81526000600482015260406024820152601f60448201527f414131302073656e64657220616c726561647920636f6e7374727563746564006064820152fd5b606460405162461bcd60e51b815260206004820152601860248201527f41413934206761732076616c756573206f766572666c6f7700000000000000006044820152fd5b606460405162461bcd60e51b815260206004820152601d60248201527f4141393320696e76616c6964207061796d6173746572416e64446174610000006044820152fd5b5050600060e083015260006080830152600060a0830152610850565b346101925761123136613fd3565b60405161123d81613e0c565b60405161124981613e0c565b6000815260006020820152600060408201526000606082015260606080820152815260405161127781613e90565b6000815260006020820152602082015260405161129381613e90565b600081526000602082015260408201526040516112af81613e90565b600081526000602082015260608201526080604051916112ce83613e90565b600083526040516112de81613e90565b6000815260006020820152602084015201526112f8614209565b9061130281614739565b6000905a928051936001600160a01b0361131b846144df565b168552602083013560208601526fffffffffffffffffffffffffffffffff6080840135166060860152608083013560801c604086015260a083013560c08601526fffffffffffffffffffffffffffffffff60c08401351661010086015260c083013560801c61012086015261139360e08401846143fa565b8015611cfb57603481106111c3578060141161019257806024116101925760341161019257602481013560801c60a0870152601481013560801c60808701523560601c60e08601525b6113e583614126565b60208301526040850151946effffffffffffffffffffffffffffff8660c08301511760608301511760808301511760a08301511761010083015117610120830151171161117f57604081015160608201510160808201510160a08201510160c082015101610100820151028351966001600160a01b038851169761146c60408801886143fa565b80611bf9575b505060e001516001600160a01b03169760008915611bc1575b60206114ca918189015160405193849283927f19822f7c0000000000000000000000000000000000000000000000000000000084528d6004850161593e565b038160008688f160009181611b8d575b5061157a576109fd3d610800808211610a015750604051906020818301016040528082526000602083013e6040519182917f65c8fd4d0000000000000000000000000000000000000000000000000000000083526000600484015260606024840152600d60648401527f4141323320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a4830190614029565b9815611b6c575b506001600160a01b03835116602084015190600052600160205260406000208160401c60005260205267ffffffffffffffff6040600020918254926115c5846140bc565b90551603610e15575a840311610dc9576001600160a01b0360e060609301511661199f575b6040840152606083015260a0830135905a90030160808201526001600160a01b0361161485615960565b911661195357611907576001600160a01b0361162f84615960565b91166118bb57611849576116506001600160a01b0360e08351015116615718565b916116886116686001600160a01b0384515116615718565b916000602060405161167981613e90565b828152015260408101906143fa565b6014811061183d57601411610192576116a4903560601c615718565b916001600160a01b038616946080820151966060604084015193015192604051986116ce8a613e0c565b895260208901526040880152606087015260808601526040516116f081613e90565b6001600160a01b0360035416815260405161170a81613e90565b6004548152600554602082015260208201529380151580611832575b61180b575b506040519461173986613e0c565b8552602085015260408401526060830152608082015260405180916020825260208060806117a78185516101408589015280516101608901528481015161018089015260408101516101a089015260608101516101c0890152015160a06101e0880152610200870190614029565b9382808201518051604089015201516060870152826040820151805184890152015160a0870152826060820151805160c0890152015160e087015201516001600160a01b038151166101008601520151805161012085015201516101408301520390f35b90935061181781615718565b6040519161182483613e90565b82526020820152928561172b565b506001811415611726565b50506116a46000615718565b60a4604051631101335b60e11b81526000600482015260406024820152602160448201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560648201527f65000000000000000000000000000000000000000000000000000000000000006084820152fd5b6084604051631101335b60e11b81526000600482015260406024820152601460448201527f41413334207369676e6174757265206572726f720000000000000000000000006064820152fd5b6084604051631101335b60e11b81526000600482015260406024820152601760448201527f414132322065787069726564206f72206e6f74206475650000000000000000006064820152fd5b6084604051631101335b60e11b81526000600482015260406024820152601460448201527f41413234207369676e6174757265206572726f720000000000000000000000006064820152fd5b9450505a938251946001600160a01b0360e087015116806000526000602052604060002096875497848910610d7d576080600092869283611a1d9c0390550151926020880151838a6040519c8d95869485937f52b7512c0000000000000000000000000000000000000000000000000000000085526004850161593e565b039286f19687600091600099611adf575b50611ace576109fd3d610800808211610c6d5750604051906020818301016040528082526000602083013e6040519182917f65c8fd4d0000000000000000000000000000000000000000000000000000000083526000600484015260606024840152600d60648401527f4141333320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a4830190614029565b96915a900311610c845794906115ea565b915097503d90816000823e611af48282613edc565b60408183810103126101925780519067ffffffffffffffff821161019257828101601f838301011215610192578181015191611b2f83613eff565b93611b3d6040519586613edc565b838552820160208483850101011161019257602092611b63918480870191850101614006565b0151978a611a2e565b600052600060205260406000208054808411610e8257839003905588611581565b9091506020813d602011611bb9575b81611ba960209383613edc565b810103126101925751908b6114da565b3d9150611b9c565b50806000526000602052604060002054838111600014611bec57506114ca602060005b91505061148b565b60206114ca918503611be4565b8a3b61113357600060206001600160a01b036006541660408b510151604051809481937f570e1a3600000000000000000000000000000000000000000000000000000000835285600484015282611c54602482018a8c614383565b0393f190811561112757600091611cdc575b506001600160a01b03811680156110ac578c03611060573b1561101457601411610192576001600160a01b03918a887fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d604060e0958787602086015195510151168251913560601c82526020820152a391611472565b611cf5915060203d602011611120576111128183613edc565b8c611c66565b5050600060e086015260006080860152600060a08601526113dc565b346101925760208060031936011261019257611d31613f68565b33600052600082526001604060002001908154916dffffffffffffffffffffffffffff8360081c16928315611ed75765ffffffffffff8160981c168015611e93574210611e4f576000936001600160a01b03859485947fffffffffffffff000000000000000000000000000000000000000000000000ff86951690556040517fb7c918e0e249f999e965cafeb6c664271b3f4317d296461500e71da39f0cbda3339180611df5878683602090939291936001600160a01b0360408201951681520152565b0390a2165af1611e036140f6565b5015611e0b57005b6064906040519062461bcd60e51b82526004820152601860248201527f6661696c656420746f207769746864726177207374616b6500000000000000006044820152fd5b6064856040519062461bcd60e51b82526004820152601b60248201527f5374616b65207769746864726177616c206973206e6f742064756500000000006044820152fd5b6064866040519062461bcd60e51b82526004820152601d60248201527f6d7573742063616c6c20756e6c6f636b5374616b6528292066697273740000006044820152fd5b6064856040519062461bcd60e51b82526004820152601460248201527f4e6f207374616b6520746f2077697468647261770000000000000000000000006044820152fd5b34610192576000600319360112610192573360005260006020526001604060002001805463ffffffff8160781c169081156120575760ff16156120135765ffffffffffff908142160191818311611fe45780547fffffffffffffff000000000000ffffffffffffffffffffffffffffffffffff001678ffffffffffff00000000000000000000000000000000000000609885901b161790556040519116815233907ffa9b3c14cc825c412c9ed81b3ba365a5b459439403f18829e572ed53a4180f0a90602090a2005b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b606460405162461bcd60e51b815260206004820152601160248201527f616c726561647920756e7374616b696e670000000000000000000000000000006044820152fd5b606460405162461bcd60e51b815260206004820152600a60248201527f6e6f74207374616b6564000000000000000000000000000000000000000000006044820152fd5b6020600319360112610192576100226120b2613f68565b6143a4565b346101925760206003193601126101925760043567ffffffffffffffff81116101925760206120ed61213c923690600401613f7e565b91906001600160a01b039283600654169060006040518097819582947f570e1a360000000000000000000000000000000000000000000000000000000084528860048501526024840191614383565b03925af190811561112757602492600092612182575b50604051917f6ca7b806000000000000000000000000000000000000000000000000000000008352166004820152fd5b61219c91925060203d602011611120576111128183613edc565b9083612152565b34610192576040600319360112610192576121bc613f68565b60243567ffffffffffffffff8111610192576000916121e083923690600401613f7e565b90816040519283928337810184815203915af46121fb6140f6565b906109fd6040519283927f9941055400000000000000000000000000000000000000000000000000000000845215156004840152604060248401526044830190614029565b346101925761224e3661404e565b612259929192614700565b61226283614292565b60005b8481106122da57506000927fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f972600080a16000915b8583106122aa576102368585615668565b9091936001906122d06122be878987614324565b6122c888866142e1565b5190886151ac565b0194019190612299565b6123056122fe6122ec838597956142e1565b516122f8848987614324565b8461483c565b9190615960565b6001600160a01b0392918316612441576123f55761232290615960565b91166123a95761233757600101929092612265565b60a49060405190631101335b60e11b8252600482015260406024820152602160448201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560648201527f65000000000000000000000000000000000000000000000000000000000000006084820152fd5b60848260405190631101335b60e11b8252600482015260406024820152601460448201527f41413334207369676e6174757265206572726f720000000000000000000000006064820152fd5b60848360405190631101335b60e11b8252600482015260406024820152601760448201527f414132322065787069726564206f72206e6f74206475650000000000000000006064820152fd5b60848460405190631101335b60e11b8252600482015260406024820152601460448201527f41413234207369676e6174757265206572726f720000000000000000000000006064820152fd5b34610192576020600319360112610192576001600160a01b036124ae613f68565b1660005260006020526020604060002054604051908152f35b34610192576124d536613fd3565b606060a06040516124e581613e74565b60008152600060208201526000604082015260008382015260006080820152015261250e614700565b612516614209565b61251f82614739565b6000905a9080516001600160a01b03612537866144df565b1681526020850135602082015260808501356fffffffffffffffffffffffffffffffff90818116606084015260801c604083015260a086013560c083015260c086013590811661010083015260801c61012082015261259960e08601866143fa565b80156130ce57603481106111c3578060141161019257806024116101925760341161019257602481013560801c60a0830152601481013560801c60808301523560601c60e08201525b6125eb85614126565b60208301526040810151926effffffffffffffffffffffffffffff8460c08401511760608401511760808401511760a08401511761010084015117610120840151171161117f57604082015160608301510160808301510160a08301510160c083015101610100830151028351946001600160a01b038651169561267260408a018a6143fa565b80612fcc575b505060e001516001600160a01b03169560008715612fa3575b6020808801518b6126cf60405194859384937f19822f7c0000000000000000000000000000000000000000000000000000000085526004850161593e565b038160008688f160009181612f6f575b5061277f576109fd3d610800808211610a015750604051906020818301016040528082526000602083013e6040519182917f65c8fd4d0000000000000000000000000000000000000000000000000000000083526000600484015260606024840152600d60648401527f4141323320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a4830190614029565b9615612f4e575b506001600160a01b03845116602085015190600052600160205260406000208160401c60005260205267ffffffffffffffff6040600020918254926127ca846140bc565b90551603610e15575a830311610dc9576001600160a01b0360e0606094015116612d8a575b604084015281606084015260a0860135905a90030160808301525a604051957fffffffff000000000000000000000000000000000000000000000000000000008761283d60608401846143fa565b600060038211612d82575b7f8dd7712f0000000000000000000000000000000000000000000000000000000094168403612c50575050506128fc6129da602093600093858901516128a260405193849389850152604060248501526064840190614543565b90604483015203906128bc601f1992838101835282613edc565b6129ce6040519485927e42dc5300000000000000000000000000000000000000000000000000000000898501526102006024850152610224840190614029565b61299d604484018c60806101a09180516001600160a01b03808251168652602082015160208701526040820151604087015260608201516060870152838201518487015260a082015160a087015260c082015160c087015260e08201511660e0860152610100808201519086015261012080910151908501526020810151610140850152604081015161016085015260608101516101808501520151910152565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc8382030161020484015289614029565b03908101835282613edc565b828151910182305af16000519660405215612aa6575b50506080015160405192610afb9291612a0885613e74565b845260208401948552604084019182526060840190815260808401906000825260405192612a3584613e90565b600284527f3078000000000000000000000000000000000000000000000000000000000000602085015260a0860193845260016002556040519687966020885251602088015251604087015251606086015251608085015251151560a08401525160c08084015260e0830190614029565b90929194506000903d602014612c3f575b7fdeaddead000000000000000000000000000000000000000000000000000000008203612b2a576084604051631101335b60e11b81526000600482015260406024820152600f60448201527f41413935206f7574206f662067617300000000000000000000000000000000006064820152fd5b610afb936080927fdeadaa510000000000000000000000000000000000000000000000000000000003612b925750612b66612b70915a906140e9565b82870151906140af565b612b89604087015191612b8288615825565b82886157c3565b945b91926129f0565b612c2a612c20612c319360208a01518a51907ff62676f440ff169a3a9afdbf812e89e7f95975ee8e5c31214ffdef631c5f479260206001600160a01b038451169301513d90610800808311612c37575b50604051916020818401016040528083526000602084013e612c166040519283928352604060208401526040830190614029565b0390a35a906140e9565b84890151906140af565b9087614607565b94612b8b565b91508f612be2565b905060206000803e60005190612ab7565b612d78945082935090612c98917e42dc53000000000000000000000000000000000000000000000000000000006020612d6a9501526102006024860152610224850191614383565b612d39604484018860806101a09180516001600160a01b03808251168652602082015160208701526040820151604087015260608201516060870152838201518487015260a082015160a087015260c082015160c087015260e08201511660e0860152610100808201519086015261012080910151908501526020810151610140850152604081015161016085015260608101516101808501520151910152565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc8382030161020484015285614029565b03601f198101885287613edc565b60206000876129da565b508135612848565b915093505a938251946001600160a01b0360e087015116806000526000602052604060002096875497858910610d7d576080600092879283612e099c0390550151926020880151838c6040519c8d95869485937f52b7512c0000000000000000000000000000000000000000000000000000000085526004850161593e565b039286f19687600091600099612ecb575b50612eba576109fd3d610800808211610c6d5750604051906020818301016040528082526000602083013e6040519182917f65c8fd4d0000000000000000000000000000000000000000000000000000000083526000600484015260606024840152600d60648401527f4141333320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a4830190614029565b96915a900311610c845794916127ef565b915097503d806000833e612edf8183613edc565b81019060408183031261019257805167ffffffffffffffff81116101925781019082601f8301121561019257815191612f1783613eff565b93612f256040519586613edc565b8385526020848301011161019257602092612f4591848087019101614006565b0151978a612e1a565b600052600060205260406000208054808411610e8257839003905588612786565b9091506020813d602011612f9b575b81612f8b60209383613edc565b810103126101925751908b6126df565b3d9150612f7e565b50806000526000602052604060002054838111600014612fc557506000612691565b8303612691565b883b61113357600060206001600160a01b036006541660408b510151604051809481937f570e1a3600000000000000000000000000000000000000000000000000000000835285600484015282613027602482018a8c614383565b0393f1908115611127576000916130af575b506001600160a01b03811680156110ac578a03611060573b1561101457601411610192576001600160a01b039188887fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d604060e0958787602086015195510151168251913560601c82526020820152a391612678565b6130c8915060203d602011611120576111128183613edc565b8c613039565b5050600060e082015260006080820152600060a08201526125e2565b34610192576020600319360112610192576001600160a01b0361310b613f68565b6000608060405161311b81613e0c565b828152826020820152826040820152826060820152015216600052600060205260a06040600020608060405161315081613e0c565b6001835493848352015490602081019060ff8316151582526dffffffffffffffffffffffffffff60408201818560081c16815263ffffffff936060840193858760781c16855265ffffffffffff978891019660981c1686526040519788525115156020880152511660408601525116606084015251166080820152f35b346101925760406003193601126101925760206131e8613f68565b6001600160a01b036131f8613fac565b911660005260018252604060002077ffffffffffffffffffffffffffffffffffffffffffffffff821660005282526040600020547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000006040519260401b16178152f35b3461019257602061327261326d36613fd3565b614126565b604051908152f35b3461019257604060031936011261019257613293613f68565b6024359033600052600060205260406000209081549182841161335f57600080856001600160a01b03829583956132ca848a6140e9565b9055604080516001600160a01b03831681526020810185905233917fd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb91a2165af16133136140f6565b501561331b57005b606460405162461bcd60e51b815260206004820152601260248201527f6661696c656420746f20776974686472617700000000000000000000000000006044820152fd5b606460405162461bcd60e51b815260206004820152601960248201527f576974686472617720616d6f756e7420746f6f206c61726765000000000000006044820152fd5b34610192576040600319360112610192576133bc613f68565b6001600160a01b036133cc613fac565b9116600052600160205277ffffffffffffffffffffffffffffffffffffffffffffffff604060002091166000526020526020604060002054604051908152f35b346101925760206003193601126101925760043577ffffffffffffffffffffffffffffffffffffffffffffffff811680910361019257336000526001602052604060002090600052602052604060002061346681546140bc565b9055005b6020806003193601126101925760043563ffffffff9182821680920361019257336000526000815260406000209282156136d8576001840154908160781c168310613694576134ce6dffffffffffffffffffffffffffff9182349160081c166140af565b9384156136505781851161360c579065ffffffffffff6135db9254604051906134f682613e0c565b8152848101926001845260408201908816815260608201878152600160808401936000855233600052600089526040600020905181550194511515917fffffffffffffffffffffffffff0000000000000000000000000000000000000060ff72ffffffff0000000000000000000000000000006effffffffffffffffffffffffffff008954945160081b16945160781b1694169116171717835551167fffffffffffffff000000000000ffffffffffffffffffffffffffffffffffffff78ffffffffffff0000000000000000000000000000000000000083549260981b169116179055565b6040519283528201527fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c0160403392a2005b6064836040519062461bcd60e51b82526004820152600e60248201527f7374616b65206f766572666c6f770000000000000000000000000000000000006044820152fd5b6064836040519062461bcd60e51b82526004820152601260248201527f6e6f207374616b652073706563696669656400000000000000000000000000006044820152fd5b6064826040519062461bcd60e51b82526004820152601c60248201527f63616e6e6f7420646563726561736520756e7374616b652074696d65000000006044820152fd5b6064826040519062461bcd60e51b82526004820152601a60248201527f6d757374207370656369667920756e7374616b652064656c61790000000000006044820152fd5b34610192576020600319360112610192576004357fffffffff00000000000000000000000000000000000000000000000000000000811680910361019257807f60fc6b6e0000000000000000000000000000000000000000000000000000000060209214908115613826575b81156137fc575b81156137d2575b81156137a8575b506040519015158152f35b7f01ffc9a7000000000000000000000000000000000000000000000000000000009150148261379d565b7f3e84f0210000000000000000000000000000000000000000000000000000000081149150613796565b7fcf28ef97000000000000000000000000000000000000000000000000000000008114915061378f565b7f915074d80000000000000000000000000000000000000000000000000000000081149150613788565b34610192576102006003193601126101925767ffffffffffffffff600435818111610192573660238201121561019257613894903690602481600401359101613f1b565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc3601906101c0821261019257610140604051926138d284613e0c565b12610192576040516138e381613e57565b6138eb613f52565b815260443560208201526064356040820152608435606082015260a435608082015260c43560a082015260e43560c0820152610104356001600160a01b03811681036101925760e0820152610124356101008201526101443561012082015282526101643560208301526101843560408301526101a43560608301526101c43560808301526101e43590811161019257613989903690600401613f7e565b91905a303303613dc8578251606081015195603f5a0260061c61271060a084015189010111613d9e5760009681519182613cd4575b50505050906139d8915a9003608084015101933691613f1b565b915a6000938351926139e984615772565b916001600160a01b0360e086015116908115600014613b895750506001600160a01b03845116925b5a9003019260a06060820151910151016080850151840390818111613b75575b50508202604084015191818310600014613ac55750506003851015613a9857602094600203613a70576132729293508093613a6b81615825565b6157c3565b5050507fdeadaa51000000000000000000000000000000000000000000000000000000008152fd5b6024847f4e487b710000000000000000000000000000000000000000000000000000000081526021600452fd5b81613ad59296979593039061579c565b506003831015613b4857602094507f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f6080868301519251946001600160a01b0386511694886001600160a01b0360e0890151169701519160405192835215898301528760408301526060820152a4613272565b6024857f4e487b710000000000000000000000000000000000000000000000000000000081526021600452fd5b6064919003600a0204909201918680613a31565b819491948151613b9b575b5050613a11565b60038a1015613ca55760028a0315613b945760a087015191813b1561019257613c05928b600080946040518097819682957f7c627b210000000000000000000000000000000000000000000000000000000084526004840152608060248401526084830190614029565b8b8b0260448301528b60648301520393f19081613c91575b50613c8a576109fd873d610800808211613c82575b5060405191602082840101604052818352602083013e6040519182917fad7954bc000000000000000000000000000000000000000000000000000000008352602060048401526024830190614029565b905083613c32565b8880613b94565b613c9c919850613ec8565b60009689613c1d565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b916000929183809360206001600160a01b03885116910192f115613cfb575b8080806139be565b6139d8929195503d610800808211613d96575b50604051906020818301016040528082526000602083013e8051613d39575b50506001949091613cf3565b7f1c4fada7374c0a9ee8841fc38afe82932dc0f8e69012e927f061a8bae611a20160208601519160206001600160a01b03855116940151613d8c6040519283928352604060208401526040830190614029565b0390a38580613d2d565b905087613d0e565b7fdeaddead0000000000000000000000000000000000000000000000000000000060005260206000fd5b606460405162461bcd60e51b815260206004820152601760248201527f4141393220696e7465726e616c2063616c6c206f6e6c790000000000000000006044820152fd5b60a0810190811067ffffffffffffffff821117613e2857604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b610140810190811067ffffffffffffffff821117613e2857604052565b60c0810190811067ffffffffffffffff821117613e2857604052565b6040810190811067ffffffffffffffff821117613e2857604052565b6060810190811067ffffffffffffffff821117613e2857604052565b67ffffffffffffffff8111613e2857604052565b90601f601f19910116810190811067ffffffffffffffff821117613e2857604052565b67ffffffffffffffff8111613e2857601f01601f191660200190565b929192613f2782613eff565b91613f356040519384613edc565b829481845281830111610192578281602093846000960137010152565b602435906001600160a01b038216820361019257565b600435906001600160a01b038216820361019257565b9181601f840112156101925782359167ffffffffffffffff8311610192576020838186019501011161019257565b6024359077ffffffffffffffffffffffffffffffffffffffffffffffff8216820361019257565b60031990602082820112610192576004359167ffffffffffffffff83116101925782610120920301126101925760040190565b60005b8381106140195750506000910152565b8181015183820152602001614009565b90601f19601f60209361404781518092818752878088019101614006565b0116010190565b9060406003198301126101925760043567ffffffffffffffff9283821161019257806023830112156101925781600401359384116101925760248460051b830101116101925760240191906024356001600160a01b03811681036101925790565b91908201809211611fe457565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114611fe45760010190565b91908203918211611fe457565b3d15614121573d9061410782613eff565b916141156040519384613edc565b82523d6000602084013e565b606090565b6040614134818301836143fa565b908183519182372061414960608401846143fa565b90818451918237209260c061416160e08301836143fa565b90818651918237209184519560208701946001600160a01b03833516865260208301358789015260608801526080870152608081013560a087015260a081013582870152013560e08501526101009081850152835261012083019167ffffffffffffffff9184841083851117613e2857838252845190206101408501908152306101608601524661018086015260608452936101a00191821183831017613e28575251902090565b6040519061421682613e0c565b60405160808361422583613e57565b60009283815283602082015283604082015283606082015283838201528360a08201528360c08201528360e0820152836101008201528361012082015281528260208201528260408201528260608201520152565b67ffffffffffffffff8111613e285760051b60200190565b9061429c8261427a565b6142a96040519182613edc565b828152601f196142b9829461427a565b019060005b8281106142ca57505050565b6020906142d5614209565b828285010152016142be565b80518210156142f55760209160051b010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b91908110156142f55760051b810135907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee181360301821215610192570190565b9081602091031261019257516001600160a01b03811681036101925790565b601f8260209493601f19938186528686013760008582860101520116010190565b6001805b600581106143f35750507f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c460206001600160a01b036143e7348561579c565b936040519485521692a2565b81016143a8565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610192570180359067ffffffffffffffff82116101925760200191813603831361019257565b91908110156142f55760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa181360301821215610192570190565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610192570180359067ffffffffffffffff821161019257602001918160051b3603831361019257565b356001600160a01b03811681036101925790565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18236030181121561019257016020813591019167ffffffffffffffff821161019257813603831361019257565b6101209181356001600160a01b038116809103610192576145ac614591614604956145e59385526020860135602086015261458160408701876144f3565b9091806040880152860191614383565b61459e60608601866144f3565b908583036060870152614383565b6080840135608084015260a084013560a084015260c084013560c08401526145d760e08501856144f3565b9084830360e0860152614383565b916145f661010091828101906144f3565b929091818503910152614383565b90565b9291905a9060009085519361461b85615772565b916001600160a01b03908160e08801511680156000146146ec575050855116935b5a9003019360a060608201519101510160808701518503908181116146d8575b505083026040860151928184106000146146b75750508061468a575090816146889294613a6b81615825565b565b807f4e487b7100000000000000000000000000000000000000000000000000000000602492526021600452fd5b6146c7908284939895039061579c565b5061468a57509083614688926157c3565b6064919003600a020490930192388061465c565b9095915094511561463c576000935061463c565b600280541461470f5760028055565b60046040517f3ee5aeb5000000000000000000000000000000000000000000000000000000008152fd5b614807906001600160a01b0360405160208101907fd69400000000000000000000000000000000000000000000000000000000000082523060601b60228201527f01000000000000000000000000000000000000000000000000000000000000006036820152601781526147ac81613e90565b519020167fffffffffffffffffffffffff000000000000000000000000000000000000000060065416176006556147e660408201826143fa565b90506147ff6147f4836144df565b9260e08101906143fa565b929091615868565b80516148105750565b6109fd90604051918291631101335b60e11b835260006004840152604060248401526044830190614029565b926000905a938051946001600160a01b03614856866144df565b1686526020850135602087015260808501356fffffffffffffffffffffffffffffffff90818116606089015260801c604088015260a086013560c088015260c086013590811661010088015260801c6101208701526148b860e08601866143fa565b801561519057603481106111c3578060141161019257806024116101925760341161019257602481013560801c60a0880152601481013560801c60808801523560601c60e08701525b61490a85614126565b60208301526040860151946effffffffffffffffffffffffffffff8660c08901511760608901511760808901511760a08901511761010089015117610120890151171161117f57604087015160608801510160808801510160a08801510160c088015101610100880151029683516001600160a01b038151169061499160408501856143fa565b80614f5e575b505060e001516001600160a01b03169060008215614f26575b60206149f5918b828a01516000868a604051978896879586937f19822f7c0000000000000000000000000000000000000000000000000000000085526004850161593e565b0393f160009181614ef2575b50614aa9573d8c610800808311614aa1575b50604051916020818401016040528083526000602084013e6109fd6040519283927f65c8fd4d000000000000000000000000000000000000000000000000000000008452600484015260606024840152600d60648401527f4141323320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a4830190614029565b915082614a13565b9a92939495969798999a9115614e85575b50976001600160a01b03835116602084015190600052600160205260406000208160401c60005260205267ffffffffffffffff604060002091825492614aff846140bc565b90551603614e39575a850311614ded576001600160a01b0360e0606093015116614b46575b509060a09184959697986040608096015260608601520135905a900301910152565b969550505a968351976001600160a01b0360e08a01511680600052600060205260406000208054848110614da1576080614bc49a9b9c600093878094039055015192602089015183604051809d819582947f52b7512c0000000000000000000000000000000000000000000000000000000084528c6004850161593e565b039286f1978860009160009a614d14575b50614c7d573d8b610800808311614c75575b50604051916020818401016040528083526000602084013e6109fd6040519283927f65c8fd4d000000000000000000000000000000000000000000000000000000008452600484015260606024840152600d60648401527f4141333320726576657274656400000000000000000000000000000000000000608484015260a0604484015260a4830190614029565b915082614be7565b9991929394959697989998925a900311614ca257509096959094939291906080614b24565b60a49060405190631101335b60e11b8252600482015260406024820152602760448201527f41413336206f766572207061796d6173746572566572696669636174696f6e4760648201527f61734c696d6974000000000000000000000000000000000000000000000000006084820152fd5b915098503d90816000823e614d298282613edc565b60408183810103126101925780519067ffffffffffffffff821161019257828101601f838301011215610192578181015191614d6483613eff565b93614d726040519586613edc565b838552820160208483850101011161019257602092614d98918480870191850101614006565b01519838614bd5565b60848b60405190631101335b60e11b8252600482015260406024820152601e60448201527f41413331207061796d6173746572206465706f73697420746f6f206c6f7700006064820152fd5b60849060405190631101335b60e11b8252600482015260406024820152601e60448201527f41413236206f76657220766572696669636174696f6e4761734c696d697400006064820152fd5b60848260405190631101335b60e11b8252600482015260406024820152601a60448201527f4141323520696e76616c6964206163636f756e74206e6f6e63650000000000006064820152fd5b600052600060205260406000208054808c11614ea6578b9003905538614aba565b60848460405190631101335b60e11b8252600482015260406024820152601760448201527f41413231206469646e2774207061792070726566756e640000000000000000006064820152fd5b9091506020813d602011614f1e575b81614f0e60209383613edc565b8101031261019257519038614a01565b3d9150614f01565b508060005260006020526040600020548a8111600014614f5157506149f5602060005b9150506149b0565b60206149f5918c03614f49565b833b61514457600060206001600160a01b036006541660408b510151604051809481937f570e1a3600000000000000000000000000000000000000000000000000000000835285600484015282614fb9602482018a8c614383565b0393f190811561112757600091615125575b506001600160a01b03811680156150d957850361508d573b1561504157601411610192576001600160a01b039183887fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d604060e0958787602086015195510151168251913560601c82526020820152a391614997565b60848d60405190631101335b60e11b8252600482015260406024820152602060448201527f4141313520696e6974436f6465206d757374206372656174652073656e6465726064820152fd5b60848e60405190631101335b60e11b8252600482015260406024820152602060448201527f4141313420696e6974436f6465206d7573742072657475726e2073656e6465726064820152fd5b60848f60405190631101335b60e11b8252600482015260406024820152601b60448201527f4141313320696e6974436f6465206661696c6564206f72204f4f4700000000006064820152fd5b61513e915060203d602011611120576111128183613edc565b38614fcb565b60848d60405190631101335b60e11b8252600482015260406024820152601f60448201527f414131302073656e64657220616c726561647920636f6e7374727563746564006064820152fd5b5050600060e087015260006080870152600060a0870152614901565b9092915a6060820151916040928351967fffffffff00000000000000000000000000000000000000000000000000000000886151eb60608401846143fa565b600060038211615660575b7f8dd7712f00000000000000000000000000000000000000000000000000000000941684036155305750505061537a6000926152a892602087015161524e8a5193849360208501528b60248501526064840190614543565b9060448301520390615268601f1992838101835282613edc565b6129ce89519485927e42dc530000000000000000000000000000000000000000000000000000000060208501526102006024850152610224840190614029565b615349604484018a60806101a09180516001600160a01b03808251168652602082015160208701526040820151604087015260608201516060870152838201518487015260a082015160a087015260c082015160c087015260e08201511660e0860152610100808201519086015261012080910151908501526020810151610140850152604081015161016085015260608101516101808501520151910152565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc8382030161020484015287614029565b6020918183809351910182305af16000519886521561539c575b505050505050565b909192939495965060003d8214615526575b7fdeaddead00000000000000000000000000000000000000000000000000000000810361541f5760848787805191631101335b60e11b835260048301526024820152600f60448201527f41413935206f7574206f662067617300000000000000000000000000000000006064820152fd5b7fdeadaa5100000000000000000000000000000000000000000000000000000000919293959496501460001461548a57505061546e61546361547d93945a906140e9565b6080850151906140af565b9083015183613a6b8295615825565b905b388080808080615394565b615518946155129293827ff62676f440ff169a3a9afdbf812e89e7f95975ee8e5c31214ffdef631c5f47926155079488015191885193612c16826001600160a01b03875116960151913d9061080080831161551e575b508051918581840101825280835260008684013e8080519586958652850152830190614029565b6080840151906140af565b91614607565b9061547f565b9150386154e0565b8181803e516153ae565b615658945082935090615578917e42dc5300000000000000000000000000000000000000000000000000000000602061564a9501526102006024860152610224850191614383565b615619604484018760806101a09180516001600160a01b03808251168652602082015160208701526040820151604087015260608201516060870152838201518487015260a082015160a087015260c082015160c087015260e08201511660e0860152610100808201519086015261012080910151908501526020810151610140850152604081015161016085015260608101516101808501520151910152565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc8382030161020484015284614029565b03601f198101895288613edc565b60008761537a565b5081356151f6565b6001600160a01b031680156156d457600080809381935af16156886140f6565b501561569057565b606460405162461bcd60e51b815260206004820152601f60248201527f41413931206661696c65642073656e6420746f2062656e6566696369617279006044820152fd5b606460405162461bcd60e51b815260206004820152601860248201527f4141393020696e76616c69642062656e656669636961727900000000000000006044820152fd5b9060405161572581613e90565b6000815263ffffffff6020820191600083526001600160a01b038195166000526000602052600160406000200154906dffffffffffffffffffffffffffff8260081c16905260781c169052565b61012061010082015191015180821461579857480180821015615793575090565b905090565b5090565b6001600160a01b031660005260006020526157bd60406000209182546140af565b80915590565b9190917f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f608060208301519251946001600160a01b03946020868851169660e089015116970151916040519283526000602084015260408301526060820152a4565b60208101519051907f67b4fa9642f42120bf031f3051d1824b0fe25627945b27b8a6a65d5761d5482e6020806001600160a01b03855116940151604051908152a3565b929192159081615934575b506158f95760148110156158a8575b50506040516020810181811067ffffffffffffffff821117613e28576040526000815290565b601411610192573560601c3b156158c0573880615882565b6040516158cc81613e90565b601b81527f41413330207061796d6173746572206e6f74206465706c6f7965640000000000602082015290565b505060405161590781613e90565b601981527f41413230206163636f756e74206e6f74206465706c6f79656400000000000000602082015290565b90503b1538615873565b61595660409295949395606083526060830190614543565b9460208201520152565b80156159e05760006040805161597581613eac565b82815282602082015201526001600160a01b03811690604065ffffffffffff91828160a01c169081156159d8575b60d01c928251916159b383613eac565b85835284602084015216918291015242119081156159d057509091565b905042109091565b8391506159a3565b5060009060009056fea2646970667358221220ff50e144b2114e87648eb607446d6c8a47731100cd3d929a5196d752d300756e64736f6c63430008170033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ 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.