Source Code
Overview
ETH Balance
655.229130596223840051 ETH
Token Holdings
More Info
ContractCreator
Multi Chain
Multichain Addresses
8 addresses found via
Latest 25 from a total of 7,459 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
Value | ||||
---|---|---|---|---|---|---|---|---|---|
Deposit To | 10025623 | 27 days 4 hrs ago | IN | 0.005 ETH | 0.0000688 | ||||
Handle Ops | 9956856 | 39 days 8 hrs ago | IN | 0 ETH | 0 | ||||
Handle Ops | 9887647 | 51 days 10 hrs ago | IN | 0 ETH | 0 | ||||
Handle Ops | 9880880 | 52 days 13 hrs ago | IN | 0 ETH | 0.00007974 | ||||
Handle Ops | 9880879 | 52 days 13 hrs ago | IN | 0 ETH | 0.00012238 | ||||
Handle Ops | 9858679 | 56 days 10 hrs ago | IN | 0 ETH | 0 | ||||
Handle Ops | 9858589 | 56 days 10 hrs ago | IN | 0 ETH | 0.0000798 | ||||
Handle Ops | 9858588 | 56 days 10 hrs ago | IN | 0 ETH | 0.00013609 | ||||
Handle Ops | 9858562 | 56 days 10 hrs ago | IN | 0 ETH | 0.00013608 | ||||
Handle Ops | 9857863 | 56 days 13 hrs ago | IN | 0 ETH | 0.00013608 | ||||
Handle Ops | 9857713 | 56 days 14 hrs ago | IN | 0 ETH | 0.00013609 | ||||
Handle Ops | 9857678 | 56 days 14 hrs ago | IN | 0 ETH | 0.00007979 | ||||
Handle Ops | 9857677 | 56 days 14 hrs ago | IN | 0 ETH | 0.00013608 | ||||
Handle Ops | 9857667 | 56 days 14 hrs ago | IN | 0 ETH | 0.00005002 | ||||
Handle Ops | 9857666 | 56 days 14 hrs ago | IN | 0 ETH | 0.00059124 | ||||
Handle Ops | 9768156 | 72 days 8 hrs ago | IN | 0 ETH | 0 | ||||
Handle Ops | 9766904 | 72 days 13 hrs ago | IN | 0 ETH | 0 | ||||
Handle Ops | 9766881 | 72 days 14 hrs ago | IN | 0 ETH | 0 | ||||
Handle Ops | 9766826 | 72 days 14 hrs ago | IN | 0 ETH | 0 | ||||
Handle Ops | 9766678 | 72 days 14 hrs ago | IN | 0 ETH | 0 | ||||
Handle Ops | 9749337 | 75 days 14 hrs ago | IN | 0 ETH | 0 | ||||
Handle Ops | 9688446 | 86 days 4 hrs ago | IN | 0 ETH | 0 | ||||
Handle Ops | 9600166 | 101 days 11 hrs ago | IN | 0 ETH | 0.00003413 | ||||
Handle Ops | 9598613 | 101 days 18 hrs ago | IN | 0 ETH | 0.00003413 | ||||
Handle Ops | 9590663 | 103 days 3 hrs ago | IN | 0 ETH | 0 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Txn Hash | Block | From | To | Value | ||
---|---|---|---|---|---|---|
10041923 | 24 days 8 hrs ago | 0.1 ETH | ||||
9956856 | 39 days 8 hrs ago | 0 ETH | ||||
9956856 | 39 days 8 hrs ago | 0 ETH | ||||
9956856 | 39 days 8 hrs ago | 0 ETH | ||||
9956856 | 39 days 8 hrs ago | 0.00044017 ETH | ||||
9956856 | 39 days 8 hrs ago | 0 ETH | ||||
9887647 | 51 days 10 hrs ago | 0 ETH | ||||
9887647 | 51 days 10 hrs ago | 0 ETH | ||||
9887647 | 51 days 10 hrs ago | 0 ETH | ||||
9887647 | 51 days 10 hrs ago | 0.0004828 ETH | ||||
9887647 | 51 days 10 hrs ago | 0 ETH | ||||
9880880 | 52 days 13 hrs ago | 0 ETH | ||||
9880879 | 52 days 13 hrs ago | 0 ETH | ||||
9880879 | 52 days 13 hrs ago | 0 ETH | ||||
9880879 | 52 days 13 hrs ago | 0 ETH | ||||
9880879 | 52 days 13 hrs ago | 0 ETH | ||||
9858679 | 56 days 10 hrs ago | 0 ETH | ||||
9858679 | 56 days 10 hrs ago | 0 ETH | ||||
9858679 | 56 days 10 hrs ago | 0 ETH | ||||
9858679 | 56 days 10 hrs ago | 0.00044401 ETH | ||||
9858679 | 56 days 10 hrs ago | 0 ETH | ||||
9858589 | 56 days 10 hrs ago | 0 ETH | ||||
9858588 | 56 days 10 hrs ago | 0 ETH | ||||
9858588 | 56 days 10 hrs ago | 0 ETH | ||||
9858588 | 56 days 10 hrs ago | 0 ETH |
Loading...
Loading
Contract Name:
EntryPoint
Compiler Version
v0.8.17+commit.8df45f5f
Contract Source Code (Solidity Standard Json-Input format)
/** ** Account-Abstraction (EIP-4337) singleton EntryPoint implementation. ** Only one instance required on each chain. **/ // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.12; /* solhint-disable avoid-low-level-calls */ /* solhint-disable no-inline-assembly */ import "../interfaces/IAccount.sol"; import "../interfaces/IPaymaster.sol"; import "../interfaces/IEntryPoint.sol"; import "../utils/Exec.sol"; import "./StakeManager.sol"; import "./SenderCreator.sol"; import "./Helpers.sol"; contract EntryPoint is IEntryPoint, StakeManager { using UserOperationLib for UserOperation; SenderCreator private immutable senderCreator = new SenderCreator(); // internal value used during simulation: need to query aggregator. address private constant SIMULATE_FIND_AGGREGATOR = address(1); // marker for inner call revert on out of gas bytes32 private constant INNER_OUT_OF_GAS = hex'deaddead'; uint256 private constant REVERT_REASON_MAX_LEN = 2048; /** * for simulation purposes, validateUserOp (and validatePaymasterUserOp) must return this value * in case of signature failure, instead of revert. */ uint256 public constant SIG_VALIDATION_FAILED = 1; /** * 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 op * @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, UserOperation calldata userOp, UserOpInfo memory opInfo) private returns (uint256 collected) { uint256 preGas = gasleft(); bytes memory context = getMemoryBytesFromOffset(opInfo.contextOffset); try this.innerHandleOp(userOp.callData, opInfo, context) returns (uint256 _actualGasCost) { collected = _actualGasCost; } catch { bytes32 innerRevertCode; assembly { returndatacopy(0, 0, 32) innerRevertCode := mload(0) } // handleOps was called with gas limit too low. abort entire bundle. if (innerRevertCode == INNER_OUT_OF_GAS) { //report paymaster, since if it is not deliberately caused by the bundler, // it must be a revert caused by paymaster. revert FailedOp(opIndex, "AA95 out of gas"); } uint256 actualGas = preGas - gasleft() + opInfo.preOpGas; collected = _handlePostOp(opIndex, IPaymaster.PostOpMode.postOpReverted, opInfo, context, actualGas); } } /** * 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(UserOperation[] calldata ops, address payable beneficiary) public { 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; for (uint256 i = 0; i < opslen; i++) { collected += _executeUserOp(i, ops[i], opInfos[i]); } _compensate(beneficiary, collected); } //unchecked } /** * 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 ) public { uint256 opasLen = opsPerAggregator.length; uint256 totalOps = 0; for (uint256 i = 0; i < opasLen; i++) { UserOpsPerAggregator calldata opa = opsPerAggregator[i]; UserOperation[] 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]; UserOperation[] 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++; } } uint256 collected = 0; opIndex = 0; for (uint256 a = 0; a < opasLen; a++) { UserOpsPerAggregator calldata opa = opsPerAggregator[a]; emit SignatureAggregatorChanged(address(opa.aggregator)); UserOperation[] 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); } /// @inheritdoc IEntryPoint function simulateHandleOp(UserOperation calldata op, address target, bytes calldata targetCallData) external override { UserOpInfo memory opInfo; _simulationOnlyValidations(op); (uint256 validationData, uint256 paymasterValidationData) = _validatePrepayment(0, op, opInfo); ValidationData memory data = _intersectTimeRange(validationData, paymasterValidationData); numberMarker(); uint256 paid = _executeUserOp(0, op, opInfo); numberMarker(); bool targetSuccess; bytes memory targetResult; if (target != address(0)) { (targetSuccess, targetResult) = target.call(targetCallData); } revert ExecutionResult(opInfo.preOpGas, paid, data.validAfter, data.validUntil, targetSuccess, targetResult); } // A memory copy of UserOp static fields only. // Excluding: callData, initCode and signature. Replacing paymasterAndData with paymaster. struct MemoryUserOp { address sender; uint256 nonce; uint256 callGasLimit; uint256 verificationGasLimit; 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. */ 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; uint callGasLimit = mUserOp.callGasLimit; unchecked { // handleOps was called with gas limit too low. abort entire bundle. if (gasleft() < callGasLimit + mUserOp.verificationGasLimit + 5000) { assembly { 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; //note: opIndex is ignored (relevant only if mode==postOpReverted, which is only possible outside of innerHandleOp) return _handlePostOp(0, mode, opInfo, context, actualGas); } } /** * generate a request Id - unique identifier for this request. * the request ID is a hash over the content of the userOp (except the signature), the entrypoint and the chainid. */ function getUserOpHash(UserOperation calldata userOp) public view returns (bytes32) { return keccak256(abi.encode(userOp.hash(), address(this), block.chainid)); } /** * copy general fields from userOp into the memory opInfo structure. */ function _copyUserOpToMemory(UserOperation calldata userOp, MemoryUserOp memory mUserOp) internal pure { mUserOp.sender = userOp.sender; mUserOp.nonce = userOp.nonce; mUserOp.callGasLimit = userOp.callGasLimit; mUserOp.verificationGasLimit = userOp.verificationGasLimit; mUserOp.preVerificationGas = userOp.preVerificationGas; mUserOp.maxFeePerGas = userOp.maxFeePerGas; mUserOp.maxPriorityFeePerGas = userOp.maxPriorityFeePerGas; bytes calldata paymasterAndData = userOp.paymasterAndData; if (paymasterAndData.length > 0) { require(paymasterAndData.length >= 20, "AA93 invalid paymasterAndData"); mUserOp.paymaster = address(bytes20(paymasterAndData[: 20])); } else { mUserOp.paymaster = address(0); } } /** * Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp. * @dev this method always revert. Successful result is ValidationResult error. other errors are failures. * @dev The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage outside the account's data. * @param userOp the user operation to validate. */ function simulateValidation(UserOperation calldata userOp) external { UserOpInfo memory outOpInfo; _simulationOnlyValidations(userOp); (uint256 validationData, uint256 paymasterValidationData) = _validatePrepayment(0, userOp, outOpInfo); 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); } ValidationData memory data = _intersectTimeRange(validationData, paymasterValidationData); address aggregator = data.aggregator; bool sigFailed = aggregator == address(1); ReturnInfo memory returnInfo = ReturnInfo(outOpInfo.preOpGas, outOpInfo.prefund, sigFailed, data.validAfter, data.validUntil, getMemoryBytesFromOffset(outOpInfo.contextOffset)); if (aggregator != address(0) && aggregator != address(1)) { AggregatorStakeInfo memory aggregatorInfo = AggregatorStakeInfo(aggregator, _getStakeInfo(aggregator)); revert ValidationResultWithAggregation(returnInfo, senderInfo, factoryInfo, paymasterInfo, aggregatorInfo); } revert ValidationResult(returnInfo, senderInfo, factoryInfo, paymasterInfo); } function _getRequiredPrefund(MemoryUserOp memory mUserOp) internal pure returns (uint256 requiredPrefund) { unchecked { //when using a Paymaster, the verificationGasLimit is used also to as a limit for the postOp call. // our security model might call postOp eventually twice uint256 mul = mUserOp.paymaster != address(0) ? 3 : 1; uint256 requiredGas = mUserOp.callGasLimit + mUserOp.verificationGasLimit * mul + mUserOp.preVerificationGas; requiredPrefund = requiredGas * mUserOp.maxFeePerGas; } } // create the sender's contract if needed. 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); } } /** * 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 calldata initCode) public { revert SenderAddressResult(senderCreator.createSender(initCode)); } function _simulationOnlyValidations(UserOperation calldata userOp) internal view { // solhint-disable-next-line no-empty-blocks try this._validateSenderAndPaymaster(userOp.initCode, userOp.sender, userOp.paymasterAndData) {} catch Error(string memory revertReason) { 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. */ function _validateSenderAndPaymaster(bytes calldata initCode, address sender, bytes calldata paymasterAndData) external view { if (initCode.length == 0 && sender.code.length == 0) { // it would revert anyway. but give a meaningful message revert("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 revert("AA30 paymaster not deployed"); } } // always revert revert(""); } /** * call account.validateUserOp. * revert (with FailedOp) in case validateUserOp reverts, or account didn't send required prefund. * decrement account's deposit if needed */ function _validateAccountPrepayment(uint256 opIndex, UserOperation calldata op, UserOpInfo memory opInfo, uint256 requiredPrefund) internal returns (uint256 gasUsedByValidateAccountPrepayment, uint256 validationData) { unchecked { uint256 preGas = gasleft(); MemoryUserOp memory mUserOp = opInfo.mUserOp; address sender = mUserOp.sender; _createSenderIfNeeded(opIndex, opInfo, op.initCode); address paymaster = mUserOp.paymaster; numberMarker(); uint256 missingAccountFunds = 0; if (paymaster == address(0)) { uint256 bal = balanceOf(sender); missingAccountFunds = bal > requiredPrefund ? 0 : requiredPrefund - bal; } try IAccount(sender).validateUserOp{gas : mUserOp.verificationGasLimit}(op, opInfo.userOpHash, missingAccountFunds) returns (uint256 _validationData) { validationData = _validationData; } catch Error(string memory revertReason) { revert FailedOp(opIndex, string.concat("AA23 reverted: ", revertReason)); } catch { revert FailedOp(opIndex, "AA23 reverted (or OOG)"); } 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 = uint112(deposit - requiredPrefund); } gasUsedByValidateAccountPrepayment = preGas - gasleft(); } } /** * 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 */ function _validatePaymasterPrepayment(uint256 opIndex, UserOperation calldata op, UserOpInfo memory opInfo, uint256 requiredPreFund, uint256 gasUsedByValidateAccountPrepayment) internal returns (bytes memory context, uint256 validationData) { unchecked { MemoryUserOp memory mUserOp = opInfo.mUserOp; uint256 verificationGasLimit = mUserOp.verificationGasLimit; require(verificationGasLimit > gasUsedByValidateAccountPrepayment, "AA41 too little verificationGas"); uint256 gas = verificationGasLimit - gasUsedByValidateAccountPrepayment; 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 = uint112(deposit - requiredPreFund); try IPaymaster(paymaster).validatePaymasterUserOp{gas : gas}(op, opInfo.userOpHash, requiredPreFund) returns (bytes memory _context, uint256 _validationData){ context = _context; validationData = _validationData; } catch Error(string memory revertReason) { revert FailedOp(opIndex, string.concat("AA33 reverted: ", revertReason)); } catch { revert FailedOp(opIndex, "AA33 reverted (or OOG)"); } } } /** * revert if either account validationData or paymaster validationData is expired */ 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"); } } 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). * 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, UserOperation calldata userOp, UserOpInfo memory outOpInfo) private 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 maxGasValues = mUserOp.preVerificationGas | mUserOp.verificationGasLimit | mUserOp.callGasLimit | userOp.maxFeePerGas | userOp.maxPriorityFeePerGas; require(maxGasValues <= type(uint120).max, "AA94 gas values overflow"); uint256 gasUsedByValidateAccountPrepayment; (uint256 requiredPreFund) = _getRequiredPrefund(mUserOp); (gasUsedByValidateAccountPrepayment, validationData) = _validateAccountPrepayment(opIndex, userOp, outOpInfo, requiredPreFund); //a "marker" where account opcode validation is done and paymaster opcode validation is about to start // (used only by off-chain simulateValidation) numberMarker(); bytes memory context; if (mUserOp.paymaster != address(0)) { (context, paymasterValidationData) = _validatePaymasterPrepayment(opIndex, userOp, outOpInfo, requiredPreFund, gasUsedByValidateAccountPrepayment); } unchecked { uint256 gasUsed = preGas - gasleft(); if (userOp.verificationGasLimit < gasUsed) { revert FailedOp(opIndex, "AA40 over verificationGasLimit"); } 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 opIndex index in the batch * @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 _handlePostOp(uint256 opIndex, 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) { IPaymaster(paymaster).postOp{gas : mUserOp.verificationGasLimit}(mode, context, actualGasCost); } else { // solhint-disable-next-line no-empty-blocks try IPaymaster(paymaster).postOp{gas : mUserOp.verificationGasLimit}(mode, context, actualGasCost) {} catch Error(string memory reason) { revert FailedOp(opIndex, string.concat("AA50 postOp reverted: ", reason)); } catch { revert FailedOp(opIndex, "AA50 postOp revert"); } } } } actualGas += preGas - gasleft(); actualGasCost = actualGas * gasPrice; if (opInfo.prefund < actualGasCost) { revert FailedOp(opIndex, "AA51 prefund below actualGasCost"); } uint256 refund = opInfo.prefund - actualGasCost; _incrementDeposit(refundAddress, refund); bool success = mode == IPaymaster.PostOpMode.opSucceeded; emit UserOperationEvent(opInfo.userOpHash, mUserOp.sender, mUserOp.paymaster, mUserOp.nonce, 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 */ 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); } } function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } function getOffsetOfMemoryBytes(bytes memory data) internal pure returns (uint256 offset) { assembly {offset := data} } function getMemoryBytesFromOffset(uint256 offset) internal pure returns (bytes memory data) { assembly {data := offset} } //place the NUMBER opcode in the code. // this is used as a marker during simulation, as this OP is completely banned from the simulated code of the // account and paymaster. function numberMarker() internal view { assembly {mstore(0, number())} } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.12; /** * returned data from validateUserOp. * validateUserOp returns a uint256, with is created by `_packedValidationData` and parsed by `_parseValidationData` * @param aggregator - address(0) - the account validated the signature by itself. * address(1) - the account failed to validate the signature. * otherwise - this is an address of a signature aggregator that must be used to validate the signature. * @param validAfter - this UserOp is valid only after this timestamp. * @param validaUntil - this UserOp is valid only up to this timestamp. */ struct ValidationData { address aggregator; uint48 validAfter; uint48 validUntil; } //extract sigFailed, validAfter, validUntil. // also convert zero validUntil to type(uint48).max function _parseValidationData(uint validationData) pure returns (ValidationData memory data) { address aggregator = address(uint160(validationData)); uint48 validUntil = uint48(validationData >> 160); if (validUntil == 0) { validUntil = type(uint48).max; } uint48 validAfter = uint48(validationData >> (48 + 160)); return ValidationData(aggregator, validAfter, validUntil); } // intersect account and paymaster ranges. function _intersectTimeRange(uint256 validationData, uint256 paymasterValidationData) pure returns (ValidationData memory) { ValidationData memory accountValidationData = _parseValidationData(validationData); ValidationData memory pmValidationData = _parseValidationData(paymasterValidationData); address aggregator = accountValidationData.aggregator; if (aggregator == address(0)) { aggregator = pmValidationData.aggregator; } uint48 validAfter = accountValidationData.validAfter; uint48 validUntil = accountValidationData.validUntil; uint48 pmValidAfter = pmValidationData.validAfter; uint48 pmValidUntil = pmValidationData.validUntil; if (validAfter < pmValidAfter) validAfter = pmValidAfter; if (validUntil > pmValidUntil) validUntil = pmValidUntil; return ValidationData(aggregator, validAfter, validUntil); } /** * helper to pack the return value for validateUserOp * @param data - the ValidationData to pack */ function _packValidationData(ValidationData memory data) pure returns (uint256) { return uint160(data.aggregator) | (uint256(data.validUntil) << 160) | (uint256(data.validAfter) << (160 + 48)); } /** * helper to pack the return value for validateUserOp, when not using an aggregator * @param sigFailed - true for signature failure, false for success * @param validUntil last timestamp this UserOperation is valid (or zero for infinite) * @param validAfter first timestamp this UserOperation is valid */ function _packValidationData(bool sigFailed, uint48 validUntil, uint48 validAfter) pure returns (uint256) { return (sigFailed ? 1 : 0) | (uint256(validUntil) << 160) | (uint256(validAfter) << (160 + 48)); }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.12; /** * 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 { 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.12; 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 function _getStakeInfo(address addr) internal view returns (StakeInfo memory info) { DepositInfo storage depositInfo = deposits[addr]; info.stake = depositInfo.stake; info.unstakeDelaySec = depositInfo.unstakeDelaySec; } /// return the deposit (for gas payment) of the account function balanceOf(address account) public view returns (uint256) { return deposits[account].deposit; } receive() external payable { depositTo(msg.sender); } function _incrementDeposit(address account, uint256 amount) internal { DepositInfo storage info = deposits[account]; uint256 newAmount = info.deposit + amount; require(newAmount <= type(uint112).max, "deposit overflow"); info.deposit = uint112(newAmount); } /** * add to the deposit of the given account */ function depositTo(address account) public payable { _incrementDeposit(account, msg.value); DepositInfo storage info = deposits[account]; emit Deposited(account, info.deposit); } /** * 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 = uint112(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.12; import "./UserOperation.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(UserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds) external returns (uint256 validationData); }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.12; import "./UserOperation.sol"; /** * Aggregated Signatures validator. */ interface IAggregator { /** * validate aggregated signature. * revert if the aggregated signature does not match the given list of operations. */ function validateSignatures(UserOperation[] calldata userOps, bytes calldata signature) external view; /** * validate signature of a single userOp * This method is should be called by bundler after EntryPoint.simulateValidation() returns (reverts) with ValidationResultWithAggregation * First it validates the signature over the userOp. Then it returns data to be used when creating the handleOps. * @param userOp the userOperation received from the user. * @return sigForUserOp the value to put into the signature field of the userOp when calling handleOps. * (usually empty, unless account and aggregator support some kind of "multisig" */ function validateUserOpSignature(UserOperation calldata userOp) external view returns (bytes memory sigForUserOp); /** * aggregate multiple signatures into a single value. * This method is called off-chain to calculate the signature to pass with handleOps() * bundler MAY use optimized custom code perform this aggregation * @param userOps array of UserOperations to collect the signatures from. * @return aggregatedSignature the aggregated signature */ function aggregateSignatures(UserOperation[] calldata userOps) external view returns (bytes memory aggregatedSignature); }
/** ** Account-Abstraction (EIP-4337) singleton EntryPoint implementation. ** Only one instance required on each chain. **/ // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.12; /* solhint-disable avoid-low-level-calls */ /* solhint-disable no-inline-assembly */ /* solhint-disable reason-string */ import "./UserOperation.sol"; import "./IStakeManager.sol"; import "./IAggregator.sol"; interface IEntryPoint is IStakeManager { /*** * 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); /** * signature aggregator used by the following UserOperationEvents within this bundle. */ event SignatureAggregatorChanged(address indexed aggregator); /** * a custom revert error of handleOps, to identify the offending op. * NOTE: if simulateValidation passes successfully, there should be no reason for handleOps to fail on it. * @param opIndex - index into the array of ops to the failed one (in simulateValidation, this is always zero) * @param reason - revert reason * The string starts with a unique code "AAmn", where "m" is "1" for factory, "2" for account and "3" for paymaster issues, * so a failure can be attributed to the correct entity. * Should be caught in off-chain handleOps simulation and not happen on-chain. * Useful for mitigating DoS attempts against batchers or for troubleshooting of factory/account/paymaster reverts. */ error FailedOp(uint256 opIndex, string reason); /** * error case when a signature aggregator fails to verify the aggregated signature it had created. */ error SignatureValidationFailed(address aggregator); /** * Successful result from simulateValidation. * @param returnInfo gas and time-range returned values * @param senderInfo stake information about the sender * @param factoryInfo stake information about the factory (if any) * @param paymasterInfo stake information about the paymaster (if any) */ error ValidationResult(ReturnInfo returnInfo, StakeInfo senderInfo, StakeInfo factoryInfo, StakeInfo paymasterInfo); /** * Successful result from simulateValidation, if the account returns a signature aggregator * @param returnInfo gas and time-range returned values * @param senderInfo stake information about the sender * @param factoryInfo stake information about the factory (if any) * @param paymasterInfo stake information about the paymaster (if any) * @param aggregatorInfo signature aggregation info (if the account requires signature aggregator) * bundler MUST use it to verify the signature, or reject the UserOperation */ error ValidationResultWithAggregation(ReturnInfo returnInfo, StakeInfo senderInfo, StakeInfo factoryInfo, StakeInfo paymasterInfo, AggregatorStakeInfo aggregatorInfo); /** * return value of getSenderAddress */ error SenderAddressResult(address sender); /** * return value of simulateHandleOp */ error ExecutionResult(uint256 preOpGas, uint256 paid, uint48 validAfter, uint48 validUntil, bool targetSuccess, bytes targetResult); //UserOps handled, per aggregator struct UserOpsPerAggregator { UserOperation[] userOps; // aggregator address IAggregator aggregator; // aggregated signature bytes signature; } /** * Execute a batch of UserOperation. * no signature aggregator is used. * if any account requires an aggregator (that is, it returned an aggregator when * performing simulateValidation), then handleAggregatedOps() must be used instead. * @param ops the operations to execute * @param beneficiary the address to receive the fees */ function handleOps(UserOperation[] calldata ops, address payable beneficiary) external; /** * Execute a batch of UserOperation with Aggregators * @param opsPerAggregator the operations to execute, grouped by aggregator (or address(0) for no-aggregator accounts) * @param beneficiary the address to receive the fees */ function handleAggregatedOps( UserOpsPerAggregator[] calldata opsPerAggregator, address payable beneficiary ) external; /** * generate a request Id - unique identifier for this request. * the request ID is a hash over the content of the userOp (except the signature), the entrypoint and the chainid. */ function getUserOpHash(UserOperation calldata userOp) external view returns (bytes32); /** * Simulate a call to account.validateUserOp and paymaster.validatePaymasterUserOp. * @dev this method always revert. Successful result is ValidationResult error. other errors are failures. * @dev The node must also verify it doesn't use banned opcodes, and that it doesn't reference storage outside the account's data. * @param userOp the user operation to validate. */ function simulateValidation(UserOperation calldata userOp) external; /** * gas and return values during simulation * @param preOpGas the gas used for validation (including preValidationGas) * @param prefund the required prefund for this operation * @param sigFailed validateUserOp's (or paymaster's) signature check failed * @param validAfter - first timestamp this UserOp is valid (merging account and paymaster time-range) * @param validUntil - last timestamp this UserOp is valid (merging account and paymaster time-range) * @param paymasterContext returned by validatePaymasterUserOp (to be passed into postOp) */ struct ReturnInfo { uint256 preOpGas; uint256 prefund; bool sigFailed; uint48 validAfter; uint48 validUntil; bytes paymasterContext; } /** * returned aggregated signature info. * the aggregator returned by the account, and its current stake. */ struct AggregatorStakeInfo { address aggregator; StakeInfo stakeInfo; } /** * Get counterfactual sender address. * Calculate the sender contract address that will be generated by the initCode and salt in the UserOperation. * this method always revert, and returns the address in SenderAddressResult error * @param initCode the constructor code to be passed into the UserOperation. */ function getSenderAddress(bytes memory initCode) external; /** * simulate full execution of a UserOperation (including both validation and target execution) * this method will always revert with "ExecutionResult". * it performs full validation of the UserOperation, but ignores signature error. * an optional target address is called after the userop succeeds, and its value is returned * (before the entire call is reverted) * Note that in order to collect the the success/failure of the target call, it must be executed * with trace enabled to track the emitted events. * @param op the UserOperation to simulate * @param target if nonzero, a target address to call after userop simulation. If called, the targetSuccess and targetResult * are set to the return from that call. * @param targetCallData callData to pass to target address */ function simulateHandleOp(UserOperation calldata op, address target, bytes calldata targetCallData) external; }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.12; import "./UserOperation.sol"; /** * the interface exposed by a paymaster contract, who agrees to pay the gas for user's operations. * a paymaster must hold a stake to cover the required entrypoint stake and also the gas for the transaction. */ interface IPaymaster { enum PostOpMode { opSucceeded, // user op succeeded opReverted, // user op reverted. still has to pay for gas. postOpReverted //user op succeeded, but caused postOp to revert. Now it's a 2nd call, after user's op was deliberately reverted. } /** * payment validation: check if paymaster agrees to pay. * Must verify sender is the entryPoint. * Revert to reject this request. * Note that bundlers will reject this method if it changes the state, unless the paymaster is trusted (whitelisted) * The paymaster pre-pays using its deposit, and receive back a refund after the postOp method returns. * @param userOp the user operation * @param userOpHash hash of the user's request data. * @param maxCost the maximum cost of this transaction (based on maximum gas and gas price from userOp) * @return context value to send to a postOp * zero length to signify postOp is not required. * @return validationData signature and time-range of this operation, encoded the same as the return value of validateUserOperation * <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure, * otherwise, an address of an "authorizer" contract. * <6-byte> validUntil - last timestamp this operation is valid. 0 for "indefinite" * <6-byte> validAfter - first timestamp this operation is valid * Note that the validation code cannot use block.timestamp (or block.number) directly. */ function validatePaymasterUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 maxCost) external returns (bytes memory context, uint256 validationData); /** * post-operation handler. * Must verify sender is the entryPoint * @param mode enum with the following options: * opSucceeded - user operation succeeded. * opReverted - user op reverted. still has to pay for gas. * postOpReverted - user op succeeded, but caused postOp (in mode=opSucceeded) to revert. * Now this is the 2nd call, after user's op was deliberately reverted. * @param context - the context value returned by validatePaymasterUserOp * @param actualGasCost - actual gas used so far (without this postOp call). */ function postOp(PostOpMode mode, bytes calldata context, uint256 actualGasCost) external; }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity ^0.8.12; /** * manage deposits and stakes. * deposit is just a balance used to pay for UserOperations (either by a paymaster or an account) * stake is value locked for at least "unstakeDelay" by the staked entity. */ interface IStakeManager { event Deposited( address indexed account, uint256 totalDeposit ); event Withdrawn( address indexed account, address withdrawAddress, uint256 amount ); /// Emitted when stake or unstake delay are modified event StakeLocked( address indexed account, uint256 totalStaked, uint256 unstakeDelaySec ); /// Emitted once a stake is scheduled for withdrawal event StakeUnlocked( address indexed account, uint256 withdrawTime ); event StakeWithdrawn( address indexed account, address withdrawAddress, uint256 amount ); /** * @param deposit the entity's deposit * @param staked true if this entity is staked. * @param stake actual amount of ether staked for this entity. * @param unstakeDelaySec minimum delay to withdraw the stake. * @param withdrawTime - first block timestamp where 'withdrawStake' will be callable, or zero if already locked * @dev sizes were chosen so that (deposit,staked, stake) fit into one cell (used during handleOps) * and the rest fit into a 2nd cell. * 112 bit allows for 10^15 eth * 48 bit for full timestamp * 32 bit allows 150 years for unstake delay */ struct DepositInfo { uint112 deposit; bool staked; uint112 stake; uint32 unstakeDelaySec; uint48 withdrawTime; } //API struct used by getStakeInfo and simulateValidation struct StakeInfo { uint256 stake; uint256 unstakeDelaySec; } /// @return info - full deposit information of given account function getDepositInfo(address account) external view returns (DepositInfo memory info); /// @return the deposit (for gas payment) of the account function balanceOf(address account) external view returns (uint256); /** * add to the deposit of the given account */ function depositTo(address account) external payable; /** * add to the account's stake - amount and delay * any pending unstake is first cancelled. * @param _unstakeDelaySec the new lock duration before the deposit can be withdrawn. */ function addStake(uint32 _unstakeDelaySec) external payable; /** * attempt to unlock the stake. * the value can be withdrawn (using withdrawStake) after the unstake delay. */ function unlockStake() external; /** * withdraw from the (unlocked) stake. * must first call unlockStake and wait for the unstakeDelay to pass * @param withdrawAddress the address to send withdrawn value. */ function withdrawStake(address payable withdrawAddress) external; /** * withdraw from the deposit. * @param withdrawAddress the address to send withdrawn value. * @param withdrawAmount the amount to withdraw. */ function withdrawTo(address payable withdrawAddress, uint256 withdrawAmount) external; }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.12; /* solhint-disable no-inline-assembly */ /** * User Operation struct * @param sender the sender account of this request. * @param nonce unique value the sender uses to verify it is not a replay. * @param initCode if set, the account contract will be created by this constructor/ * @param callData the method call to execute on this account. * @param callGasLimit the gas limit passed to the callData method call. * @param verificationGasLimit gas used for validateUserOp and validatePaymasterUserOp. * @param preVerificationGas gas not calculated by the handleOps method, but added to the gas paid. Covers batch overhead. * @param maxFeePerGas same as EIP-1559 gas parameter. * @param maxPriorityFeePerGas same as EIP-1559 gas parameter. * @param paymasterAndData if set, this field holds the paymaster address and paymaster-specific data. the paymaster will pay for the transaction instead of the sender. * @param signature sender-verified signature over the entire request, the EntryPoint address and the chain ID. */ struct UserOperation { address sender; uint256 nonce; bytes initCode; bytes callData; uint256 callGasLimit; uint256 verificationGasLimit; uint256 preVerificationGas; uint256 maxFeePerGas; uint256 maxPriorityFeePerGas; bytes paymasterAndData; bytes signature; } /** * Utility functions helpful when working with UserOperation structs. */ library UserOperationLib { function getSender(UserOperation calldata userOp) internal pure returns (address) { address data; //read sender from userOp, which is first userOp member (saves 800 gas...) assembly {data := calldataload(userOp)} return address(uint160(data)); } //relayer/block builder might submit the TX with higher priorityFee, but the user should not // pay above what he signed for. function gasPrice(UserOperation calldata userOp) internal view returns (uint256) { unchecked { uint256 maxFeePerGas = userOp.maxFeePerGas; uint256 maxPriorityFeePerGas = userOp.maxPriorityFeePerGas; if (maxFeePerGas == maxPriorityFeePerGas) { //legacy mode (for networks that don't support basefee opcode) return maxFeePerGas; } return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee); } } function pack(UserOperation calldata userOp) internal pure returns (bytes memory ret) { //lighter signature scheme. must match UserOp.ts#packUserOp bytes calldata sig = userOp.signature; // copy directly the userOp from calldata up to (but not including) the signature. // this encoding depends on the ABI encoding of calldata, but is much lighter to copy // than referencing each field separately. assembly { let ofs := userOp let len := sub(sub(sig.offset, ofs), 32) ret := mload(0x40) mstore(0x40, add(ret, add(len, 32))) mstore(ret, len) calldatacopy(add(ret, 32), ofs, len) } } function hash(UserOperation calldata userOp) internal pure returns (bytes32) { return keccak256(pack(userOp)); } function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } }
// SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.7.5 <0.9.0; // 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 { 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 { 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 { 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 { 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 { 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)); } } }
{ "optimizer": { "enabled": true, "runs": 1000000 }, "viaIR": true, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
[{"inputs":[{"internalType":"uint256","name":"preOpGas","type":"uint256"},{"internalType":"uint256","name":"paid","type":"uint256"},{"internalType":"uint48","name":"validAfter","type":"uint48"},{"internalType":"uint48","name":"validUntil","type":"uint48"},{"internalType":"bool","name":"targetSuccess","type":"bool"},{"internalType":"bytes","name":"targetResult","type":"bytes"}],"name":"ExecutionResult","type":"error"},{"inputs":[{"internalType":"uint256","name":"opIndex","type":"uint256"},{"internalType":"string","name":"reason","type":"string"}],"name":"FailedOp","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"SenderAddressResult","type":"error"},{"inputs":[{"internalType":"address","name":"aggregator","type":"address"}],"name":"SignatureValidationFailed","type":"error"},{"inputs":[{"components":[{"internalType":"uint256","name":"preOpGas","type":"uint256"},{"internalType":"uint256","name":"prefund","type":"uint256"},{"internalType":"bool","name":"sigFailed","type":"bool"},{"internalType":"uint48","name":"validAfter","type":"uint48"},{"internalType":"uint48","name":"validUntil","type":"uint48"},{"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"}],"name":"ValidationResult","type":"error"},{"inputs":[{"components":[{"internalType":"uint256","name":"preOpGas","type":"uint256"},{"internalType":"uint256","name":"prefund","type":"uint256"},{"internalType":"bool","name":"sigFailed","type":"bool"},{"internalType":"uint48","name":"validAfter","type":"uint48"},{"internalType":"uint48","name":"validUntil","type":"uint48"},{"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"}],"name":"ValidationResultWithAggregation","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":[{"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":"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"},{"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":[],"name":"SIG_VALIDATION_FAILED","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"initCode","type":"bytes"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"bytes","name":"paymasterAndData","type":"bytes"}],"name":"_validateSenderAndPaymaster","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"unstakeDelaySec","type":"uint32"}],"name":"addStake","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"depositTo","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"deposits","outputs":[{"internalType":"uint112","name":"deposit","type":"uint112"},{"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":"uint112","name":"deposit","type":"uint112"},{"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":"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":"uint256","name":"callGasLimit","type":"uint256"},{"internalType":"uint256","name":"verificationGasLimit","type":"uint256"},{"internalType":"uint256","name":"preVerificationGas","type":"uint256"},{"internalType":"uint256","name":"maxFeePerGas","type":"uint256"},{"internalType":"uint256","name":"maxPriorityFeePerGas","type":"uint256"},{"internalType":"bytes","name":"paymasterAndData","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct UserOperation","name":"userOp","type":"tuple"}],"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":"uint256","name":"callGasLimit","type":"uint256"},{"internalType":"uint256","name":"verificationGasLimit","type":"uint256"},{"internalType":"uint256","name":"preVerificationGas","type":"uint256"},{"internalType":"uint256","name":"maxFeePerGas","type":"uint256"},{"internalType":"uint256","name":"maxPriorityFeePerGas","type":"uint256"},{"internalType":"bytes","name":"paymasterAndData","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct UserOperation[]","name":"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":"uint256","name":"callGasLimit","type":"uint256"},{"internalType":"uint256","name":"verificationGasLimit","type":"uint256"},{"internalType":"uint256","name":"preVerificationGas","type":"uint256"},{"internalType":"uint256","name":"maxFeePerGas","type":"uint256"},{"internalType":"uint256","name":"maxPriorityFeePerGas","type":"uint256"},{"internalType":"bytes","name":"paymasterAndData","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct UserOperation[]","name":"ops","type":"tuple[]"},{"internalType":"address payable","name":"beneficiary","type":"address"}],"name":"handleOps","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":"callGasLimit","type":"uint256"},{"internalType":"uint256","name":"verificationGasLimit","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":[{"components":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes","name":"initCode","type":"bytes"},{"internalType":"bytes","name":"callData","type":"bytes"},{"internalType":"uint256","name":"callGasLimit","type":"uint256"},{"internalType":"uint256","name":"verificationGasLimit","type":"uint256"},{"internalType":"uint256","name":"preVerificationGas","type":"uint256"},{"internalType":"uint256","name":"maxFeePerGas","type":"uint256"},{"internalType":"uint256","name":"maxPriorityFeePerGas","type":"uint256"},{"internalType":"bytes","name":"paymasterAndData","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct UserOperation","name":"op","type":"tuple"},{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"targetCallData","type":"bytes"}],"name":"simulateHandleOp","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes","name":"initCode","type":"bytes"},{"internalType":"bytes","name":"callData","type":"bytes"},{"internalType":"uint256","name":"callGasLimit","type":"uint256"},{"internalType":"uint256","name":"verificationGasLimit","type":"uint256"},{"internalType":"uint256","name":"preVerificationGas","type":"uint256"},{"internalType":"uint256","name":"maxFeePerGas","type":"uint256"},{"internalType":"uint256","name":"maxPriorityFeePerGas","type":"uint256"},{"internalType":"bytes","name":"paymasterAndData","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct UserOperation","name":"userOp","type":"tuple"}],"name":"simulateValidation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unlockStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"withdrawAddress","type":"address"}],"name":"withdrawStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"withdrawAddress","type":"address"},{"internalType":"uint256","name":"withdrawAmount","type":"uint256"}],"name":"withdrawTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60a08060405234620000845761022c8181016001600160401b038111838210176200006e57829162005773833903906000f0801562000062576080526040516156e990816200008a8239608051818181611321015281816139700152613c910152f35b6040513d6000823e3d90fd5b634e487b7160e01b600052604160045260246000fd5b600080fdfe60806040526004361015610023575b361561001957600080fd5b610021614f9c565b005b60003560e01c80630396cb60146101775780631d7327561461016e5780631fad948c14610165578063205c28781461015c5780634b1d7cf5146101535780635287ce121461014a57806370a08231146101415780638f41ec5a14610138578063957122ab1461012f5780639b249f6914610126578063a61935311461011d578063b760faf914610114578063bb9fe6bf1461010b578063c23a5cea14610102578063d6383f94146100f9578063ee219423146100f05763fc7e286d0361000e576100eb611b0f565b61000e565b506100eb6118f7565b506100eb61178f565b506100eb6115f6565b506100eb611478565b506100eb611439565b506100eb611418565b506100eb611279565b506100eb6110a6565b506100eb61106b565b506100eb610fe6565b506100eb610e96565b506100eb610b6b565b506100eb6109cc565b506100eb61071c565b506100eb610549565b5060207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031d5760043563ffffffff811680820361031d576103187fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c01916102356102053373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b91610211811515615102565b61022e610225600185015463ffffffff1690565b63ffffffff1690565b1115615167565b54926102fa6dffffffffffffffffffffffffffff946102b861025c34888460781c166120aa565b966102688815156151cc565b61027481891115615231565b61029881610280610409565b941684906dffffffffffffffffffffffffffff169052565b6001602084015287166dffffffffffffffffffffffffffff166040830152565b63ffffffff83166060820152600060808201526102f53373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b615296565b6040805194855263ffffffff90911660208501523393918291820190565b0390a2005b600080fd5b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60a0810190811067ffffffffffffffff82111761036e57604052565b610376610322565b604052565b610100810190811067ffffffffffffffff82111761036e57604052565b67ffffffffffffffff811161036e57604052565b6060810190811067ffffffffffffffff82111761036e57604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761036e57604052565b6040519061041682610352565b565b6040519060c0820182811067ffffffffffffffff82111761036e57604052565b604051906040820182811067ffffffffffffffff82111761036e57604052565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f60209267ffffffffffffffff8111610494575b01160190565b61049c610322565b61048e565b9291926104ad82610458565b916104bb60405193846103c8565b82948184528183011161031d578281602093846000960137010152565b73ffffffffffffffffffffffffffffffffffffffff81160361031d57565b60243590610416826104d8565b60c43590610416826104d8565b3590610416826104d8565b9181601f8401121561031d5782359167ffffffffffffffff831161031d576020838186019501011161031d57565b503461031d576101c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031d5767ffffffffffffffff60043581811161031d573660238201121561031d576105ac9036906024816004013591016104a1565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc3601610180811261031d57610100604051916105e983610352565b1261031d576040516105fa8161037b565b6106026104f6565b815260443560208201526064356040820152608435606082015260a435608082015261062c610503565b60a082015260e43560c08201526101043560e082015281526101243560208201526101443560408201526101643560608201526101843560808201526101a43591821161031d576106a09261068861069093369060040161051b565b929091612786565b6040519081529081906020820190565b0390f35b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc83011261031d5760043567ffffffffffffffff9283821161031d578060238301121561031d57816004013593841161031d5760248460051b8301011161031d576024019190602435610719816104d8565b90565b503461031d5761072b366106a4565b610736829392611c6f565b60005b848110610788575060009283915b858310610758576100218585611dac565b90919360019061077e61076c878987611d2e565b6107768886611d0c565b519088612214565b0194019190610747565b6107b36107ac61079a83859795611d0c565b516107a6848987611d2e565b84612fc4565b9190612d9b565b73ffffffffffffffffffffffffffffffffffffffff9291831661095e576108f0576107dd90612d9b565b9116610882576107f257600101929092610739565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602160448201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a490fd5b0390fd5b61087e826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601460408201527f41413334207369676e6174757265206572726f7200000000000000000000000060608201520190565b61087e836040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601760408201527f414132322065787069726564206f72206e6f742064756500000000000000000060608201520190565b61087e846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601460408201527f41413234207369676e6174757265206572726f7200000000000000000000000060608201520190565b503461031d5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031d57600435610a08816104d8565b6024359060009133835282602052604083206dffffffffffffffffffffffffffff81541692838311610b0d57848373ffffffffffffffffffffffffffffffffffffffff829593610ab08496610a77610a648798610b0a9c612095565b6dffffffffffffffffffffffffffff1690565b6dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b6040805173ffffffffffffffffffffffffffffffffffffffff831681526020810185905233917fd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb91a2165af1610b04611d7c565b5061560d565b80f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f576974686472617720616d6f756e7420746f6f206c61726765000000000000006044820152fd5b503461031d57610b7a366106a4565b6000805b838210610d3c57610b8f9150611c6f565b6000805b848110610ca257505060008093815b818110610bd957610021868660007f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d8180a2611dac565b610c3d610be782848a6123a0565b610c12610bf9610bf960208401612442565b73ffffffffffffffffffffffffffffffffffffffff1690565b7f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d600080a2806123ee565b906000915b808310610c5a57505050610c5590612366565b610ba2565b90919497610c95610c8f610c9b92610c898c8b610c8282610c7c8e8b8d611d2e565b92611d0c565b5191612214565b906120aa565b99612366565b95612366565b9190610c42565b610cad8186886123a0565b6020610cc5610cbc83806123ee565b92909301612442565b9173ffffffffffffffffffffffffffffffffffffffff60009316905b828410610cfa5750505050610cf590612366565b610b93565b90919294610c9581610d2f85610d28610d16610d34968d611d0c565b51610d228c8b8a611d2e565b85612fc4565b908b612d53565b612366565b929190610ce1565b610d478285876123a0565b90610d5282806123ee565b92610d62610bf960208301612442565b9173ffffffffffffffffffffffffffffffffffffffff8316610d87600182141561244c565b610da8575b505050610da291610d9c916120aa565b91612366565b90610b7e565b909592610dc16040999693999895989788810190611e9d565b92908a3b1561031d5789938b918a5193849283927fe3563a4f00000000000000000000000000000000000000000000000000000000845260049e8f850193610e08946125e6565b03815a93600094fa9081610e7d575b50610e675786517f86a9f75000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a16818a0190815281906020010390fd5b9497509295509093509181610d9c610da2610d8c565b80610e8a610e9092610398565b80611060565b38610e17565b503461031d5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031d576106a073ffffffffffffffffffffffffffffffffffffffff600435610eea816104d8565b608060409283928351610efc81610352565b600093818580935282602082015282878201528260608201520152168152806020522090610f8b65ffffffffffff6001835194610f3886610352565b80546dffffffffffffffffffffffffffff8082168852607082901c60ff161515602089015260789190911c1685870152015463ffffffff8116606086015260201c16608084019065ffffffffffff169052565b5191829182919091608065ffffffffffff8160a08401956dffffffffffffffffffffffffffff808251168652602082015115156020870152604082015116604086015263ffffffff6060820151166060860152015116910152565b503461031d5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031d5773ffffffffffffffffffffffffffffffffffffffff600435611037816104d8565b16600052600060205260206dffffffffffffffffffffffffffff60406000205416604051908152f35b600091031261031d57565b503461031d5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031d57602060405160018152f35b503461031d5760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031d57600467ffffffffffffffff813581811161031d576110f7903690840161051b565b905060243591611106836104d8565b60443590811161031d5761111d903690850161051b565b92909115908161126f575b50611208576014821015611178575b61087e836040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160409060208152600060208201520190565b6111886111949261118e926129ab565b906129b9565b60601c90565b3b156111a1573880611137565b61087e906040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160609060208152601b60208201527f41413330207061796d6173746572206e6f74206465706c6f796564000000000060408201520190565b61087e836040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160609060208152601960208201527f41413230206163636f756e74206e6f74206465706c6f7965640000000000000060408201520190565b90503b1538611128565b503461031d5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031d5760043567ffffffffffffffff811161031d576112cb602491369060040161051b565b906113016040519283927f570e1a3600000000000000000000000000000000000000000000000000000000845260048401612b4f565b0360208273ffffffffffffffffffffffffffffffffffffffff92816000857f0000000000000000000000000000000000000000000000000000000000000000165af19182156113b3575b600092611383575b50604051917f6ca7b806000000000000000000000000000000000000000000000000000000008352166004820152fd5b6113a591925060203d81116113ac575b61139d81836103c8565b810190612b3a565b9038611353565b503d611393565b6113bb612058565b61134b565b908161016091031261031d5790565b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82011261031d576004359067ffffffffffffffff821161031d57610719916004016113c0565b503461031d57602061143161142c366113cf565b6128e1565b604051908152f35b5060207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031d57610021600435611473816104d8565b615096565b503461031d576000807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126115f3573381528060205260408120600181019063ffffffff825416908115611595576115326114f761155a936114e96114e4855460ff9060701c1690565b6153fa565b65ffffffffffff421661545f565b84547fffffffffffffffffffffffffffffffffffffffffffff000000000000ffffffff16602082901b69ffffffffffff000000001617909455565b7fffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffff8154169055565b60405165ffffffffffff91909116815233907ffa9b3c14cc825c412c9ed81b3ba365a5b459439403f18829e572ed53a4180f0a90602090a280f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f6e6f74207374616b6564000000000000000000000000000000000000000000006044820152fd5b80fd5b503461031d5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031d57600435611632816104d8565b610b0a73ffffffffffffffffffffffffffffffffffffffff6116743373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b9261172c611697610a6486546dffffffffffffffffffffffffffff9060781c1690565b946116a3861515615479565b611704600182016116dc65ffffffffffff6116c8835465ffffffffffff9060201c1690565b166116d48115156154de565b421015615543565b80547fffffffffffffffffffffffffffffffffffffffffffff00000000000000000000169055565b7fffffff0000000000000000000000000000ffffffffffffffffffffffffffffff8154169055565b6040805173ffffffffffffffffffffffffffffffffffffffff831681526020810186905233917fb7c918e0e249f999e965cafeb6c664271b3f4317d296461500e71da39f0cbda391a2600080809581948294165af1611789611d7c565b506155a8565b503461031d5760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031d5767ffffffffffffffff60043581811161031d576117e09036906004016113c0565b602435916117ed836104d8565b60443590811161031d5761180861087e91369060040161051b565b611810611bec565b61181985612c4e565b61182c6118268287612e5c565b90614e95565b9461183c826000924384526120b7565b96438252819360609573ffffffffffffffffffffffffffffffffffffffff83166118c3575b5050505060800151936118906040611882602084015165ffffffffffff1690565b92015165ffffffffffff1690565b906040519687967f8b7ac980000000000000000000000000000000000000000000000000000000008852600488016126b6565b839550839496506118dd60409492939451809481936126a8565b03925af19060806118ec611d7c565b929190388080611861565b503461031d57611906366113cf565b61190e611bec565b61191782612c4e565b6119218183612e5c565b825160a0015191939161194e9073ffffffffffffffffffffffffffffffffffffffff16614f47565b614f47565b90611972611949855173ffffffffffffffffffffffffffffffffffffffff90511690565b9461197b612973565b506119aa61198e60409586810190611e9d565b90600060148310611b0757506111886119499261118e926129ab565b916119b491614e95565b805173ffffffffffffffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff821660018114916080880151978781015191886020820151611a099065ffffffffffff1690565b91015165ffffffffffff16916060015192611a22610418565b9a8b5260208b0152841515898b015265ffffffffffff1660608a015265ffffffffffff16608089015260a088015215159081611afe575b50611a93575061087e92519485947fe0cff05f00000000000000000000000000000000000000000000000000000000865260048601612ae0565b919061087e93611aa284614f47565b611ac9611aad610438565b73ffffffffffffffffffffffffffffffffffffffff9096168652565b6020850152519586957ffaecb4e400000000000000000000000000000000000000000000000000000000875260048701612a4e565b90501538611a59565b915050614f47565b503461031d5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031d5773ffffffffffffffffffffffffffffffffffffffff600435611b60816104d8565b16600052600060205260a0604060002065ffffffffffff60018254920154604051926dffffffffffffffffffffffffffff90818116855260ff8160701c161515602086015260781c16604084015263ffffffff8116606084015260201c166080820152f35b60209067ffffffffffffffff8111611bdf575b60051b0190565b611be7610322565b611bd8565b60405190611bf982610352565b604051608083610100830167ffffffffffffffff811184821017611c62575b60405260009283815283602082015283604082015283606082015283838201528360a08201528360c08201528360e082015281528260208201528260408201528260608201520152565b611c6a610322565b611c18565b90611c7982611bc5565b611c8660405191826103c8565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0611cb48294611bc5565b019060005b828110611cc557505050565b602090611cd0611bec565b82828501015201611cb9565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020918151811015611d21575b60051b010190565b611d29611cdc565b611d19565b9190811015611d6f575b60051b810135907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea18136030182121561031d570190565b611d77611cdc565b611d38565b3d15611da7573d90611d8d82610458565b91611d9b60405193846103c8565b82523d6000602084013e565b606090565b73ffffffffffffffffffffffffffffffffffffffff168015611e3f57600080809381935af1611dd9611d7c565b5015611de157565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f41413931206661696c65642073656e6420746f2062656e6566696369617279006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4141393020696e76616c69642062656e656669636961727900000000000000006044820152fd5b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561031d570180359067ffffffffffffffff821161031d5760200191813603831361031d57565b9081602091031261031d575190565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b60005b838110611f4f5750506000910152565b8181015183820152602001611f3f565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f602093611f9b81518092818752878088019101611f3c565b0116010190565b90611fbc60809161071996946101c0808652850191611efd565b9360e0815173ffffffffffffffffffffffffffffffffffffffff80825116602087015260208201516040870152604082015160608701526060820151858701528482015160a087015260a08201511660c086015260c081015182860152015161010084015260208101516101208401526040810151610140840152606081015161016084015201516101808201526101a0818403910152611f5f565b506040513d6000823e3d90fd5b507f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b919082039182116120a257565b610416612065565b919082018092116120a257565b905a918160206120d06060830151936060810190611e9d565b906121098560405195869485947f1d73275600000000000000000000000000000000000000000000000000000000865260048601611fa2565b03816000305af1600091816121e4575b506121dd575060206000803e7fdeaddead00000000000000000000000000000000000000000000000000000000600051146121705761216a61215f610719945a90612095565b6080840151906120aa565b916145d7565b6040517f220266b60000000000000000000000000000000000000000000000000000000081528061087e600482016080906000815260406020820152600f60408201527f41413935206f7574206f6620676173000000000000000000000000000000000060608201520190565b9250505090565b61220691925060203d811161220d575b6121fe81836103c8565b810190611eee565b9038612119565b503d6121f4565b909291925a938060206122306060830151946060810190611e9d565b906122698660405195869485947f1d73275600000000000000000000000000000000000000000000000000000000865260048601611fa2565b03816000305af160009181612346575b5061233f575060206000803e7fdeaddead00000000000000000000000000000000000000000000000000000000600051146122d1576122cb6122c061071995965a90612095565b6080830151906120aa565b926148ba565b61087e836040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152600f60408201527f41413935206f7574206f6620676173000000000000000000000000000000000060608201520190565b9450505050565b61235f91925060203d811161220d576121fe81836103c8565b9038612279565b6001907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114612394570190565b61239c612065565b0190565b91908110156123e1575b60051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa18136030182121561031d570190565b6123e9611cdc565b6123aa565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561031d570180359067ffffffffffffffff821161031d57602001918160051b3603831361031d57565b35610719816104d8565b1561245357565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393620696e76616c69642061676772656761746f720000000000000000006044820152fd5b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18236030181121561031d57016020813591019167ffffffffffffffff821161031d57813603831361031d57565b6107199161252c8161251284610510565b73ffffffffffffffffffffffffffffffffffffffff169052565b602082013560208201526125c761257861255d61254c60408601866124b1565b610160806040880152860191611efd565b61256a60608601866124b1565b908583036060870152611efd565b6080840135608084015260a084013560a084015260c084013560c084015260e084013560e084015261010080850135908401526101206125ba818601866124b1565b9185840390860152611efd565b916125d861014091828101906124b1565b929091818503910152611efd565b949391929083604087016040885252606086019360608160051b8801019482600090815b8483106126295750505050505084602061071995968503910152611efd565b9091929394977fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08b820301855288357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea1843603018112156126a457600191846126929201612501565b9860209081019695019301919061260a565b8280fd5b908092918237016000815290565b92909361071996959260c0958552602085015265ffffffffffff8092166040850152166060830152151560808201528160a08201520190611f5f565b156126f957565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393220696e7465726e616c2063616c6c206f6e6c790000000000000000006044820152fd5b90604061071992600081528160208201520190611f5f565b604090610719939281528160208201520190611f5f565b909291925a936127973033146126f2565b8151946040860151955a6113886060830151890101116128b7576107199660009580516127de575b505050906127d8915a90036080840151019436916104a1565b91614b22565b61280d9161280991612804855173ffffffffffffffffffffffffffffffffffffffff1690565b615672565b1590565b612819575b80806127bf565b6127d892919450612828615684565b90815161283c575b50506001939091612812565b7f1c4fada7374c0a9ee8841fc38afe82932dc0f8e69012e927f061a8bae611a20173ffffffffffffffffffffffffffffffffffffffff6020870151926128ad602061289b835173ffffffffffffffffffffffffffffffffffffffff1690565b9201519560405193849316968361276f565b0390a33880612830565b7fdeaddead0000000000000000000000000000000000000000000000000000000060005260206000fd5b806128f0610140820182611e9d565b50037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081016040519182016040528082526020820192833751902060405160208101918252306040820152466060820152606081526080810181811067ffffffffffffffff821117612966575b60405251902090565b61296e610322565b61295d565b604051906040820182811067ffffffffffffffff82111761299e575b60405260006020838281520152565b6129a6610322565b61298f565b9060141161031d5790601490565b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000090358181169392601481106129ee57505050565b60140360031b82901b16169150565b9060c060a061071993805184526020810151602085015260408101511515604085015265ffffffffffff80606083015116606086015260808201511660808501520151918160a08201520190611f5f565b9294612aaf61041695612a9d610100959998612a8b612a77602097610140808c528b01906129fd565b9b878a019060208091805184520151910152565b80516060890152602001516080880152565b805160a08701526020015160c0860152565b73ffffffffffffffffffffffffffffffffffffffff81511660e0850152015191019060208091805184520151910152565b612b2961041694612b17612b0260a0959998969960e0865260e08601906129fd565b98602085019060208091805184520151910152565b80516060840152602001516080830152565b019060208091805184520151910152565b9081602091031261031d5751610719816104d8565b916020610719938181520191611efd565b90612b8f73ffffffffffffffffffffffffffffffffffffffff9161071997959694606085526060850191611efd565b941660208201526040818503910152611efd565b60009060033d11612bb057565b905060046000803e60005160e01c90565b600060443d10610719576040517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc91823d016004833e815167ffffffffffffffff918282113d602484011117612c3d57818401948551938411612c45573d85010160208487010111612c3d5750610719929101602001906103c8565b949350505050565b50949350505050565b612c5b6040820182611e9d565b612c73612c6784612442565b93610120810190611e9d565b9290303b1561031d57600093612cb79160405196879586957f957122ab00000000000000000000000000000000000000000000000000000000875260048701612b60565b0381305afa9081612d40575b50610416576001612cd2612ba3565b6308c379a014612ceb575b612ce357565b610416612058565b612cf3612bc1565b80612cff575b50612cdd565b80516000925015612cf95761087e906040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301612757565b80610e8a612d4d92610398565b38612cc3565b929190612d5f90612d9b565b909273ffffffffffffffffffffffffffffffffffffffff8080951691160361095e576108f057612d8e90612d9b565b9116610882576107f25750565b8015612dee57612daa90614e3a565b73ffffffffffffffffffffffffffffffffffffffff65ffffffffffff806040840151164211908115612dde575b5091511691565b9050602083015116421038612dd7565b50600090600090565b15612dfe57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f41413934206761732076616c756573206f766572666c6f7700000000000000006044820152fd5b916000915a93815190612e6f828261318e565b612e78816128e1565b6020840152612eb66effffffffffffffffffffffffffffff60808401516060850151176040850151176101008401359060e085013517171115612df7565b612ebf82613250565b612eca818584613311565b9790612ed543600052565b73ffffffffffffffffffffffffffffffffffffffff612f0d60a0606097015173ffffffffffffffffffffffffffffffffffffffff1690565b16612faa575b505a810360a084013510612f3d5760809360c092604087015260608601525a900391013501910152565b6040517f220266b60000000000000000000000000000000000000000000000000000000081528061087e600482016080906000815260406020820152601e60408201527f41413430206f76657220766572696669636174696f6e4761734c696d6974000060608201520190565b90935081612fbb9297508584614037565b95909238612f13565b9290916000925a8251612fd7818461318e565b612fe0836128e1565b602085015261301e6effffffffffffffffffffffffffffff60808301516060840151176040840151176101008601359060e087013517171115612df7565b61302781613250565b6130338186868b61367d565b989061303e43600052565b73ffffffffffffffffffffffffffffffffffffffff61307660a0606096015173ffffffffffffffffffffffffffffffffffffffff1690565b1661310e575b505a840360a0860135106130a85750604085015260608401526080919060c0905a900391013501910152565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601e60448201527f41413430206f76657220766572696669636174696f6e4761734c696d697400006064820152608490fd5b909250816131209298508686856142ca565b9690913861307c565b1561313057565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4141393320696e76616c6964207061796d6173746572416e64446174610000006044820152fd5b613200906131b861319e82612442565b73ffffffffffffffffffffffffffffffffffffffff168452565b602081013560208401526080810135604084015260a0810135606084015260c0810135608084015260e081013560c084015261010081013560e0840152610120810190611e9d565b9081156132455761322a61118e6111888460a094613225601461041699981015613129565b6129ab565b73ffffffffffffffffffffffffffffffffffffffff16910152565b505060a06000910152565b60a081015173ffffffffffffffffffffffffffffffffffffffff16156132925760c060035b60ff60408401519116606084015102016080830151019101510290565b60c06001613275565b6132b360409295949395606083526060830190612501565b9460208201520152565b90610416602f60405180947f414132332072657665727465643a20000000000000000000000000000000000060208301526133018151809260208686019101611f3c565b810103600f8101855201836103c8565b916000926000925a936133df6020835193613340855173ffffffffffffffffffffffffffffffffffffffff1690565b956133586133516040830183611e9d565b90846138e8565b60a086015173ffffffffffffffffffffffffffffffffffffffff169061337d43600052565b85809373ffffffffffffffffffffffffffffffffffffffff809416159889613615575b60600151908601516040517f3a871cdd00000000000000000000000000000000000000000000000000000000815297889687958693906004850161329b565b03938a1690f18291816135f5575b506135ec57506001906133fe612ba3565b6308c379a014613598575b5061352b575b61341c575b50505a900391565b6134469073ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b613461610a6482546dffffffffffffffffffffffffffff1690565b8083116134be576134b7926dffffffffffffffffffffffffffff9103166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b3880613414565b6040517f220266b60000000000000000000000000000000000000000000000000000000081528061087e600482016080906000815260406020820152601760408201527f41413231206469646e2774207061792070726566756e6400000000000000000060608201520190565b6040517f220266b60000000000000000000000000000000000000000000000000000000081528061087e600482016080906000815260406020820152601660408201527f4141323320726576657274656420286f72204f4f47290000000000000000000060608201520190565b6135a0612bc1565b90816135ac5750613409565b61087e916135ba91506132bd565b6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301612757565b955061340f9050565b61360e91925060203d811161220d576121fe81836103c8565b90386133ed565b945061365b610a646136478c73ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b546dffffffffffffffffffffffffffff1690565b8b8111156136725750856060835b969150506133a0565b606087918d03613669565b90926000936000935a946136c660208351936136ad855173ffffffffffffffffffffffffffffffffffffffff1690565b956133586136be6040830183611e9d565b90848c613c06565b03938a1690f18291816138c8575b506138bf57506001906136e5612ba3565b6308c379a014613869575b506137fb575b613704575b5050505a900391565b61372e9073ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b9161374a610a6484546dffffffffffffffffffffffffffff1690565b90818311613795575082547fffffffffffffffffffffffffffffffffffff0000000000000000000000000000169190036dffffffffffffffffffffffffffff161790553880806136fb565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601760448201527f41413231206469646e2774207061792070726566756e640000000000000000006064820152608490fd5b61087e846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601660408201527f4141323320726576657274656420286f72204f4f47290000000000000000000060608201520190565b613871612bc1565b908161387d57506136f0565b869161388991506132bd565b9061087e6040519283927f220266b60000000000000000000000000000000000000000000000000000000084526004840161276f565b96506136f69050565b6138e191925060203d811161220d576121fe81836103c8565b90386136d4565b9091806138f457505050565b81515173ffffffffffffffffffffffffffffffffffffffff1692833b613b9957606083510151604051907f570e1a3600000000000000000000000000000000000000000000000000000000825260208280613953878760048401612b4f565b0381600073ffffffffffffffffffffffffffffffffffffffff95867f00000000000000000000000000000000000000000000000000000000000000001690f1918215613b8c575b600092613b6c575b50808216958615613aff5716809503613a92573b15613a255761118e6111887fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d936139ec936129ab565b602083810151935160a001516040805173ffffffffffffffffffffffffffffffffffffffff9485168152939091169183019190915290a3565b6040517f220266b60000000000000000000000000000000000000000000000000000000081528061087e600482016080906000815260406020820152602060408201527f4141313520696e6974436f6465206d757374206372656174652073656e64657260608201520190565b6040517f220266b60000000000000000000000000000000000000000000000000000000081528061087e600482016080906000815260406020820152602060408201527f4141313420696e6974436f6465206d7573742072657475726e2073656e64657260608201520190565b6040517f220266b60000000000000000000000000000000000000000000000000000000081528061087e600482016080906000815260406020820152601b60408201527f4141313320696e6974436f6465206661696c6564206f72204f4f47000000000060608201520190565b613b8591925060203d81116113ac5761139d81836103c8565b90386139a2565b613b94612058565b61399a565b6040517f220266b60000000000000000000000000000000000000000000000000000000081528061087e600482016080906000815260406020820152601f60408201527f414131302073656e64657220616c726561647920636f6e73747275637465640060608201520190565b92909181613c15575b50505050565b82515173ffffffffffffffffffffffffffffffffffffffff1693843b613ebd57606084510151604051907f570e1a3600000000000000000000000000000000000000000000000000000000825260208280613c74888860048401612b4f565b0381600073ffffffffffffffffffffffffffffffffffffffff95867f00000000000000000000000000000000000000000000000000000000000000001690f1918215613eb0575b600092613e90575b50808216968715613e225716809603613db4573b15613d4e575061118e6111887fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d93613d0e936129ab565b602083810151935160a001516040805173ffffffffffffffffffffffffffffffffffffffff9485168152939091169183019190915290a338808080613c0f565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602060448201527f4141313520696e6974436f6465206d757374206372656174652073656e6465726064820152608490fd5b61087e826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152602060408201527f4141313420696e6974436f6465206d7573742072657475726e2073656e64657260608201520190565b61087e846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601b60408201527f4141313320696e6974436f6465206661696c6564206f72204f4f47000000000060608201520190565b613ea991925060203d81116113ac5761139d81836103c8565b9038613cc3565b613eb8612058565b613cbb565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601f60448201527f414131302073656e64657220616c726561647920636f6e7374727563746564006064820152608490fd5b15613f2a57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4141343120746f6f206c6974746c6520766572696669636174696f6e476173006044820152fd5b919060408382031261031d57825167ffffffffffffffff811161031d5783019080601f8301121561031d57815191613fbf83610458565b91613fcd60405193846103c8565b8383526020848301011161031d57602092613fed91848085019101611f3c565b92015190565b90610416602f60405180947f414133332072657665727465643a20000000000000000000000000000000000060208301526133018151809260208686019101611f3c565b93919260609460009460009380519261407660a08a8601519561405b888811613f23565b015173ffffffffffffffffffffffffffffffffffffffff1690565b916140a18373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b946140bd610a6487546dffffffffffffffffffffffffffff1690565b9685881061425d5773ffffffffffffffffffffffffffffffffffffffff60208a98946141338a966dffffffffffffffffffffffffffff8b61416c9e03166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b015194604051998a98899788937ff465c77e0000000000000000000000000000000000000000000000000000000085526004850161329b565b0395169103f1908183918493614237575b5061423057505060019061418f612ba3565b6308c379a01461420e575b506141a157565b6040517f220266b60000000000000000000000000000000000000000000000000000000081528061087e600482016080906000815260406020820152601660408201527f4141333320726576657274656420286f72204f4f47290000000000000000000060608201520190565b614216612bc1565b9081614222575061419a565b61087e916135ba9150613ff3565b9450925050565b90925061425691503d8085833e61424e81836103c8565b810190613f88565b913861417d565b6040517f220266b60000000000000000000000000000000000000000000000000000000081528061087e600482016080906000815260406020820152601e60408201527f41413331207061796d6173746572206465706f73697420746f6f206c6f77000060608201520190565b9194929390936060956000956000938251906142f160a08b8401519361405b848611613f23565b9361431c8573ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b614337610a6482546dffffffffffffffffffffffffffff1690565b878110614492579273ffffffffffffffffffffffffffffffffffffffff60208a989693946141338a966dffffffffffffffffffffffffffff8d6143b19e9c9a03166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b0395169103f1908183918493614474575b5061446c5750506001906143d4612ba3565b6308c379a01461444d575b506143e75750565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601660448201527f4141333320726576657274656420286f72204f4f4729000000000000000000006064820152608490fd5b614455612bc1565b908161446157506143df565b613889925050613ff3565b955093505050565b90925061448b91503d8085833e61424e81836103c8565b91386143c2565b61087e8a6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601e60408201527f41413331207061796d6173746572206465706f73697420746f6f206c6f77000060608201520190565b6003111561450a57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b92919061455760409160028652606060208701526060860190611f5f565b930152565b93929190600381101561450a57604091614557918652606060208701526060860190611f5f565b90610416603660405180947f4141353020706f73744f702072657665727465643a200000000000000000000060208301526145c78151809260208686019101611f3c565b81010360168101855201836103c8565b929190925a936000918051916145ec83614df3565b9260a0810195614610875173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff9390848116908161477f57505050614651825173ffffffffffffffffffffffffffffffffffffffff1690565b985b5a90030193840297604084019089825110614712577f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f9461469d6020928c61470d95510390614fa5565b0151948960206146df6146c4865173ffffffffffffffffffffffffffffffffffffffff1690565b9a5173ffffffffffffffffffffffffffffffffffffffff1690565b9401519785604051968796169a16988590949392606092608083019683521515602083015260408201520152565b0390a4565b6040517f220266b60000000000000000000000000000000000000000000000000000000081528061087e600482016080906000815260406020820152602060408201527f414135312070726566756e642062656c6f772061637475616c476173436f737460608201520190565b9a91805161478f575b5050614653565b6060850151600099509091803b156148b65791899189836147e2956040518097819682957fa9a234090000000000000000000000000000000000000000000000000000000084528c029060048401614539565b0393f190816148a3575b5061489e5760016147fb612ba3565b6308c379a01461487f575b614812575b3880614788565b6040517f220266b60000000000000000000000000000000000000000000000000000000081528061087e600482016080906000815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b614887612bc1565b806148925750614806565b6135ba61087e91614583565b61480b565b80610e8a6148b092610398565b386147ec565b8980fd5b9392915a906000928051906148ce82614df3565b9360a08301966148f2885173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff959086811690816149e857505050614933845173ffffffffffffffffffffffffffffffffffffffff1690565b915b5a9003019485029860408301908a82511061498257507f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f94939261469d61470d938c602094510390614fa5565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602060448201527f414135312070726566756e642062656c6f772061637475616c476173436f73746064820152608490fd5b939180516149f8575b5050614935565b606087015160009a509091803b15614b1e57918a918a83614a4b956040518097819682957fa9a234090000000000000000000000000000000000000000000000000000000084528c029060048401614539565b0393f19081614b0b575b50614b06576001614a64612ba3565b6308c379a014614ae9575b614a7b575b38806149f1565b61087e8b6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b614af1612bc1565b80614afc5750614a6f565b6138898d91614583565b614a74565b80610e8a614b1892610398565b38614a55565b8a80fd5b909392915a94805191614b3483614df3565b9260a0810195614b58875173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff938185169182614c4057505050614b98825173ffffffffffffffffffffffffffffffffffffffff1690565b985b5a90030193840297604084019089825110614712577f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f94614be46020928c61470d95510390614fa5565b614bed88614500565b015194896020614c146146c4865173ffffffffffffffffffffffffffffffffffffffff1690565b940151604080519182529815602082015297880152606087015290821695909116939081906080820190565b9a918151614c50575b5050614b9a565b878402614c5c8a614500565b60028a14614ce7576060860151823b1561031d57614caf93600080948d604051978896879586937fa9a234090000000000000000000000000000000000000000000000000000000085526004850161455c565b0393f18015614cda575b614cc7575b505b3880614c49565b80610e8a614cd492610398565b38614cbe565b614ce2612058565b614cb9565b6060860151823b1561031d57614d3293600080948d604051978896879586937fa9a234090000000000000000000000000000000000000000000000000000000085526004850161455c565b0393f19081614de0575b50614ddb576001614d4b612ba3565b6308c379a014614dc8575b15614cc0576040517f220266b60000000000000000000000000000000000000000000000000000000081528061087e600482016080906000815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b614dd0612bc1565b806148925750614d56565b614cc0565b80610e8a614ded92610398565b38614d3c565b60e060c0820151910151808214614e1757480180821015614e12575090565b905090565b5090565b60405190614e28826103ac565b60006040838281528260208201520152565b614e42614e1b565b5065ffffffffffff808260a01c168015614e8e575b60405192614e64846103ac565b73ffffffffffffffffffffffffffffffffffffffff8116845260d01c602084015216604082015290565b5080614e57565b614eaa614eb091614ea4614e1b565b50614e3a565b91614e3a565b9073ffffffffffffffffffffffffffffffffffffffff9182825116928315614f3c575b65ffffffffffff928391826040816020850151169301511693836040816020840151169201511690808410614f34575b50808511614f2c575b5060405195614f1a876103ac565b16855216602084015216604082015290565b935038614f0c565b925038614f03565b815181169350614ed3565b9073ffffffffffffffffffffffffffffffffffffffff614f65612973565b9216600052600060205263ffffffff600160406000206dffffffffffffffffffffffffffff815460781c1685520154166020830152565b61041633615096565b73ffffffffffffffffffffffffffffffffffffffff16600052600060205260406000206dffffffffffffffffffffffffffff80825416928301809311615089575b80831161502b5761041692166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6465706f736974206f766572666c6f77000000000000000000000000000000006044820152fd5b615091612065565b614fe6565b73ffffffffffffffffffffffffffffffffffffffff906150b63482614fa5565b168060005260006020527f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c460206dffffffffffffffffffffffffffff60406000205416604051908152a2565b1561510957565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f6d757374207370656369667920756e7374616b652064656c61790000000000006044820152fd5b1561516e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f63616e6e6f7420646563726561736520756e7374616b652074696d65000000006044820152fd5b156151d357565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6e6f207374616b652073706563696669656400000000000000000000000000006044820152fd5b1561523857565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f7374616b65206f766572666c6f770000000000000000000000000000000000006044820152fd5b9065ffffffffffff60806001610416946152f66dffffffffffffffffffffffffffff86511682906dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b602085015115156eff000000000000000000000000000082549160701b16807fffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffff83161783557fffffff000000000000000000000000000000ffffffffffffffffffffffffffff7cffffffffffffffffffffffffffff000000000000000000000000000000604089015160781b16921617178155019263ffffffff6060820151167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000008554161784550151167fffffffffffffffffffffffffffffffffffffffffffff000000000000ffffffff69ffffffffffff0000000083549260201b169116179055565b1561540157565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f616c726561647920756e7374616b696e670000000000000000000000000000006044820152fd5b91909165ffffffffffff808094169116019182116120a257565b1561548057565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f207374616b6520746f2077697468647261770000000000000000000000006044820152fd5b156154e557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f6d7573742063616c6c20756e6c6f636b5374616b6528292066697273740000006044820152fd5b1561554a57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f5374616b65207769746864726177616c206973206e6f742064756500000000006044820152fd5b156155af57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6661696c656420746f207769746864726177207374616b6500000000000000006044820152fd5b1561561457565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6661696c656420746f20776974686472617700000000000000000000000000006044820152fd5b9060009283809360208451940192f190565b3d6108008082116156ab575b50604051906020818301016040528082526000602083013e90565b90503861569056fea2646970667358221220ae4a26a2417d41eec912cee72664fcf55e9abebe95b0def4d185ac695cb88b5564736f6c634300081100336080806040523461001657610210908161001c8239f35b600080fdfe6080604052600436101561001257600080fd5b6000803560e01c63570e1a361461002857600080fd5b346100c95760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100c95760043567ffffffffffffffff918282116100c957366023830112156100c95781600401359283116100c95736602484840101116100c9576100c561009e84602485016100fc565b60405173ffffffffffffffffffffffffffffffffffffffff90911681529081906020820190565b0390f35b80fd5b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b90806014116101bb5767ffffffffffffffff917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec82018381116101cd575b604051937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f81600b8701160116850190858210908211176101c0575b604052808452602084019036848401116101bb576020946000600c819682946014880187378301015251923560601c5af19060005191156101b557565b60009150565b600080fd5b6101c86100cc565b610178565b6101d56100cc565b61013a56fea26469706673582212201927e80b76ab9b71c952137dd676621a9fdf520c25928815636594036eb1c40364736f6c63430008110033
Deployed Bytecode
0x60806040526004361015610023575b361561001957600080fd5b610021614f9c565b005b60003560e01c80630396cb60146101775780631d7327561461016e5780631fad948c14610165578063205c28781461015c5780634b1d7cf5146101535780635287ce121461014a57806370a08231146101415780638f41ec5a14610138578063957122ab1461012f5780639b249f6914610126578063a61935311461011d578063b760faf914610114578063bb9fe6bf1461010b578063c23a5cea14610102578063d6383f94146100f9578063ee219423146100f05763fc7e286d0361000e576100eb611b0f565b61000e565b506100eb6118f7565b506100eb61178f565b506100eb6115f6565b506100eb611478565b506100eb611439565b506100eb611418565b506100eb611279565b506100eb6110a6565b506100eb61106b565b506100eb610fe6565b506100eb610e96565b506100eb610b6b565b506100eb6109cc565b506100eb61071c565b506100eb610549565b5060207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031d5760043563ffffffff811680820361031d576103187fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c01916102356102053373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b91610211811515615102565b61022e610225600185015463ffffffff1690565b63ffffffff1690565b1115615167565b54926102fa6dffffffffffffffffffffffffffff946102b861025c34888460781c166120aa565b966102688815156151cc565b61027481891115615231565b61029881610280610409565b941684906dffffffffffffffffffffffffffff169052565b6001602084015287166dffffffffffffffffffffffffffff166040830152565b63ffffffff83166060820152600060808201526102f53373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b615296565b6040805194855263ffffffff90911660208501523393918291820190565b0390a2005b600080fd5b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60a0810190811067ffffffffffffffff82111761036e57604052565b610376610322565b604052565b610100810190811067ffffffffffffffff82111761036e57604052565b67ffffffffffffffff811161036e57604052565b6060810190811067ffffffffffffffff82111761036e57604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761036e57604052565b6040519061041682610352565b565b6040519060c0820182811067ffffffffffffffff82111761036e57604052565b604051906040820182811067ffffffffffffffff82111761036e57604052565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f60209267ffffffffffffffff8111610494575b01160190565b61049c610322565b61048e565b9291926104ad82610458565b916104bb60405193846103c8565b82948184528183011161031d578281602093846000960137010152565b73ffffffffffffffffffffffffffffffffffffffff81160361031d57565b60243590610416826104d8565b60c43590610416826104d8565b3590610416826104d8565b9181601f8401121561031d5782359167ffffffffffffffff831161031d576020838186019501011161031d57565b503461031d576101c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031d5767ffffffffffffffff60043581811161031d573660238201121561031d576105ac9036906024816004013591016104a1565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc3601610180811261031d57610100604051916105e983610352565b1261031d576040516105fa8161037b565b6106026104f6565b815260443560208201526064356040820152608435606082015260a435608082015261062c610503565b60a082015260e43560c08201526101043560e082015281526101243560208201526101443560408201526101643560608201526101843560808201526101a43591821161031d576106a09261068861069093369060040161051b565b929091612786565b6040519081529081906020820190565b0390f35b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc83011261031d5760043567ffffffffffffffff9283821161031d578060238301121561031d57816004013593841161031d5760248460051b8301011161031d576024019190602435610719816104d8565b90565b503461031d5761072b366106a4565b610736829392611c6f565b60005b848110610788575060009283915b858310610758576100218585611dac565b90919360019061077e61076c878987611d2e565b6107768886611d0c565b519088612214565b0194019190610747565b6107b36107ac61079a83859795611d0c565b516107a6848987611d2e565b84612fc4565b9190612d9b565b73ffffffffffffffffffffffffffffffffffffffff9291831661095e576108f0576107dd90612d9b565b9116610882576107f257600101929092610739565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602160448201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a490fd5b0390fd5b61087e826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601460408201527f41413334207369676e6174757265206572726f7200000000000000000000000060608201520190565b61087e836040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601760408201527f414132322065787069726564206f72206e6f742064756500000000000000000060608201520190565b61087e846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601460408201527f41413234207369676e6174757265206572726f7200000000000000000000000060608201520190565b503461031d5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031d57600435610a08816104d8565b6024359060009133835282602052604083206dffffffffffffffffffffffffffff81541692838311610b0d57848373ffffffffffffffffffffffffffffffffffffffff829593610ab08496610a77610a648798610b0a9c612095565b6dffffffffffffffffffffffffffff1690565b6dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b6040805173ffffffffffffffffffffffffffffffffffffffff831681526020810185905233917fd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb91a2165af1610b04611d7c565b5061560d565b80f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f576974686472617720616d6f756e7420746f6f206c61726765000000000000006044820152fd5b503461031d57610b7a366106a4565b6000805b838210610d3c57610b8f9150611c6f565b6000805b848110610ca257505060008093815b818110610bd957610021868660007f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d8180a2611dac565b610c3d610be782848a6123a0565b610c12610bf9610bf960208401612442565b73ffffffffffffffffffffffffffffffffffffffff1690565b7f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d600080a2806123ee565b906000915b808310610c5a57505050610c5590612366565b610ba2565b90919497610c95610c8f610c9b92610c898c8b610c8282610c7c8e8b8d611d2e565b92611d0c565b5191612214565b906120aa565b99612366565b95612366565b9190610c42565b610cad8186886123a0565b6020610cc5610cbc83806123ee565b92909301612442565b9173ffffffffffffffffffffffffffffffffffffffff60009316905b828410610cfa5750505050610cf590612366565b610b93565b90919294610c9581610d2f85610d28610d16610d34968d611d0c565b51610d228c8b8a611d2e565b85612fc4565b908b612d53565b612366565b929190610ce1565b610d478285876123a0565b90610d5282806123ee565b92610d62610bf960208301612442565b9173ffffffffffffffffffffffffffffffffffffffff8316610d87600182141561244c565b610da8575b505050610da291610d9c916120aa565b91612366565b90610b7e565b909592610dc16040999693999895989788810190611e9d565b92908a3b1561031d5789938b918a5193849283927fe3563a4f00000000000000000000000000000000000000000000000000000000845260049e8f850193610e08946125e6565b03815a93600094fa9081610e7d575b50610e675786517f86a9f75000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a16818a0190815281906020010390fd5b9497509295509093509181610d9c610da2610d8c565b80610e8a610e9092610398565b80611060565b38610e17565b503461031d5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031d576106a073ffffffffffffffffffffffffffffffffffffffff600435610eea816104d8565b608060409283928351610efc81610352565b600093818580935282602082015282878201528260608201520152168152806020522090610f8b65ffffffffffff6001835194610f3886610352565b80546dffffffffffffffffffffffffffff8082168852607082901c60ff161515602089015260789190911c1685870152015463ffffffff8116606086015260201c16608084019065ffffffffffff169052565b5191829182919091608065ffffffffffff8160a08401956dffffffffffffffffffffffffffff808251168652602082015115156020870152604082015116604086015263ffffffff6060820151166060860152015116910152565b503461031d5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031d5773ffffffffffffffffffffffffffffffffffffffff600435611037816104d8565b16600052600060205260206dffffffffffffffffffffffffffff60406000205416604051908152f35b600091031261031d57565b503461031d5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031d57602060405160018152f35b503461031d5760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031d57600467ffffffffffffffff813581811161031d576110f7903690840161051b565b905060243591611106836104d8565b60443590811161031d5761111d903690850161051b565b92909115908161126f575b50611208576014821015611178575b61087e836040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160409060208152600060208201520190565b6111886111949261118e926129ab565b906129b9565b60601c90565b3b156111a1573880611137565b61087e906040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160609060208152601b60208201527f41413330207061796d6173746572206e6f74206465706c6f796564000000000060408201520190565b61087e836040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160609060208152601960208201527f41413230206163636f756e74206e6f74206465706c6f7965640000000000000060408201520190565b90503b1538611128565b503461031d5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031d5760043567ffffffffffffffff811161031d576112cb602491369060040161051b565b906113016040519283927f570e1a3600000000000000000000000000000000000000000000000000000000845260048401612b4f565b0360208273ffffffffffffffffffffffffffffffffffffffff92816000857f000000000000000000000000932a3a220ac2cd48fab18118954601f565f19681165af19182156113b3575b600092611383575b50604051917f6ca7b806000000000000000000000000000000000000000000000000000000008352166004820152fd5b6113a591925060203d81116113ac575b61139d81836103c8565b810190612b3a565b9038611353565b503d611393565b6113bb612058565b61134b565b908161016091031261031d5790565b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82011261031d576004359067ffffffffffffffff821161031d57610719916004016113c0565b503461031d57602061143161142c366113cf565b6128e1565b604051908152f35b5060207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031d57610021600435611473816104d8565b615096565b503461031d576000807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126115f3573381528060205260408120600181019063ffffffff825416908115611595576115326114f761155a936114e96114e4855460ff9060701c1690565b6153fa565b65ffffffffffff421661545f565b84547fffffffffffffffffffffffffffffffffffffffffffff000000000000ffffffff16602082901b69ffffffffffff000000001617909455565b7fffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffff8154169055565b60405165ffffffffffff91909116815233907ffa9b3c14cc825c412c9ed81b3ba365a5b459439403f18829e572ed53a4180f0a90602090a280f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f6e6f74207374616b6564000000000000000000000000000000000000000000006044820152fd5b80fd5b503461031d5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031d57600435611632816104d8565b610b0a73ffffffffffffffffffffffffffffffffffffffff6116743373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b9261172c611697610a6486546dffffffffffffffffffffffffffff9060781c1690565b946116a3861515615479565b611704600182016116dc65ffffffffffff6116c8835465ffffffffffff9060201c1690565b166116d48115156154de565b421015615543565b80547fffffffffffffffffffffffffffffffffffffffffffff00000000000000000000169055565b7fffffff0000000000000000000000000000ffffffffffffffffffffffffffffff8154169055565b6040805173ffffffffffffffffffffffffffffffffffffffff831681526020810186905233917fb7c918e0e249f999e965cafeb6c664271b3f4317d296461500e71da39f0cbda391a2600080809581948294165af1611789611d7c565b506155a8565b503461031d5760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031d5767ffffffffffffffff60043581811161031d576117e09036906004016113c0565b602435916117ed836104d8565b60443590811161031d5761180861087e91369060040161051b565b611810611bec565b61181985612c4e565b61182c6118268287612e5c565b90614e95565b9461183c826000924384526120b7565b96438252819360609573ffffffffffffffffffffffffffffffffffffffff83166118c3575b5050505060800151936118906040611882602084015165ffffffffffff1690565b92015165ffffffffffff1690565b906040519687967f8b7ac980000000000000000000000000000000000000000000000000000000008852600488016126b6565b839550839496506118dd60409492939451809481936126a8565b03925af19060806118ec611d7c565b929190388080611861565b503461031d57611906366113cf565b61190e611bec565b61191782612c4e565b6119218183612e5c565b825160a0015191939161194e9073ffffffffffffffffffffffffffffffffffffffff16614f47565b614f47565b90611972611949855173ffffffffffffffffffffffffffffffffffffffff90511690565b9461197b612973565b506119aa61198e60409586810190611e9d565b90600060148310611b0757506111886119499261118e926129ab565b916119b491614e95565b805173ffffffffffffffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff821660018114916080880151978781015191886020820151611a099065ffffffffffff1690565b91015165ffffffffffff16916060015192611a22610418565b9a8b5260208b0152841515898b015265ffffffffffff1660608a015265ffffffffffff16608089015260a088015215159081611afe575b50611a93575061087e92519485947fe0cff05f00000000000000000000000000000000000000000000000000000000865260048601612ae0565b919061087e93611aa284614f47565b611ac9611aad610438565b73ffffffffffffffffffffffffffffffffffffffff9096168652565b6020850152519586957ffaecb4e400000000000000000000000000000000000000000000000000000000875260048701612a4e565b90501538611a59565b915050614f47565b503461031d5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031d5773ffffffffffffffffffffffffffffffffffffffff600435611b60816104d8565b16600052600060205260a0604060002065ffffffffffff60018254920154604051926dffffffffffffffffffffffffffff90818116855260ff8160701c161515602086015260781c16604084015263ffffffff8116606084015260201c166080820152f35b60209067ffffffffffffffff8111611bdf575b60051b0190565b611be7610322565b611bd8565b60405190611bf982610352565b604051608083610100830167ffffffffffffffff811184821017611c62575b60405260009283815283602082015283604082015283606082015283838201528360a08201528360c08201528360e082015281528260208201528260408201528260608201520152565b611c6a610322565b611c18565b90611c7982611bc5565b611c8660405191826103c8565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0611cb48294611bc5565b019060005b828110611cc557505050565b602090611cd0611bec565b82828501015201611cb9565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020918151811015611d21575b60051b010190565b611d29611cdc565b611d19565b9190811015611d6f575b60051b810135907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea18136030182121561031d570190565b611d77611cdc565b611d38565b3d15611da7573d90611d8d82610458565b91611d9b60405193846103c8565b82523d6000602084013e565b606090565b73ffffffffffffffffffffffffffffffffffffffff168015611e3f57600080809381935af1611dd9611d7c565b5015611de157565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f41413931206661696c65642073656e6420746f2062656e6566696369617279006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4141393020696e76616c69642062656e656669636961727900000000000000006044820152fd5b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561031d570180359067ffffffffffffffff821161031d5760200191813603831361031d57565b9081602091031261031d575190565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b60005b838110611f4f5750506000910152565b8181015183820152602001611f3f565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f602093611f9b81518092818752878088019101611f3c565b0116010190565b90611fbc60809161071996946101c0808652850191611efd565b9360e0815173ffffffffffffffffffffffffffffffffffffffff80825116602087015260208201516040870152604082015160608701526060820151858701528482015160a087015260a08201511660c086015260c081015182860152015161010084015260208101516101208401526040810151610140840152606081015161016084015201516101808201526101a0818403910152611f5f565b506040513d6000823e3d90fd5b507f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b919082039182116120a257565b610416612065565b919082018092116120a257565b905a918160206120d06060830151936060810190611e9d565b906121098560405195869485947f1d73275600000000000000000000000000000000000000000000000000000000865260048601611fa2565b03816000305af1600091816121e4575b506121dd575060206000803e7fdeaddead00000000000000000000000000000000000000000000000000000000600051146121705761216a61215f610719945a90612095565b6080840151906120aa565b916145d7565b6040517f220266b60000000000000000000000000000000000000000000000000000000081528061087e600482016080906000815260406020820152600f60408201527f41413935206f7574206f6620676173000000000000000000000000000000000060608201520190565b9250505090565b61220691925060203d811161220d575b6121fe81836103c8565b810190611eee565b9038612119565b503d6121f4565b909291925a938060206122306060830151946060810190611e9d565b906122698660405195869485947f1d73275600000000000000000000000000000000000000000000000000000000865260048601611fa2565b03816000305af160009181612346575b5061233f575060206000803e7fdeaddead00000000000000000000000000000000000000000000000000000000600051146122d1576122cb6122c061071995965a90612095565b6080830151906120aa565b926148ba565b61087e836040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152600f60408201527f41413935206f7574206f6620676173000000000000000000000000000000000060608201520190565b9450505050565b61235f91925060203d811161220d576121fe81836103c8565b9038612279565b6001907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114612394570190565b61239c612065565b0190565b91908110156123e1575b60051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa18136030182121561031d570190565b6123e9611cdc565b6123aa565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561031d570180359067ffffffffffffffff821161031d57602001918160051b3603831361031d57565b35610719816104d8565b1561245357565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393620696e76616c69642061676772656761746f720000000000000000006044820152fd5b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18236030181121561031d57016020813591019167ffffffffffffffff821161031d57813603831361031d57565b6107199161252c8161251284610510565b73ffffffffffffffffffffffffffffffffffffffff169052565b602082013560208201526125c761257861255d61254c60408601866124b1565b610160806040880152860191611efd565b61256a60608601866124b1565b908583036060870152611efd565b6080840135608084015260a084013560a084015260c084013560c084015260e084013560e084015261010080850135908401526101206125ba818601866124b1565b9185840390860152611efd565b916125d861014091828101906124b1565b929091818503910152611efd565b949391929083604087016040885252606086019360608160051b8801019482600090815b8483106126295750505050505084602061071995968503910152611efd565b9091929394977fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08b820301855288357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea1843603018112156126a457600191846126929201612501565b9860209081019695019301919061260a565b8280fd5b908092918237016000815290565b92909361071996959260c0958552602085015265ffffffffffff8092166040850152166060830152151560808201528160a08201520190611f5f565b156126f957565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393220696e7465726e616c2063616c6c206f6e6c790000000000000000006044820152fd5b90604061071992600081528160208201520190611f5f565b604090610719939281528160208201520190611f5f565b909291925a936127973033146126f2565b8151946040860151955a6113886060830151890101116128b7576107199660009580516127de575b505050906127d8915a90036080840151019436916104a1565b91614b22565b61280d9161280991612804855173ffffffffffffffffffffffffffffffffffffffff1690565b615672565b1590565b612819575b80806127bf565b6127d892919450612828615684565b90815161283c575b50506001939091612812565b7f1c4fada7374c0a9ee8841fc38afe82932dc0f8e69012e927f061a8bae611a20173ffffffffffffffffffffffffffffffffffffffff6020870151926128ad602061289b835173ffffffffffffffffffffffffffffffffffffffff1690565b9201519560405193849316968361276f565b0390a33880612830565b7fdeaddead0000000000000000000000000000000000000000000000000000000060005260206000fd5b806128f0610140820182611e9d565b50037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081016040519182016040528082526020820192833751902060405160208101918252306040820152466060820152606081526080810181811067ffffffffffffffff821117612966575b60405251902090565b61296e610322565b61295d565b604051906040820182811067ffffffffffffffff82111761299e575b60405260006020838281520152565b6129a6610322565b61298f565b9060141161031d5790601490565b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000090358181169392601481106129ee57505050565b60140360031b82901b16169150565b9060c060a061071993805184526020810151602085015260408101511515604085015265ffffffffffff80606083015116606086015260808201511660808501520151918160a08201520190611f5f565b9294612aaf61041695612a9d610100959998612a8b612a77602097610140808c528b01906129fd565b9b878a019060208091805184520151910152565b80516060890152602001516080880152565b805160a08701526020015160c0860152565b73ffffffffffffffffffffffffffffffffffffffff81511660e0850152015191019060208091805184520151910152565b612b2961041694612b17612b0260a0959998969960e0865260e08601906129fd565b98602085019060208091805184520151910152565b80516060840152602001516080830152565b019060208091805184520151910152565b9081602091031261031d5751610719816104d8565b916020610719938181520191611efd565b90612b8f73ffffffffffffffffffffffffffffffffffffffff9161071997959694606085526060850191611efd565b941660208201526040818503910152611efd565b60009060033d11612bb057565b905060046000803e60005160e01c90565b600060443d10610719576040517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc91823d016004833e815167ffffffffffffffff918282113d602484011117612c3d57818401948551938411612c45573d85010160208487010111612c3d5750610719929101602001906103c8565b949350505050565b50949350505050565b612c5b6040820182611e9d565b612c73612c6784612442565b93610120810190611e9d565b9290303b1561031d57600093612cb79160405196879586957f957122ab00000000000000000000000000000000000000000000000000000000875260048701612b60565b0381305afa9081612d40575b50610416576001612cd2612ba3565b6308c379a014612ceb575b612ce357565b610416612058565b612cf3612bc1565b80612cff575b50612cdd565b80516000925015612cf95761087e906040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301612757565b80610e8a612d4d92610398565b38612cc3565b929190612d5f90612d9b565b909273ffffffffffffffffffffffffffffffffffffffff8080951691160361095e576108f057612d8e90612d9b565b9116610882576107f25750565b8015612dee57612daa90614e3a565b73ffffffffffffffffffffffffffffffffffffffff65ffffffffffff806040840151164211908115612dde575b5091511691565b9050602083015116421038612dd7565b50600090600090565b15612dfe57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f41413934206761732076616c756573206f766572666c6f7700000000000000006044820152fd5b916000915a93815190612e6f828261318e565b612e78816128e1565b6020840152612eb66effffffffffffffffffffffffffffff60808401516060850151176040850151176101008401359060e085013517171115612df7565b612ebf82613250565b612eca818584613311565b9790612ed543600052565b73ffffffffffffffffffffffffffffffffffffffff612f0d60a0606097015173ffffffffffffffffffffffffffffffffffffffff1690565b16612faa575b505a810360a084013510612f3d5760809360c092604087015260608601525a900391013501910152565b6040517f220266b60000000000000000000000000000000000000000000000000000000081528061087e600482016080906000815260406020820152601e60408201527f41413430206f76657220766572696669636174696f6e4761734c696d6974000060608201520190565b90935081612fbb9297508584614037565b95909238612f13565b9290916000925a8251612fd7818461318e565b612fe0836128e1565b602085015261301e6effffffffffffffffffffffffffffff60808301516060840151176040840151176101008601359060e087013517171115612df7565b61302781613250565b6130338186868b61367d565b989061303e43600052565b73ffffffffffffffffffffffffffffffffffffffff61307660a0606096015173ffffffffffffffffffffffffffffffffffffffff1690565b1661310e575b505a840360a0860135106130a85750604085015260608401526080919060c0905a900391013501910152565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601e60448201527f41413430206f76657220766572696669636174696f6e4761734c696d697400006064820152608490fd5b909250816131209298508686856142ca565b9690913861307c565b1561313057565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4141393320696e76616c6964207061796d6173746572416e64446174610000006044820152fd5b613200906131b861319e82612442565b73ffffffffffffffffffffffffffffffffffffffff168452565b602081013560208401526080810135604084015260a0810135606084015260c0810135608084015260e081013560c084015261010081013560e0840152610120810190611e9d565b9081156132455761322a61118e6111888460a094613225601461041699981015613129565b6129ab565b73ffffffffffffffffffffffffffffffffffffffff16910152565b505060a06000910152565b60a081015173ffffffffffffffffffffffffffffffffffffffff16156132925760c060035b60ff60408401519116606084015102016080830151019101510290565b60c06001613275565b6132b360409295949395606083526060830190612501565b9460208201520152565b90610416602f60405180947f414132332072657665727465643a20000000000000000000000000000000000060208301526133018151809260208686019101611f3c565b810103600f8101855201836103c8565b916000926000925a936133df6020835193613340855173ffffffffffffffffffffffffffffffffffffffff1690565b956133586133516040830183611e9d565b90846138e8565b60a086015173ffffffffffffffffffffffffffffffffffffffff169061337d43600052565b85809373ffffffffffffffffffffffffffffffffffffffff809416159889613615575b60600151908601516040517f3a871cdd00000000000000000000000000000000000000000000000000000000815297889687958693906004850161329b565b03938a1690f18291816135f5575b506135ec57506001906133fe612ba3565b6308c379a014613598575b5061352b575b61341c575b50505a900391565b6134469073ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b613461610a6482546dffffffffffffffffffffffffffff1690565b8083116134be576134b7926dffffffffffffffffffffffffffff9103166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b3880613414565b6040517f220266b60000000000000000000000000000000000000000000000000000000081528061087e600482016080906000815260406020820152601760408201527f41413231206469646e2774207061792070726566756e6400000000000000000060608201520190565b6040517f220266b60000000000000000000000000000000000000000000000000000000081528061087e600482016080906000815260406020820152601660408201527f4141323320726576657274656420286f72204f4f47290000000000000000000060608201520190565b6135a0612bc1565b90816135ac5750613409565b61087e916135ba91506132bd565b6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301612757565b955061340f9050565b61360e91925060203d811161220d576121fe81836103c8565b90386133ed565b945061365b610a646136478c73ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b546dffffffffffffffffffffffffffff1690565b8b8111156136725750856060835b969150506133a0565b606087918d03613669565b90926000936000935a946136c660208351936136ad855173ffffffffffffffffffffffffffffffffffffffff1690565b956133586136be6040830183611e9d565b90848c613c06565b03938a1690f18291816138c8575b506138bf57506001906136e5612ba3565b6308c379a014613869575b506137fb575b613704575b5050505a900391565b61372e9073ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b9161374a610a6484546dffffffffffffffffffffffffffff1690565b90818311613795575082547fffffffffffffffffffffffffffffffffffff0000000000000000000000000000169190036dffffffffffffffffffffffffffff161790553880806136fb565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601760448201527f41413231206469646e2774207061792070726566756e640000000000000000006064820152608490fd5b61087e846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601660408201527f4141323320726576657274656420286f72204f4f47290000000000000000000060608201520190565b613871612bc1565b908161387d57506136f0565b869161388991506132bd565b9061087e6040519283927f220266b60000000000000000000000000000000000000000000000000000000084526004840161276f565b96506136f69050565b6138e191925060203d811161220d576121fe81836103c8565b90386136d4565b9091806138f457505050565b81515173ffffffffffffffffffffffffffffffffffffffff1692833b613b9957606083510151604051907f570e1a3600000000000000000000000000000000000000000000000000000000825260208280613953878760048401612b4f565b0381600073ffffffffffffffffffffffffffffffffffffffff95867f000000000000000000000000932a3a220ac2cd48fab18118954601f565f196811690f1918215613b8c575b600092613b6c575b50808216958615613aff5716809503613a92573b15613a255761118e6111887fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d936139ec936129ab565b602083810151935160a001516040805173ffffffffffffffffffffffffffffffffffffffff9485168152939091169183019190915290a3565b6040517f220266b60000000000000000000000000000000000000000000000000000000081528061087e600482016080906000815260406020820152602060408201527f4141313520696e6974436f6465206d757374206372656174652073656e64657260608201520190565b6040517f220266b60000000000000000000000000000000000000000000000000000000081528061087e600482016080906000815260406020820152602060408201527f4141313420696e6974436f6465206d7573742072657475726e2073656e64657260608201520190565b6040517f220266b60000000000000000000000000000000000000000000000000000000081528061087e600482016080906000815260406020820152601b60408201527f4141313320696e6974436f6465206661696c6564206f72204f4f47000000000060608201520190565b613b8591925060203d81116113ac5761139d81836103c8565b90386139a2565b613b94612058565b61399a565b6040517f220266b60000000000000000000000000000000000000000000000000000000081528061087e600482016080906000815260406020820152601f60408201527f414131302073656e64657220616c726561647920636f6e73747275637465640060608201520190565b92909181613c15575b50505050565b82515173ffffffffffffffffffffffffffffffffffffffff1693843b613ebd57606084510151604051907f570e1a3600000000000000000000000000000000000000000000000000000000825260208280613c74888860048401612b4f565b0381600073ffffffffffffffffffffffffffffffffffffffff95867f000000000000000000000000932a3a220ac2cd48fab18118954601f565f196811690f1918215613eb0575b600092613e90575b50808216968715613e225716809603613db4573b15613d4e575061118e6111887fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d93613d0e936129ab565b602083810151935160a001516040805173ffffffffffffffffffffffffffffffffffffffff9485168152939091169183019190915290a338808080613c0f565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602060448201527f4141313520696e6974436f6465206d757374206372656174652073656e6465726064820152608490fd5b61087e826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152602060408201527f4141313420696e6974436f6465206d7573742072657475726e2073656e64657260608201520190565b61087e846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601b60408201527f4141313320696e6974436f6465206661696c6564206f72204f4f47000000000060608201520190565b613ea991925060203d81116113ac5761139d81836103c8565b9038613cc3565b613eb8612058565b613cbb565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601f60448201527f414131302073656e64657220616c726561647920636f6e7374727563746564006064820152608490fd5b15613f2a57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4141343120746f6f206c6974746c6520766572696669636174696f6e476173006044820152fd5b919060408382031261031d57825167ffffffffffffffff811161031d5783019080601f8301121561031d57815191613fbf83610458565b91613fcd60405193846103c8565b8383526020848301011161031d57602092613fed91848085019101611f3c565b92015190565b90610416602f60405180947f414133332072657665727465643a20000000000000000000000000000000000060208301526133018151809260208686019101611f3c565b93919260609460009460009380519261407660a08a8601519561405b888811613f23565b015173ffffffffffffffffffffffffffffffffffffffff1690565b916140a18373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b946140bd610a6487546dffffffffffffffffffffffffffff1690565b9685881061425d5773ffffffffffffffffffffffffffffffffffffffff60208a98946141338a966dffffffffffffffffffffffffffff8b61416c9e03166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b015194604051998a98899788937ff465c77e0000000000000000000000000000000000000000000000000000000085526004850161329b565b0395169103f1908183918493614237575b5061423057505060019061418f612ba3565b6308c379a01461420e575b506141a157565b6040517f220266b60000000000000000000000000000000000000000000000000000000081528061087e600482016080906000815260406020820152601660408201527f4141333320726576657274656420286f72204f4f47290000000000000000000060608201520190565b614216612bc1565b9081614222575061419a565b61087e916135ba9150613ff3565b9450925050565b90925061425691503d8085833e61424e81836103c8565b810190613f88565b913861417d565b6040517f220266b60000000000000000000000000000000000000000000000000000000081528061087e600482016080906000815260406020820152601e60408201527f41413331207061796d6173746572206465706f73697420746f6f206c6f77000060608201520190565b9194929390936060956000956000938251906142f160a08b8401519361405b848611613f23565b9361431c8573ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b614337610a6482546dffffffffffffffffffffffffffff1690565b878110614492579273ffffffffffffffffffffffffffffffffffffffff60208a989693946141338a966dffffffffffffffffffffffffffff8d6143b19e9c9a03166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b0395169103f1908183918493614474575b5061446c5750506001906143d4612ba3565b6308c379a01461444d575b506143e75750565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601660448201527f4141333320726576657274656420286f72204f4f4729000000000000000000006064820152608490fd5b614455612bc1565b908161446157506143df565b613889925050613ff3565b955093505050565b90925061448b91503d8085833e61424e81836103c8565b91386143c2565b61087e8a6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601e60408201527f41413331207061796d6173746572206465706f73697420746f6f206c6f77000060608201520190565b6003111561450a57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b92919061455760409160028652606060208701526060860190611f5f565b930152565b93929190600381101561450a57604091614557918652606060208701526060860190611f5f565b90610416603660405180947f4141353020706f73744f702072657665727465643a200000000000000000000060208301526145c78151809260208686019101611f3c565b81010360168101855201836103c8565b929190925a936000918051916145ec83614df3565b9260a0810195614610875173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff9390848116908161477f57505050614651825173ffffffffffffffffffffffffffffffffffffffff1690565b985b5a90030193840297604084019089825110614712577f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f9461469d6020928c61470d95510390614fa5565b0151948960206146df6146c4865173ffffffffffffffffffffffffffffffffffffffff1690565b9a5173ffffffffffffffffffffffffffffffffffffffff1690565b9401519785604051968796169a16988590949392606092608083019683521515602083015260408201520152565b0390a4565b6040517f220266b60000000000000000000000000000000000000000000000000000000081528061087e600482016080906000815260406020820152602060408201527f414135312070726566756e642062656c6f772061637475616c476173436f737460608201520190565b9a91805161478f575b5050614653565b6060850151600099509091803b156148b65791899189836147e2956040518097819682957fa9a234090000000000000000000000000000000000000000000000000000000084528c029060048401614539565b0393f190816148a3575b5061489e5760016147fb612ba3565b6308c379a01461487f575b614812575b3880614788565b6040517f220266b60000000000000000000000000000000000000000000000000000000081528061087e600482016080906000815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b614887612bc1565b806148925750614806565b6135ba61087e91614583565b61480b565b80610e8a6148b092610398565b386147ec565b8980fd5b9392915a906000928051906148ce82614df3565b9360a08301966148f2885173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff959086811690816149e857505050614933845173ffffffffffffffffffffffffffffffffffffffff1690565b915b5a9003019485029860408301908a82511061498257507f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f94939261469d61470d938c602094510390614fa5565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602060448201527f414135312070726566756e642062656c6f772061637475616c476173436f73746064820152608490fd5b939180516149f8575b5050614935565b606087015160009a509091803b15614b1e57918a918a83614a4b956040518097819682957fa9a234090000000000000000000000000000000000000000000000000000000084528c029060048401614539565b0393f19081614b0b575b50614b06576001614a64612ba3565b6308c379a014614ae9575b614a7b575b38806149f1565b61087e8b6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b614af1612bc1565b80614afc5750614a6f565b6138898d91614583565b614a74565b80610e8a614b1892610398565b38614a55565b8a80fd5b909392915a94805191614b3483614df3565b9260a0810195614b58875173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff938185169182614c4057505050614b98825173ffffffffffffffffffffffffffffffffffffffff1690565b985b5a90030193840297604084019089825110614712577f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f94614be46020928c61470d95510390614fa5565b614bed88614500565b015194896020614c146146c4865173ffffffffffffffffffffffffffffffffffffffff1690565b940151604080519182529815602082015297880152606087015290821695909116939081906080820190565b9a918151614c50575b5050614b9a565b878402614c5c8a614500565b60028a14614ce7576060860151823b1561031d57614caf93600080948d604051978896879586937fa9a234090000000000000000000000000000000000000000000000000000000085526004850161455c565b0393f18015614cda575b614cc7575b505b3880614c49565b80610e8a614cd492610398565b38614cbe565b614ce2612058565b614cb9565b6060860151823b1561031d57614d3293600080948d604051978896879586937fa9a234090000000000000000000000000000000000000000000000000000000085526004850161455c565b0393f19081614de0575b50614ddb576001614d4b612ba3565b6308c379a014614dc8575b15614cc0576040517f220266b60000000000000000000000000000000000000000000000000000000081528061087e600482016080906000815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b614dd0612bc1565b806148925750614d56565b614cc0565b80610e8a614ded92610398565b38614d3c565b60e060c0820151910151808214614e1757480180821015614e12575090565b905090565b5090565b60405190614e28826103ac565b60006040838281528260208201520152565b614e42614e1b565b5065ffffffffffff808260a01c168015614e8e575b60405192614e64846103ac565b73ffffffffffffffffffffffffffffffffffffffff8116845260d01c602084015216604082015290565b5080614e57565b614eaa614eb091614ea4614e1b565b50614e3a565b91614e3a565b9073ffffffffffffffffffffffffffffffffffffffff9182825116928315614f3c575b65ffffffffffff928391826040816020850151169301511693836040816020840151169201511690808410614f34575b50808511614f2c575b5060405195614f1a876103ac565b16855216602084015216604082015290565b935038614f0c565b925038614f03565b815181169350614ed3565b9073ffffffffffffffffffffffffffffffffffffffff614f65612973565b9216600052600060205263ffffffff600160406000206dffffffffffffffffffffffffffff815460781c1685520154166020830152565b61041633615096565b73ffffffffffffffffffffffffffffffffffffffff16600052600060205260406000206dffffffffffffffffffffffffffff80825416928301809311615089575b80831161502b5761041692166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6465706f736974206f766572666c6f77000000000000000000000000000000006044820152fd5b615091612065565b614fe6565b73ffffffffffffffffffffffffffffffffffffffff906150b63482614fa5565b168060005260006020527f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c460206dffffffffffffffffffffffffffff60406000205416604051908152a2565b1561510957565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f6d757374207370656369667920756e7374616b652064656c61790000000000006044820152fd5b1561516e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f63616e6e6f7420646563726561736520756e7374616b652074696d65000000006044820152fd5b156151d357565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6e6f207374616b652073706563696669656400000000000000000000000000006044820152fd5b1561523857565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f7374616b65206f766572666c6f770000000000000000000000000000000000006044820152fd5b9065ffffffffffff60806001610416946152f66dffffffffffffffffffffffffffff86511682906dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b602085015115156eff000000000000000000000000000082549160701b16807fffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffff83161783557fffffff000000000000000000000000000000ffffffffffffffffffffffffffff7cffffffffffffffffffffffffffff000000000000000000000000000000604089015160781b16921617178155019263ffffffff6060820151167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000008554161784550151167fffffffffffffffffffffffffffffffffffffffffffff000000000000ffffffff69ffffffffffff0000000083549260201b169116179055565b1561540157565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f616c726561647920756e7374616b696e670000000000000000000000000000006044820152fd5b91909165ffffffffffff808094169116019182116120a257565b1561548057565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f207374616b6520746f2077697468647261770000000000000000000000006044820152fd5b156154e557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f6d7573742063616c6c20756e6c6f636b5374616b6528292066697273740000006044820152fd5b1561554a57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f5374616b65207769746864726177616c206973206e6f742064756500000000006044820152fd5b156155af57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6661696c656420746f207769746864726177207374616b6500000000000000006044820152fd5b1561561457565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6661696c656420746f20776974686472617700000000000000000000000000006044820152fd5b9060009283809360208451940192f190565b3d6108008082116156ab575b50604051906020818301016040528082526000602083013e90565b90503861569056fea2646970667358221220ae4a26a2417d41eec912cee72664fcf55e9abebe95b0def4d185ac695cb88b5564736f6c63430008110033
Loading...
Loading
[ Download: CSV Export ]
[ 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.