Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multichain Info
N/A
Latest 25 from a total of 240 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Create Session | 4593931 | 2 hrs ago | IN | 0 ETH | 0.00000972 | ||||
Create Session | 4588987 | 3 hrs ago | IN | 0 ETH | 0.00000833 | ||||
Create Session | 4586703 | 4 hrs ago | IN | 0 ETH | 0.00000922 | ||||
Create Session | 4586183 | 4 hrs ago | IN | 0 ETH | 0.00001073 | ||||
Create Session | 4585956 | 4 hrs ago | IN | 0 ETH | 0.00001121 | ||||
Create Session | 4585376 | 4 hrs ago | IN | 0 ETH | 0.00000914 | ||||
Create Session | 4584359 | 5 hrs ago | IN | 0 ETH | 0.00000692 | ||||
Create Session | 4584241 | 5 hrs ago | IN | 0 ETH | 0.00000692 | ||||
Create Session | 4583979 | 5 hrs ago | IN | 0 ETH | 0.00000812 | ||||
Create Session | 4583932 | 5 hrs ago | IN | 0 ETH | 0.00000947 | ||||
Create Session | 4583713 | 5 hrs ago | IN | 0 ETH | 0.00000585 | ||||
Create Session | 4583526 | 5 hrs ago | IN | 0 ETH | 0.00000585 | ||||
Create Session | 4583471 | 5 hrs ago | IN | 0 ETH | 0.00000687 | ||||
Create Session | 4580151 | 6 hrs ago | IN | 0 ETH | 0.00000515 | ||||
Create Session | 4573356 | 8 hrs ago | IN | 0 ETH | 0.00000503 | ||||
Create Session | 4573309 | 8 hrs ago | IN | 0 ETH | 0.00000629 | ||||
Create Session | 4568155 | 10 hrs ago | IN | 0 ETH | 0.00000681 | ||||
Create Session | 4565036 | 10 hrs ago | IN | 0 ETH | 0.0000109 | ||||
Create Session | 4564521 | 11 hrs ago | IN | 0 ETH | 0.0000097 | ||||
Create Session | 4563569 | 11 hrs ago | IN | 0 ETH | 0.00000641 | ||||
Create Session | 4563334 | 11 hrs ago | IN | 0 ETH | 0.00000644 | ||||
Create Session | 4563173 | 11 hrs ago | IN | 0 ETH | 0.00000641 | ||||
Create Session | 4563149 | 11 hrs ago | IN | 0 ETH | 0.00000641 | ||||
Create Session | 4562837 | 11 hrs ago | IN | 0 ETH | 0.00000752 | ||||
Create Session | 4562379 | 11 hrs ago | IN | 0 ETH | 0.00000641 |
Latest 25 internal transactions (View All)
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
4601172 | 9 secs ago | 0 ETH | ||||
4601172 | 9 secs ago | 0 ETH | ||||
4601172 | 9 secs ago | 0 ETH | ||||
4601172 | 9 secs ago | 0 ETH | ||||
4601172 | 9 secs ago | 0 ETH | ||||
4601172 | 9 secs ago | 0 ETH | ||||
4601172 | 9 secs ago | 0 ETH | ||||
4601172 | 9 secs ago | 0 ETH | ||||
4601172 | 9 secs ago | 0 ETH | ||||
4601172 | 9 secs ago | 0 ETH | ||||
4601172 | 9 secs ago | 0 ETH | ||||
4601172 | 9 secs ago | 0 ETH | ||||
4601171 | 10 secs ago | 0 ETH | ||||
4601171 | 10 secs ago | 0 ETH | ||||
4601171 | 10 secs ago | 0 ETH | ||||
4601171 | 10 secs ago | 0 ETH | ||||
4601171 | 10 secs ago | 0 ETH | ||||
4601171 | 10 secs ago | 0 ETH | ||||
4601171 | 10 secs ago | 0 ETH | ||||
4601171 | 10 secs ago | 0 ETH | ||||
4601171 | 10 secs ago | 0 ETH | ||||
4601171 | 10 secs ago | 0 ETH | ||||
4601171 | 10 secs ago | 0 ETH | ||||
4601171 | 10 secs ago | 0 ETH | ||||
4601169 | 12 secs ago | 0 ETH |
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
SessionKeyValidator
Compiler Version
v0.8.26+commit.8a97fa7a
ZkSolc Version
v1.5.6
Optimization Enabled:
Yes with Mode 3
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; import { EnumerableSet } from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import { IModule } from "../interfaces/IModule.sol"; import { IValidationHook } from "../interfaces/IHook.sol"; import { IModuleValidator } from "../interfaces/IModuleValidator.sol"; import { OperationType } from "../interfaces/IValidator.sol"; import { Transaction } from "@matterlabs/zksync-contracts/l2/system-contracts/libraries/TransactionHelper.sol"; import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import { IHookManager } from "../interfaces/IHookManager.sol"; import { IValidatorManager } from "../interfaces/IValidatorManager.sol"; import { SessionLib } from "../libraries/SessionLib.sol"; contract SessionKeyValidator is IValidationHook, IModuleValidator, IModule { using SessionLib for SessionLib.SessionStorage; using EnumerableSet for EnumerableSet.Bytes32Set; event SessionCreated(address indexed account, bytes32 indexed sessionHash, SessionLib.SessionSpec sessionSpec); event SessionRevoked(address indexed account, bytes32 indexed sessionHash); // account => number of open sessions // NOTE: expired sessions are still counted if not explicitly revoked mapping(address => uint256) private sessionCounter; // session hash => session state mapping(bytes32 => SessionLib.SessionStorage) private sessions; function sessionState( address account, SessionLib.SessionSpec calldata spec ) external view returns (SessionLib.SessionState memory) { return sessions[keccak256(abi.encode(spec))].getState(account, spec); } function sessionStatus(address account, bytes32 sessionHash) external view returns (SessionLib.Status) { SessionLib.Status status = sessions[sessionHash].status[account]; if (status == SessionLib.Status.Active) { if (block.timestamp > sessions[sessionHash].expiresAt) { return SessionLib.Status.Expired; } } return status; } function handleValidation(OperationType operationType, bytes32 signedHash, bytes memory signature) external view returns (bool) { if (operationType != OperationType.Transaction) { return false; } // This only succeeds if the validationHook has previously succeeded for this hash. uint256 slot = uint256(signedHash); uint256 hookResult; assembly { hookResult := tload(slot) } require(hookResult == 1, "Session key validation failed. Please check session status and limits."); return true; } function addValidationKey(bytes memory sessionData) external returns (bool) { if (sessionData.length == 0) { return false; } SessionLib.SessionSpec memory sessionSpec = abi.decode(sessionData, (SessionLib.SessionSpec)); createSession(sessionSpec); return true; } function createSession(SessionLib.SessionSpec memory sessionSpec) public { bytes32 sessionHash = keccak256(abi.encode(sessionSpec)); require(_isInitialized(msg.sender), "Account not initialized"); require(sessionSpec.signer != address(0), "Invalid signer"); require(sessions[sessionHash].status[msg.sender] == SessionLib.Status.NotInitialized, "Session already exists"); require(sessionSpec.feeLimit.limitType != SessionLib.LimitType.Unlimited, "Unlimited fee allowance is not safe"); sessionCounter[msg.sender]++; sessions[sessionHash].status[msg.sender] = SessionLib.Status.Active; sessions[sessionHash].expiresAt = sessionSpec.expiresAt; emit SessionCreated(msg.sender, sessionHash, sessionSpec); } function init(bytes calldata data) external { // to prevent recursion, since addHook also calls init if (!_isInitialized(msg.sender)) { // Ensure that all keys are revoked before installing the module again. // This is to prevent the module from being installed, used and installed // again later with dormant keys that could be used to execute transactions. require(sessionCounter[msg.sender] == 0, "Revoke all keys first"); IHookManager(msg.sender).addHook(abi.encodePacked(address(this)), true); IValidatorManager(msg.sender).addModuleValidator(address(this), data); } } function disable() external { if (_isInitialized(msg.sender)) { IValidatorManager(msg.sender).removeModuleValidator(address(this)); IHookManager(msg.sender).removeHook(address(this), true); } } function supportsInterface(bytes4 interfaceId) external pure override returns (bool) { return interfaceId != 0xffffffff && (interfaceId == type(IERC165).interfaceId || interfaceId == type(IValidationHook).interfaceId || interfaceId == type(IModuleValidator).interfaceId || interfaceId == type(IModule).interfaceId); } // TODO: make the session owner able revoke its own key, in case it was leaked, to prevent further misuse? function revokeKey(bytes32 sessionHash) public { require(sessions[sessionHash].status[msg.sender] == SessionLib.Status.Active, "Nothing to revoke"); sessions[sessionHash].status[msg.sender] = SessionLib.Status.Closed; sessionCounter[msg.sender]--; emit SessionRevoked(msg.sender, sessionHash); } function revokeKeys(bytes32[] calldata sessionHashes) external { for (uint256 i = 0; i < sessionHashes.length; i++) { revokeKey(sessionHashes[i]); } } /* * Check if the validator is registered for the smart account * @param smartAccount The smart account to check * @return true if validator is registered for the account, false otherwise */ function isInited(address smartAccount) external view returns (bool) { return _isInitialized(smartAccount); } function _isInitialized(address smartAccount) internal view returns (bool) { return IHookManager(smartAccount).isHook(address(this)); } function validationHook(bytes32 signedHash, Transaction calldata transaction, bytes calldata hookData) external { if (hookData.length == 0) { // There's no session data so we aren't validating anything return; } (bytes memory signature, address validator, ) = abi.decode(transaction.signature, (bytes, address, bytes[])); if (validator != address(this)) { // This transaction is not meant to be validated by this module return; } (SessionLib.SessionSpec memory spec, uint64[] memory periodIds) = abi.decode( hookData, (SessionLib.SessionSpec, uint64[]) ); require(spec.signer != address(0), "Invalid signer (empty)"); bytes32 sessionHash = keccak256(abi.encode(spec)); // this generally throws instead of returning false sessions[sessionHash].validate(transaction, spec, periodIds); (address recoveredAddress, ECDSA.RecoverError recoverError, ) = ECDSA.tryRecover(signedHash, signature); if (recoverError != ECDSA.RecoverError.NoError || recoveredAddress == address(0)) { return; } require(recoveredAddress == spec.signer, "Invalid signer (mismatch)"); // This check is separate and performed last to prevent gas estimation failures sessions[sessionHash].validateFeeLimit(transaction, spec, periodIds[0]); // Set the validation result to 1 for this hash, so that isValidSignature succeeds uint256 slot = uint256(signedHash); assembly { tstore(slot, 1) } } /** * The name of the module * @return name The name of the module */ function name() external pure returns (string memory) { return "SessionKeyValidator"; } /** * Currently in dev * @return version The version of the module */ function version() external pure returns (string memory) { return "0.0.0"; } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.17; import {Transaction} from '@matterlabs/zksync-contracts/l2/system-contracts/libraries/TransactionHelper.sol'; import {IInitable} from '../interfaces/IInitable.sol'; import {IERC165} from '@openzeppelin/contracts/utils/introspection/IERC165.sol'; interface IValidationHook is IInitable, IERC165 { function validationHook( bytes32 signedHash, Transaction calldata transaction, bytes calldata hookData ) external; } interface IExecutionHook is IInitable, IERC165 { function preExecutionHook( Transaction calldata transaction ) external returns (bytes memory context); function postExecutionHook(bytes memory context) external; }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.24; import {OperationType} from './IValidator.sol'; /** * @title Modular validator interface for native AA * @dev Add signature to module or validate existing signatures for acccount */ interface IModuleValidator { function handleValidation(OperationType operationType, bytes32 signedHash, bytes memory signature) external view returns (bool); function addValidationKey(bytes memory key) external returns (bool); }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.17; import {IERC165} from '@openzeppelin/contracts/utils/introspection/IERC165.sol'; enum OperationType { Signature, Transaction } /** * @title secp256r1 ec keys' signature validator interface * @author https://getclave.io */ interface IR1Validator is IERC165 { /** * @notice Allows to validate secp256r1 ec signatures * @param signedHash bytes32 - hash of the data that is signed by the key * @param signature bytes - signature * @param pubKey bytes32[2] - public key coordinates array for the x and y values * @return valid bool - validation result */ function validateSignature( OperationType operationType, bytes32 signedHash, bytes calldata signature, bytes32[2] calldata pubKey ) external view returns (bool valid); } /** * @title secp256k1 ec keys' signature validator interface * @author https://getclave.io */ interface IK1Validator is IERC165 { /** * @notice Allows to validate secp256k1 ec signatures * @param signedHash bytes32 - hash of the transaction signed by the key * @param signature bytes - signature * @return signer address - recovered signer address */ function validateSignature( OperationType operationType, bytes32 signedHash, bytes calldata signature ) external view returns (address signer); }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.17; import {IInitable} from '../interfaces/IInitable.sol'; import {IERC165} from '@openzeppelin/contracts/utils/introspection/IERC165.sol'; interface IModule is IInitable, IERC165 {}
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.17; /** * @title Interface of the manager contract for hooks * @author https://getclave.io */ interface IHookManager { /** * @notice Event emitted when a hook is added * @param hook address - Address of the added hook */ event AddHook(address indexed hook); /** * @notice Event emitted when a hook is removed * @param hook address - Address of the removed hook */ event RemoveHook(address indexed hook); /** * @notice Add a hook to the list of hooks and call it's init function * @dev Can only be called by self or a module * @param hookAndData bytes calldata - Address of the hook and data to initialize it with * @param isValidation bool - True if the hook is a validation hook, false otherwise */ function addHook(bytes calldata hookAndData, bool isValidation) external; /** * @notice Remove a hook from the list of hooks and call it's disable function * @dev Can only be called by self or a module * @param hook address - Address of the hook to remove * @param isValidation bool - True if the hook is a validation hook, false otherwise */ function removeHook(address hook, bool isValidation) external; /** * @notice Allow a hook to store data in the contract * @dev Can only be called by a hook * @param key bytes32 - Slot to store data at * @param data bytes calldata - Data to store */ function setHookData(bytes32 key, bytes calldata data) external; /** * @notice Get the data stored by a hook * @param hook address - Address of the hook to retrieve data for * @param key bytes32 - Slot to retrieve data from * @return bytes memory - Data stored at the slot */ function getHookData(address hook, bytes32 key) external view returns (bytes memory); /** * @notice Check if an address is in the list of hooks * @param addr address - Address to check * @return bool - True if the address is a hook, false otherwise */ function isHook(address addr) external view returns (bool); /** * @notice Get the list of validation or execution hooks * @param isValidation bool - True if the list of validation hooks should be returned, false otherwise * @return hookList address[] memory - List of validation or exeuction hooks */ function listHooks(bool isValidation) external view returns (address[] memory hookList); }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.24; import { Transaction } from "@matterlabs/zksync-contracts/l2/system-contracts/libraries/TransactionHelper.sol"; import { IPaymasterFlow } from "@matterlabs/zksync-contracts/l2/system-contracts/interfaces/IPaymasterFlow.sol"; import { TimestampAsserterLocator } from "../helpers/TimestampAsserterLocator.sol"; library SessionLib { using SessionLib for SessionLib.Constraint; using SessionLib for SessionLib.UsageLimit; // We do not permit session keys to be reused to open multiple sessions // (after one expires or is closed, e.g.). // For each session key, its session status can only be changed // from NotInitialized to Active, and from Active to Closed. enum Status { NotInitialized, Active, Closed, Expired } // This struct is used to track usage information for each session. // Along with `status`, this is considered the session state. // While everything else is considered the session spec, and is stored offchain. // Storage layout of this struct is weird to conform to ERC-7562 storage access restrictions during validation. // Each innermost mapping is always mapping(address account => ...). struct SessionStorage { uint256 expiresAt; mapping(address => Status) status; UsageTracker fee; // (target) => transfer value tracker mapping(address => UsageTracker) transferValue; // (target, selector) => call value tracker mapping(address => mapping(bytes4 => UsageTracker)) callValue; // (target, selector, index) => call parameter tracker // index is the constraint index in callPolicy, not the parameter index mapping(address => mapping(bytes4 => mapping(uint256 => UsageTracker))) params; } struct Constraint { Condition condition; uint64 index; bytes32 refValue; UsageLimit limit; } struct UsageTracker { // Used for LimitType.Lifetime mapping(address => uint256) lifetimeUsage; // Used for LimitType.Allowance // period => used that period mapping(uint64 => mapping(address => uint256)) allowanceUsage; } struct UsageLimit { LimitType limitType; uint256 limit; // ignored if limitType == Unlimited uint256 period; // ignored if limitType != Allowance } enum LimitType { Unlimited, Lifetime, Allowance } enum Condition { Unconstrained, Equal, Greater, Less, GreaterOrEqual, LessOrEqual, NotEqual } struct SessionSpec { address signer; uint256 expiresAt; UsageLimit feeLimit; CallSpec[] callPolicies; TransferSpec[] transferPolicies; } struct CallSpec { address target; bytes4 selector; uint256 maxValuePerUse; UsageLimit valueLimit; Constraint[] constraints; // add max data length restriction? // add max number of calls restriction? } struct TransferSpec { address target; uint256 maxValuePerUse; UsageLimit valueLimit; } struct LimitState { // this might also be limited by a constraint or `maxValuePerUse`, // which is not reflected here uint256 remaining; address target; // ignored for transfer value bytes4 selector; // ignored for transfer and call value uint256 index; } // Info about remaining session limits and its status struct SessionState { uint256 expiresAt; Status status; uint256 feesRemaining; LimitState[] transferValue; LimitState[] callValue; LimitState[] callParams; } function checkAndUpdate( UsageLimit memory limit, UsageTracker storage tracker, uint256 value, uint64 period ) internal { if (limit.limitType == LimitType.Lifetime) { require(tracker.lifetimeUsage[msg.sender] + value <= limit.limit, "Lifetime limit exceeded"); tracker.lifetimeUsage[msg.sender] += value; } if (limit.limitType == LimitType.Allowance) { TimestampAsserterLocator.locate().assertTimestampInRange(period * limit.period, (period + 1) * limit.period); require(tracker.allowanceUsage[period][msg.sender] + value <= limit.limit, "Allowance limit exceeded"); tracker.allowanceUsage[period][msg.sender] += value; } } function checkAndUpdate( Constraint memory constraint, UsageTracker storage tracker, bytes calldata data, uint64 period ) internal { uint256 index = 4 + constraint.index * 32; bytes32 param = bytes32(data[index:index + 32]); Condition condition = constraint.condition; bytes32 refValue = constraint.refValue; if (condition == Condition.Equal) { require(param == refValue, "EQUAL constraint not met"); } else if (condition == Condition.Greater) { require(param > refValue, "GREATER constraint not met"); } else if (condition == Condition.Less) { require(param < refValue, "LESS constraint not met"); } else if (condition == Condition.GreaterOrEqual) { require(param >= refValue, "GREATER_OR_EQUAL constraint not met"); } else if (condition == Condition.LessOrEqual) { require(param <= refValue, "LESS_OR_EQUAL constraint not met"); } else if (condition == Condition.NotEqual) { require(param != refValue, "NOT_EQUAL constraint not met"); } constraint.limit.checkAndUpdate(tracker, uint256(param), period); } function validateFeeLimit( SessionStorage storage state, Transaction calldata transaction, SessionSpec memory spec, uint64 periodId ) internal { // This is split from `validate` to prevent gas estimation failures. // When this check was part of `validate`, gas estimation could fail due to // fee limit being smaller than the upper bound of the gas estimation binary search. // By splitting this check, we can now have this order of operations in `validateTransaction`: // 1. session.validate() // 2. ECDSA.tryRecover() // 3. session.validateFeeLimit() // This way, gas estimation will exit on step 2 instead of failing, but will still run through // most of the computation needed to validate the session. // TODO: update fee allowance with the gasleft/refund at the end of execution if (transaction.paymaster == 0) { // If a paymaster is paying the fee, we don't need to check the fee limit uint256 fee = transaction.maxFeePerGas * transaction.gasLimit; spec.feeLimit.checkAndUpdate(state.fee, fee, periodId); } } function validate( SessionStorage storage state, Transaction calldata transaction, SessionSpec memory spec, uint64[] memory periodIds ) internal { // Here we additionally pass uint64[] periodId to check allowance limits // periodId is defined as block.timestamp / limit.period if limitType == Allowance, and 0 otherwise (which will be ignored). // periodIds[0] is for fee limit, // periodIds[1] is for value limit, // periodIds[2:] are for call constraints, if there are any. // It is required to pass them in (instead of computing via block.timestamp) since during validation // we can only assert the range of the timestamp, but not access its value. require(state.status[msg.sender] == Status.Active, "Session is not active"); TimestampAsserterLocator.locate().assertTimestampInRange(0, spec.expiresAt); address target = address(uint160(transaction.to)); if (transaction.paymasterInput.length >= 4) { bytes4 paymasterInputSelector = bytes4(transaction.paymasterInput[0:4]); require( paymasterInputSelector != IPaymasterFlow.approvalBased.selector, "Approval based paymaster flow not allowed" ); } if (transaction.data.length >= 4) { // Disallow self-targeting transactions with session keys as these have the ability to administer // the smart account. require(address(uint160(transaction.to)) != msg.sender, "Can not target self"); require(address(uint160(transaction.to)) != address(this), "Can not manage session keys"); bytes4 selector = bytes4(transaction.data[:4]); CallSpec memory callPolicy; bool found = false; for (uint256 i = 0; i < spec.callPolicies.length; i++) { if (spec.callPolicies[i].target == target && spec.callPolicies[i].selector == selector) { callPolicy = spec.callPolicies[i]; found = true; break; } } require(found, "Call to this contract is not allowed"); require(transaction.value <= callPolicy.maxValuePerUse, "Value exceeds limit"); callPolicy.valueLimit.checkAndUpdate(state.callValue[target][selector], transaction.value, periodIds[1]); for (uint256 i = 0; i < callPolicy.constraints.length; i++) { callPolicy.constraints[i].checkAndUpdate(state.params[target][selector][i], transaction.data, periodIds[i + 2]); } } else { TransferSpec memory transferPolicy; bool found = false; for (uint256 i = 0; i < spec.transferPolicies.length; i++) { if (spec.transferPolicies[i].target == target) { transferPolicy = spec.transferPolicies[i]; found = true; break; } } require(found, "Transfer to this address is not allowed"); require(transaction.value <= transferPolicy.maxValuePerUse, "Value exceeds limit"); transferPolicy.valueLimit.checkAndUpdate(state.transferValue[target], transaction.value, periodIds[1]); } } function remainingLimit( UsageLimit memory limit, UsageTracker storage tracker, address account ) internal view returns (uint256) { if (limit.limitType == LimitType.Unlimited) { // this might be still limited by `maxValuePerUse` or a constraint return type(uint256).max; } if (limit.limitType == LimitType.Lifetime) { return limit.limit - tracker.lifetimeUsage[account]; } if (limit.limitType == LimitType.Allowance) { // this is not used during validation, so it's fine to use block.timestamp uint64 period = uint64(block.timestamp / limit.period); return limit.limit - tracker.allowanceUsage[period][account]; } } function getState( SessionStorage storage session, address account, SessionSpec calldata spec ) internal view returns (SessionState memory) { uint256 totalConstraints = 0; for (uint256 i = 0; i < spec.callPolicies.length; i++) { totalConstraints += spec.callPolicies[i].constraints.length; } LimitState[] memory transferValue = new LimitState[](spec.transferPolicies.length); LimitState[] memory callValue = new LimitState[](spec.callPolicies.length); LimitState[] memory callParams = new LimitState[](totalConstraints); // there will be empty ones at the end uint256 paramLimitIndex = 0; for (uint256 i = 0; i < transferValue.length; i++) { TransferSpec memory transferSpec = spec.transferPolicies[i]; transferValue[i] = LimitState({ remaining: remainingLimit(transferSpec.valueLimit, session.transferValue[transferSpec.target], account), target: spec.transferPolicies[i].target, selector: bytes4(0), index: 0 }); } for (uint256 i = 0; i < callValue.length; i++) { CallSpec memory callSpec = spec.callPolicies[i]; callValue[i] = LimitState({ remaining: remainingLimit(callSpec.valueLimit, session.callValue[callSpec.target][callSpec.selector], account), target: callSpec.target, selector: callSpec.selector, index: 0 }); for (uint256 j = 0; j < callSpec.constraints.length; j++) { if (callSpec.constraints[j].limit.limitType != LimitType.Unlimited) { callParams[paramLimitIndex++] = LimitState({ remaining: remainingLimit( callSpec.constraints[j].limit, session.params[callSpec.target][callSpec.selector][j], account ), target: callSpec.target, selector: callSpec.selector, index: callSpec.constraints[j].index }); } } } // shrink array to actual size assembly { mstore(callParams, paramLimitIndex) } Status status = session.status[account]; if (status == Status.Active) { if (block.timestamp > session.expiresAt) { status = Status.Expired; } } return SessionState({ expiresAt: session.expiresAt, status: status, feesRemaining: remainingLimit(spec.feeLimit, session.fee, account), transferValue: transferValue, callValue: callValue, callParams: callParams }); } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.17; /** * @title Manager contract for validators * @author https://getclave.io */ interface IValidatorManager { /** * @notice Event emitted when a r1 validator is added * @param validator address - Address of the added r1 validator */ event R1AddValidator(address indexed validator); /** * @notice Event emitted when a k1 validator is added * @param validator address - Address of the added k1 validator */ event K1AddValidator(address indexed validator); /** * @notice Event emitted when a modular validator is added * @param validator address - Address of the added modular validator */ event AddModuleValidator(address indexed validator); /** * @notice Event emitted when a r1 validator is removed * @param validator address - Address of the removed r1 validator */ event R1RemoveValidator(address indexed validator); /** * @notice Event emitted when a k1 validator is removed * @param validator address - Address of the removed k1 validator */ event K1RemoveValidator(address indexed validator); /** * @notice Event emitted when a modular validator is removed * @param validator address - Address of the removed modular validator */ event RemoveModuleValidator(address indexed validator); /** * @notice Adds a validator to the list of r1 validators * @dev Can only be called by self or a whitelisted module * @param validator address - Address of the r1 validator to add */ function r1AddValidator(address validator) external; /** * @notice Adds a validator to the list of modular validators * @dev Can only be called by self or a whitelisted module * @param validator address - Address of the generic validator to add * @param accountValidationKey bytes - data for the validator to use to validate the account */ function addModuleValidator(address validator, bytes memory accountValidationKey) external; /** * @notice Adds a validator to the list of k1 validators * @dev Can only be called by self or a whitelisted module * @param validator address - Address of the k1 validator to add */ function k1AddValidator(address validator) external; /** * @notice Removes a validator from the list of r1 validators * @dev Can only be called by self or a whitelisted module * @dev Can not remove the last validator * @param validator address - Address of the validator to remove */ function r1RemoveValidator(address validator) external; /** * @notice Removes a validator from the list of k1 validators * @dev Can only be called by self or a whitelisted module * @param validator address - Address of the validator to remove */ function k1RemoveValidator(address validator) external; /** * @notice Removes a validator from the list of modular validators * @dev Can only be called by self or a whitelisted module * @param validator address - Address of the validator to remove */ function removeModuleValidator(address validator) external; /** * @notice Checks if an address is in the r1 validator list * @param validator address -Address of the validator to check * @return True if the address is a validator, false otherwise */ function r1IsValidator(address validator) external view returns (bool); /** * @notice Checks if an address is in the k1 validator list * @param validator address - Address of the validator to check * @return True if the address is a validator, false otherwise */ function k1IsValidator(address validator) external view returns (bool); /** * @notice Checks if an address is in the modular validator list * @param validator address - Address of the validator to check * @return True if the address is a validator, false otherwise */ function isModuleValidator(address validator) external view returns (bool); /** * @notice Returns the list of r1 validators * @return validatorList address[] memory - Array of r1 validator addresses */ function r1ListValidators() external view returns (address[] memory validatorList); /** * @notice Returns the list of k1 validators * @return validatorList address[] memory - Array of k1 validator addresses */ function k1ListValidators() external view returns (address[] memory validatorList); /** * @notice Returns the list of modular validators * @return validatorList address[] memory - Array of modular validator addresses */ function listModuleValidators() external view returns (address[] memory validatorList); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/structs/EnumerableSet.sol) // This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. pragma solidity ^0.8.20; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ```solidity * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. * * [WARNING] * ==== * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure * unusable. * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. * * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an * array of EnumerableSet. * ==== */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position is the index of the value in the `values` array plus 1. // Position 0 is used to mean a value is not in the set. mapping(bytes32 value => uint256) _positions; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._positions[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We cache the value's position to prevent multiple reads from the same storage slot uint256 position = set._positions[value]; if (position != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 valueIndex = position - 1; uint256 lastIndex = set._values.length - 1; if (valueIndex != lastIndex) { bytes32 lastValue = set._values[lastIndex]; // Move the lastValue to the index where the value to delete is set._values[valueIndex] = lastValue; // Update the tracked position of the lastValue (that was just moved) set._positions[lastValue] = position; } // Delete the slot where the moved value was stored set._values.pop(); // Delete the tracked position for the deleted slot delete set._positions[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._positions[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { bytes32[] memory store = _values(set._inner); bytes32[] memory result; assembly ("memory-safe") { result := store } return result; } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; assembly ("memory-safe") { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values in the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; assembly ("memory-safe") { result := store } return result; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[ERC]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.20; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS } /** * @dev The signature derives the `address(0)`. */ error ECDSAInvalidSignature(); /** * @dev The signature has an invalid length. */ error ECDSAInvalidSignatureLength(uint256 length); /** * @dev The signature has an S value that is in the upper half order. */ error ECDSAInvalidSignatureS(bytes32 s); /** * @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not * return address(0) without also returning an error description. Errors are documented using an enum (error type) * and a bytes32 providing additional information about the error. * * If no error is returned, then the address can be used for verification purposes. * * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] */ function tryRecover( bytes32 hash, bytes memory signature ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. assembly ("memory-safe") { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length)); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature); _throwError(error, errorArg); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[ERC-2098 short signatures] */ function tryRecover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) { unchecked { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); // We do not check for an overflow here since the shift operation results in 0 or 1. uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. */ function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs); _throwError(error, errorArg); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address recovered, RecoverError err, bytes32 errArg) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS, s); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature, bytes32(0)); } return (signer, RecoverError.NoError, bytes32(0)); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s); _throwError(error, errorArg); return recovered; } /** * @dev Optionally reverts with the corresponding custom error according to the `error` argument provided. */ function _throwError(RecoverError error, bytes32 errorArg) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert ECDSAInvalidSignature(); } else if (error == RecoverError.InvalidSignatureLength) { revert ECDSAInvalidSignatureLength(uint256(errorArg)); } else if (error == RecoverError.InvalidSignatureS) { revert ECDSAInvalidSignatureS(errorArg); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../openzeppelin/token/ERC20/IERC20.sol"; import "../openzeppelin/token/ERC20/utils/SafeERC20.sol"; import "../interfaces/IPaymasterFlow.sol"; import "../interfaces/IContractDeployer.sol"; import {ETH_TOKEN_SYSTEM_CONTRACT, BOOTLOADER_FORMAL_ADDRESS} from "../Constants.sol"; import "./RLPEncoder.sol"; import "./EfficientCall.sol"; /// @dev The type id of zkSync's EIP-712-signed transaction. uint8 constant EIP_712_TX_TYPE = 0x71; /// @dev The type id of legacy transactions. uint8 constant LEGACY_TX_TYPE = 0x0; /// @dev The type id of legacy transactions. uint8 constant EIP_2930_TX_TYPE = 0x01; /// @dev The type id of EIP1559 transactions. uint8 constant EIP_1559_TX_TYPE = 0x02; /// @notice Structure used to represent zkSync transaction. struct Transaction { // The type of the transaction. uint256 txType; // The caller. uint256 from; // The callee. uint256 to; // The gasLimit to pass with the transaction. // It has the same meaning as Ethereum's gasLimit. uint256 gasLimit; // The maximum amount of gas the user is willing to pay for a byte of pubdata. uint256 gasPerPubdataByteLimit; // The maximum fee per gas that the user is willing to pay. // It is akin to EIP1559's maxFeePerGas. uint256 maxFeePerGas; // The maximum priority fee per gas that the user is willing to pay. // It is akin to EIP1559's maxPriorityFeePerGas. uint256 maxPriorityFeePerGas; // The transaction's paymaster. If there is no paymaster, it is equal to 0. uint256 paymaster; // The nonce of the transaction. uint256 nonce; // The value to pass with the transaction. uint256 value; // In the future, we might want to add some // new fields to the struct. The `txData` struct // is to be passed to account and any changes to its structure // would mean a breaking change to these accounts. In order to prevent this, // we should keep some fields as "reserved". // It is also recommended that their length is fixed, since // it would allow easier proof integration (in case we will need // some special circuit for preprocessing transactions). uint256[4] reserved; // The transaction's calldata. bytes data; // The signature of the transaction. bytes signature; // The properly formatted hashes of bytecodes that must be published on L1 // with the inclusion of this transaction. Note, that a bytecode has been published // before, the user won't pay fees for its republishing. bytes32[] factoryDeps; // The input to the paymaster. bytes paymasterInput; // Reserved dynamic type for the future use-case. Using it should be avoided, // But it is still here, just in case we want to enable some additional functionality. bytes reservedDynamic; } /** * @author Matter Labs * @notice Library is used to help custom accounts to work with common methods for the Transaction type. */ library TransactionHelper { using SafeERC20 for IERC20; /// @notice The EIP-712 typehash for the contract's domain bytes32 constant EIP712_DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,string version,uint256 chainId)"); bytes32 constant EIP712_TRANSACTION_TYPE_HASH = keccak256( "Transaction(uint256 txType,uint256 from,uint256 to,uint256 gasLimit,uint256 gasPerPubdataByteLimit,uint256 maxFeePerGas,uint256 maxPriorityFeePerGas,uint256 paymaster,uint256 nonce,uint256 value,bytes data,bytes32[] factoryDeps,bytes paymasterInput)" ); /// @notice Whether the token is Ethereum. /// @param _addr The address of the token /// @return `true` or `false` based on whether the token is Ether. /// @dev This method assumes that address is Ether either if the address is 0 (for convenience) /// or if the address is the address of the L2EthToken system contract. function isEthToken(uint256 _addr) internal pure returns (bool) { return _addr == uint256(uint160(address(ETH_TOKEN_SYSTEM_CONTRACT))) || _addr == 0; } /// @notice Calculate the suggested signed hash of the transaction, /// i.e. the hash that is signed by EOAs and is recommended to be signed by other accounts. function encodeHash(Transaction calldata _transaction) internal view returns (bytes32 resultHash) { if (_transaction.txType == LEGACY_TX_TYPE) { resultHash = _encodeHashLegacyTransaction(_transaction); } else if (_transaction.txType == EIP_712_TX_TYPE) { resultHash = _encodeHashEIP712Transaction(_transaction); } else if (_transaction.txType == EIP_1559_TX_TYPE) { resultHash = _encodeHashEIP1559Transaction(_transaction); } else if (_transaction.txType == EIP_2930_TX_TYPE) { resultHash = _encodeHashEIP2930Transaction(_transaction); } else { // Currently no other transaction types are supported. // Any new transaction types will be processed in a similar manner. revert("Encoding unsupported tx"); } } /// @notice Encode hash of the zkSync native transaction type. /// @return keccak256 hash of the EIP-712 encoded representation of transaction function _encodeHashEIP712Transaction(Transaction calldata _transaction) private view returns (bytes32) { bytes32 structHash = keccak256( abi.encode( EIP712_TRANSACTION_TYPE_HASH, _transaction.txType, _transaction.from, _transaction.to, _transaction.gasLimit, _transaction.gasPerPubdataByteLimit, _transaction.maxFeePerGas, _transaction.maxPriorityFeePerGas, _transaction.paymaster, _transaction.nonce, _transaction.value, EfficientCall.keccak(_transaction.data), keccak256(abi.encodePacked(_transaction.factoryDeps)), EfficientCall.keccak(_transaction.paymasterInput) ) ); bytes32 domainSeparator = keccak256( abi.encode(EIP712_DOMAIN_TYPEHASH, keccak256("zkSync"), keccak256("2"), block.chainid) ); return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); } /// @notice Encode hash of the legacy transaction type. /// @return keccak256 of the serialized RLP encoded representation of transaction function _encodeHashLegacyTransaction(Transaction calldata _transaction) private view returns (bytes32) { // Hash of legacy transactions are encoded as one of the: // - RLP(nonce, gasPrice, gasLimit, to, value, data, chainId, 0, 0) // - RLP(nonce, gasPrice, gasLimit, to, value, data) // // In this RLP encoding, only the first one above list appears, so we encode each element // inside list and then concatenate the length of all elements with them. bytes memory encodedNonce = RLPEncoder.encodeUint256(_transaction.nonce); // Encode `gasPrice` and `gasLimit` together to prevent "stack too deep error". bytes memory encodedGasParam; { bytes memory encodedGasPrice = RLPEncoder.encodeUint256(_transaction.maxFeePerGas); bytes memory encodedGasLimit = RLPEncoder.encodeUint256(_transaction.gasLimit); encodedGasParam = bytes.concat(encodedGasPrice, encodedGasLimit); } bytes memory encodedTo = RLPEncoder.encodeAddress(address(uint160(_transaction.to))); bytes memory encodedValue = RLPEncoder.encodeUint256(_transaction.value); // Encode only the length of the transaction data, and not the data itself, // so as not to copy to memory a potentially huge transaction data twice. bytes memory encodedDataLength; { // Safe cast, because the length of the transaction data can't be so large. uint64 txDataLen = uint64(_transaction.data.length); if (txDataLen != 1) { // If the length is not equal to one, then only using the length can it be encoded definitely. encodedDataLength = RLPEncoder.encodeNonSingleBytesLen(txDataLen); } else if (_transaction.data[0] >= 0x80) { // If input is a byte in [0x80, 0xff] range, RLP encoding will concatenates 0x81 with the byte. encodedDataLength = hex"81"; } // Otherwise the length is not encoded at all. } // Encode `chainId` according to EIP-155, but only if the `chainId` is specified in the transaction. bytes memory encodedChainId; if (_transaction.reserved[0] != 0) { encodedChainId = bytes.concat(RLPEncoder.encodeUint256(block.chainid), hex"80_80"); } bytes memory encodedListLength; unchecked { uint256 listLength = encodedNonce.length + encodedGasParam.length + encodedTo.length + encodedValue.length + encodedDataLength.length + _transaction.data.length + encodedChainId.length; // Safe cast, because the length of the list can't be so large. encodedListLength = RLPEncoder.encodeListLen(uint64(listLength)); } return keccak256( bytes.concat( encodedListLength, encodedNonce, encodedGasParam, encodedTo, encodedValue, encodedDataLength, _transaction.data, encodedChainId ) ); } /// @notice Encode hash of the EIP2930 transaction type. /// @return keccak256 of the serialized RLP encoded representation of transaction function _encodeHashEIP2930Transaction(Transaction calldata _transaction) private view returns (bytes32) { // Hash of EIP2930 transactions is encoded the following way: // H(0x01 || RLP(chain_id, nonce, gas_price, gas_limit, destination, amount, data, access_list)) // // Note, that on zkSync access lists are not supported and should always be empty. // Encode all fixed-length params to avoid "stack too deep error" bytes memory encodedFixedLengthParams; { bytes memory encodedChainId = RLPEncoder.encodeUint256(block.chainid); bytes memory encodedNonce = RLPEncoder.encodeUint256(_transaction.nonce); bytes memory encodedGasPrice = RLPEncoder.encodeUint256(_transaction.maxFeePerGas); bytes memory encodedGasLimit = RLPEncoder.encodeUint256(_transaction.gasLimit); bytes memory encodedTo = RLPEncoder.encodeAddress(address(uint160(_transaction.to))); bytes memory encodedValue = RLPEncoder.encodeUint256(_transaction.value); encodedFixedLengthParams = bytes.concat( encodedChainId, encodedNonce, encodedGasPrice, encodedGasLimit, encodedTo, encodedValue ); } // Encode only the length of the transaction data, and not the data itself, // so as not to copy to memory a potentially huge transaction data twice. bytes memory encodedDataLength; { // Safe cast, because the length of the transaction data can't be so large. uint64 txDataLen = uint64(_transaction.data.length); if (txDataLen != 1) { // If the length is not equal to one, then only using the length can it be encoded definitely. encodedDataLength = RLPEncoder.encodeNonSingleBytesLen(txDataLen); } else if (_transaction.data[0] >= 0x80) { // If input is a byte in [0x80, 0xff] range, RLP encoding will concatenates 0x81 with the byte. encodedDataLength = hex"81"; } // Otherwise the length is not encoded at all. } // On zkSync, access lists are always zero length (at least for now). bytes memory encodedAccessListLength = RLPEncoder.encodeListLen(0); bytes memory encodedListLength; unchecked { uint256 listLength = encodedFixedLengthParams.length + encodedDataLength.length + _transaction.data.length + encodedAccessListLength.length; // Safe cast, because the length of the list can't be so large. encodedListLength = RLPEncoder.encodeListLen(uint64(listLength)); } return keccak256( bytes.concat( "\x01", encodedListLength, encodedFixedLengthParams, encodedDataLength, _transaction.data, encodedAccessListLength ) ); } /// @notice Encode hash of the EIP1559 transaction type. /// @return keccak256 of the serialized RLP encoded representation of transaction function _encodeHashEIP1559Transaction(Transaction calldata _transaction) private view returns (bytes32) { // Hash of EIP1559 transactions is encoded the following way: // H(0x02 || RLP(chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, destination, amount, data, access_list)) // // Note, that on zkSync access lists are not supported and should always be empty. // Encode all fixed-length params to avoid "stack too deep error" bytes memory encodedFixedLengthParams; { bytes memory encodedChainId = RLPEncoder.encodeUint256(block.chainid); bytes memory encodedNonce = RLPEncoder.encodeUint256(_transaction.nonce); bytes memory encodedMaxPriorityFeePerGas = RLPEncoder.encodeUint256(_transaction.maxPriorityFeePerGas); bytes memory encodedMaxFeePerGas = RLPEncoder.encodeUint256(_transaction.maxFeePerGas); bytes memory encodedGasLimit = RLPEncoder.encodeUint256(_transaction.gasLimit); bytes memory encodedTo = RLPEncoder.encodeAddress(address(uint160(_transaction.to))); bytes memory encodedValue = RLPEncoder.encodeUint256(_transaction.value); encodedFixedLengthParams = bytes.concat( encodedChainId, encodedNonce, encodedMaxPriorityFeePerGas, encodedMaxFeePerGas, encodedGasLimit, encodedTo, encodedValue ); } // Encode only the length of the transaction data, and not the data itself, // so as not to copy to memory a potentially huge transaction data twice. bytes memory encodedDataLength; { // Safe cast, because the length of the transaction data can't be so large. uint64 txDataLen = uint64(_transaction.data.length); if (txDataLen != 1) { // If the length is not equal to one, then only using the length can it be encoded definitely. encodedDataLength = RLPEncoder.encodeNonSingleBytesLen(txDataLen); } else if (_transaction.data[0] >= 0x80) { // If input is a byte in [0x80, 0xff] range, RLP encoding will concatenates 0x81 with the byte. encodedDataLength = hex"81"; } // Otherwise the length is not encoded at all. } // On zkSync, access lists are always zero length (at least for now). bytes memory encodedAccessListLength = RLPEncoder.encodeListLen(0); bytes memory encodedListLength; unchecked { uint256 listLength = encodedFixedLengthParams.length + encodedDataLength.length + _transaction.data.length + encodedAccessListLength.length; // Safe cast, because the length of the list can't be so large. encodedListLength = RLPEncoder.encodeListLen(uint64(listLength)); } return keccak256( bytes.concat( "\x02", encodedListLength, encodedFixedLengthParams, encodedDataLength, _transaction.data, encodedAccessListLength ) ); } /// @notice Processes the common paymaster flows, e.g. setting proper allowance /// for tokens, etc. For more information on the expected behavior, check out /// the "Paymaster flows" section in the documentation. function processPaymasterInput(Transaction calldata _transaction) internal { require(_transaction.paymasterInput.length >= 4, "The standard paymaster input must be at least 4 bytes long"); bytes4 paymasterInputSelector = bytes4(_transaction.paymasterInput[0:4]); if (paymasterInputSelector == IPaymasterFlow.approvalBased.selector) { require( _transaction.paymasterInput.length >= 68, "The approvalBased paymaster input must be at least 68 bytes long" ); // While the actual data consists of address, uint256 and bytes data, // the data is needed only for the paymaster, so we ignore it here for the sake of optimization (address token, uint256 minAllowance) = abi.decode(_transaction.paymasterInput[4:68], (address, uint256)); address paymaster = address(uint160(_transaction.paymaster)); uint256 currentAllowance = IERC20(token).allowance(address(this), paymaster); if (currentAllowance < minAllowance) { // Some tokens, e.g. USDT require that the allowance is firsty set to zero // and only then updated to the new value. IERC20(token).safeApprove(paymaster, 0); IERC20(token).safeApprove(paymaster, minAllowance); } } else if (paymasterInputSelector == IPaymasterFlow.general.selector) { // Do nothing. general(bytes) paymaster flow means that the paymaster must interpret these bytes on his own. } else { revert("Unsupported paymaster flow"); } } /// @notice Pays the required fee for the transaction to the bootloader. /// @dev Currently it pays the maximum amount "_transaction.maxFeePerGas * _transaction.gasLimit", /// it will change in the future. function payToTheBootloader(Transaction calldata _transaction) internal returns (bool success) { address bootloaderAddr = BOOTLOADER_FORMAL_ADDRESS; uint256 amount = _transaction.maxFeePerGas * _transaction.gasLimit; assembly { success := call(gas(), bootloaderAddr, amount, 0, 0, 0, 0) } } // Returns the balance required to process the transaction. function totalRequiredBalance(Transaction calldata _transaction) internal pure returns (uint256 requiredBalance) { if (address(uint160(_transaction.paymaster)) != address(0)) { // Paymaster pays for the fee requiredBalance = _transaction.value; } else { // The user should have enough balance for both the fee and the value of the transaction requiredBalance = _transaction.maxFeePerGas * _transaction.gasLimit + _transaction.value; } } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.17; interface IInitable { event Inited(address indexed account); event Disabled(address indexed account); function init(bytes calldata initData) external; function disable() external; function isInited(address account) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; import "../interfaces/ITimestampAsserter.sol"; library TimestampAsserterLocator { function locate() internal view returns (ITimestampAsserter) { if (block.chainid == 260) { return ITimestampAsserter(address(0x00000000000000000000000000000000808012)); } else { return ITimestampAsserter(address(0x958F70e4Fd676c9CeAaFe5c48cB78CDD08b4880d)); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @author Matter Labs * @dev The interface that is used for encoding/decoding of * different types of paymaster flows. * @notice This is NOT an interface to be implementated * by contracts. It is just used for encoding. */ interface IPaymasterFlow { function general(bytes calldata input) external; function approvalBased(address _token, uint256 _minAllowance, bytes calldata _innerInput) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; interface ITimestampAsserter { function assertTimestampInRange(uint256 start, uint256 end) external view; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./interfaces/IAccountCodeStorage.sol"; import "./interfaces/INonceHolder.sol"; import "./interfaces/IContractDeployer.sol"; import "./interfaces/IKnownCodesStorage.sol"; import "./interfaces/IImmutableSimulator.sol"; import "./interfaces/IEthToken.sol"; import "./interfaces/IL1Messenger.sol"; import "./interfaces/ISystemContext.sol"; import "./interfaces/IBytecodeCompressor.sol"; import "./BootloaderUtilities.sol"; /// @dev All the system contracts introduced by zkSync have their addresses /// started from 2^15 in order to avoid collision with Ethereum precompiles. uint160 constant SYSTEM_CONTRACTS_OFFSET = 0x8000; // 2^15 /// @dev All the system contracts must be located in the kernel space, /// i.e. their addresses must be below 2^16. uint160 constant MAX_SYSTEM_CONTRACT_ADDRESS = 0xffff; // 2^16 - 1 address constant ECRECOVER_SYSTEM_CONTRACT = address(0x01); address constant SHA256_SYSTEM_CONTRACT = address(0x02); /// @dev The current maximum deployed precompile address. /// Note: currently only two precompiles are deployed: /// 0x01 - ecrecover /// 0x02 - sha256 /// Important! So the constant should be updated if more precompiles are deployed. uint256 constant CURRENT_MAX_PRECOMPILE_ADDRESS = uint256(uint160(SHA256_SYSTEM_CONTRACT)); address payable constant BOOTLOADER_FORMAL_ADDRESS = payable(address(SYSTEM_CONTRACTS_OFFSET + 0x01)); IAccountCodeStorage constant ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT = IAccountCodeStorage( address(SYSTEM_CONTRACTS_OFFSET + 0x02) ); INonceHolder constant NONCE_HOLDER_SYSTEM_CONTRACT = INonceHolder(address(SYSTEM_CONTRACTS_OFFSET + 0x03)); IKnownCodesStorage constant KNOWN_CODE_STORAGE_CONTRACT = IKnownCodesStorage(address(SYSTEM_CONTRACTS_OFFSET + 0x04)); IImmutableSimulator constant IMMUTABLE_SIMULATOR_SYSTEM_CONTRACT = IImmutableSimulator( address(SYSTEM_CONTRACTS_OFFSET + 0x05) ); IContractDeployer constant DEPLOYER_SYSTEM_CONTRACT = IContractDeployer(address(SYSTEM_CONTRACTS_OFFSET + 0x06)); // A contract that is allowed to deploy any codehash // on any address. To be used only during an upgrade. address constant FORCE_DEPLOYER = address(SYSTEM_CONTRACTS_OFFSET + 0x07); IL1Messenger constant L1_MESSENGER_CONTRACT = IL1Messenger(address(SYSTEM_CONTRACTS_OFFSET + 0x08)); address constant MSG_VALUE_SYSTEM_CONTRACT = address(SYSTEM_CONTRACTS_OFFSET + 0x09); IEthToken constant ETH_TOKEN_SYSTEM_CONTRACT = IEthToken(address(SYSTEM_CONTRACTS_OFFSET + 0x0a)); address constant KECCAK256_SYSTEM_CONTRACT = address(SYSTEM_CONTRACTS_OFFSET + 0x10); ISystemContext constant SYSTEM_CONTEXT_CONTRACT = ISystemContext(payable(address(SYSTEM_CONTRACTS_OFFSET + 0x0b))); BootloaderUtilities constant BOOTLOADER_UTILITIES = BootloaderUtilities(address(SYSTEM_CONTRACTS_OFFSET + 0x0c)); address constant EVENT_WRITER_CONTRACT = address(SYSTEM_CONTRACTS_OFFSET + 0x0d); IBytecodeCompressor constant BYTECODE_COMPRESSOR_CONTRACT = IBytecodeCompressor( address(SYSTEM_CONTRACTS_OFFSET + 0x0e) ); /// @dev If the bitwise AND of the extraAbi[2] param when calling the MSG_VALUE_SIMULATOR /// is non-zero, the call will be assumed to be a system one. uint256 constant MSG_VALUE_SIMULATOR_IS_SYSTEM_BIT = 1; /// @dev The maximal msg.value that context can have uint256 constant MAX_MSG_VALUE = 2 ** 128 - 1; /// @dev Prefix used during derivation of account addresses using CREATE2 /// @dev keccak256("zksyncCreate2") bytes32 constant CREATE2_PREFIX = 0x2020dba91b30cc0006188af794c2fb30dd8520db7e2c088b7fc7c103c00ca494; /// @dev Prefix used during derivation of account addresses using CREATE /// @dev keccak256("zksyncCreate") bytes32 constant CREATE_PREFIX = 0x63bae3a9951d38e8a3fbb7b70909afc1200610fc5bc55ade242f815974674f23;
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IContractDeployer { /// @notice Defines the version of the account abstraction protocol /// that a contract claims to follow. /// - `None` means that the account is just a contract and it should never be interacted /// with as a custom account /// - `Version1` means that the account follows the first version of the account abstraction protocol enum AccountAbstractionVersion { None, Version1 } /// @notice Defines the nonce ordering used by the account /// - `Sequential` means that it is expected that the nonces are monotonic and increment by 1 /// at a time (the same as EOAs). /// - `Arbitrary` means that the nonces for the accounts can be arbitrary. The operator /// should serve the transactions from such an account on a first-come-first-serve basis. /// @dev This ordering is more of a suggestion to the operator on how the AA expects its transactions /// to be processed and is not considered as a system invariant. enum AccountNonceOrdering { Sequential, Arbitrary } struct AccountInfo { AccountAbstractionVersion supportedAAVersion; AccountNonceOrdering nonceOrdering; } event ContractDeployed( address indexed deployerAddress, bytes32 indexed bytecodeHash, address indexed contractAddress ); event AccountNonceOrderingUpdated(address indexed accountAddress, AccountNonceOrdering nonceOrdering); event AccountVersionUpdated(address indexed accountAddress, AccountAbstractionVersion aaVersion); function getNewAddressCreate2( address _sender, bytes32 _bytecodeHash, bytes32 _salt, bytes calldata _input ) external view returns (address newAddress); function getNewAddressCreate(address _sender, uint256 _senderNonce) external pure returns (address newAddress); function create2( bytes32 _salt, bytes32 _bytecodeHash, bytes calldata _input ) external payable returns (address newAddress); function create2Account( bytes32 _salt, bytes32 _bytecodeHash, bytes calldata _input, AccountAbstractionVersion _aaVersion ) external payable returns (address newAddress); /// @dev While the `_salt` parameter is not used anywhere here, /// it is still needed for consistency between `create` and /// `create2` functions (required by the compiler). function create( bytes32 _salt, bytes32 _bytecodeHash, bytes calldata _input ) external payable returns (address newAddress); /// @dev While `_salt` is never used here, we leave it here as a parameter /// for the consistency with the `create` function. function createAccount( bytes32 _salt, bytes32 _bytecodeHash, bytes calldata _input, AccountAbstractionVersion _aaVersion ) external payable returns (address newAddress); /// @notice Returns the information about a certain AA. function getAccountInfo(address _address) external view returns (AccountInfo memory info); /// @notice Can be called by an account to update its account version function updateAccountVersion(AccountAbstractionVersion _version) external; /// @notice Can be called by an account to update its nonce ordering function updateNonceOrdering(AccountNonceOrdering _nonceOrdering) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; library RLPEncoder { function encodeAddress(address _val) internal pure returns (bytes memory encoded) { // The size is equal to 20 bytes of the address itself + 1 for encoding bytes length in RLP. encoded = new bytes(0x15); bytes20 shiftedVal = bytes20(_val); assembly { // In the first byte we write the encoded length as 0x80 + 0x14 == 0x94. mstore(add(encoded, 0x20), 0x9400000000000000000000000000000000000000000000000000000000000000) // Write address data without stripping zeros. mstore(add(encoded, 0x21), shiftedVal) } } function encodeUint256(uint256 _val) internal pure returns (bytes memory encoded) { unchecked { if (_val < 128) { encoded = new bytes(1); // Handle zero as a non-value, since stripping zeroes results in an empty byte array encoded[0] = (_val == 0) ? bytes1(uint8(128)) : bytes1(uint8(_val)); } else { uint256 hbs = _highestByteSet(_val); encoded = new bytes(hbs + 2); encoded[0] = bytes1(uint8(hbs + 0x81)); uint256 lbs = 31 - hbs; uint256 shiftedVal = _val << (lbs * 8); assembly { mstore(add(encoded, 0x21), shiftedVal) } } } } /// @notice Encodes the size of bytes in RLP format. /// @param _len The length of the bytes to encode. It has a `uint64` type since as larger values are not supported. /// NOTE: panics if the length is 1 since the length encoding is ambiguous in this case. function encodeNonSingleBytesLen(uint64 _len) internal pure returns (bytes memory) { assert(_len != 1); return _encodeLength(_len, 0x80); } /// @notice Encodes the size of list items in RLP format. /// @param _len The length of the bytes to encode. It has a `uint64` type since as larger values are not supported. function encodeListLen(uint64 _len) internal pure returns (bytes memory) { return _encodeLength(_len, 0xc0); } function _encodeLength(uint64 _len, uint256 _offset) private pure returns (bytes memory encoded) { unchecked { if (_len < 56) { encoded = new bytes(1); encoded[0] = bytes1(uint8(_len + _offset)); } else { uint256 hbs = _highestByteSet(uint256(_len)); encoded = new bytes(hbs + 2); encoded[0] = bytes1(uint8(_offset + hbs + 56)); uint256 lbs = 31 - hbs; uint256 shiftedVal = uint256(_len) << (lbs * 8); assembly { mstore(add(encoded, 0x21), shiftedVal) } } } } /// @notice Computes the index of the highest byte set in number. /// @notice Uses little endian ordering (The least significant byte has index `0`). /// NOTE: returns `0` for `0` function _highestByteSet(uint256 _number) private pure returns (uint256 hbs) { unchecked { if (_number > type(uint128).max) { _number >>= 128; hbs += 16; } if (_number > type(uint64).max) { _number >>= 64; hbs += 8; } if (_number > type(uint32).max) { _number >>= 32; hbs += 4; } if (_number > type(uint16).max) { _number >>= 16; hbs += 2; } if (_number > type(uint8).max) { hbs += 1; } } } }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.0; import "./SystemContractHelper.sol"; import "./Utils.sol"; import {SHA256_SYSTEM_CONTRACT, KECCAK256_SYSTEM_CONTRACT} from "../Constants.sol"; /** * @author Matter Labs * @notice This library is used to perform ultra-efficient calls using zkEVM-specific features. * @dev EVM calls always accept a memory slice as input and return a memory slice as output. * Therefore, even if the user has a ready-made calldata slice, they still need to copy it to memory * before calling. This is especially inefficient for large inputs (proxies, multi-calls, etc.). * In turn, zkEVM operates over a fat pointer, which is a set of (memory page, offset, start, length) in the memory/calldata/returndata. * This allows forwarding the calldata slice as is, without copying it to memory. * @dev Fat pointer is not just an integer, it is an extended data type supported on the VM level. * zkEVM creates the wellformed fat pointers for all the calldata/returndata regions, later * the contract may manipulate the already created fat pointers to forward a slice of the data, but not * to create new fat pointers! * @dev The allowed operation on fat pointers are: * 1. `ptr.add` - Transforms `ptr.offset` into `ptr.offset + u32(_value)`. If overflow happens then it panics. * 2. `ptr.sub` - Transforms `ptr.offset` into `ptr.offset - u32(_value)`. If underflow happens then it panics. * 3. `ptr.pack` - Do the concatenation between the lowest 128 bits of the pointer itself and the highest 128 bits of `_value`. It is typically used to prepare the ABI for external calls. * 4. `ptr.shrink` - Transforms `ptr.length` into `ptr.length - u32(_shrink)`. If underflow happens then it panics. * @dev The call opcodes accept the fat pointer and change it to its canonical form before passing it to the child call * 1. `ptr.start` is transformed into `ptr.offset + ptr.start` * 2. `ptr.length` is transformed into `ptr.length - ptr.offset` * 3. `ptr.offset` is transformed into `0` */ library EfficientCall { /// @notice Call the `keccak256` without copying calldata to memory. /// @param _data The preimage data. /// @return The `keccak256` hash. function keccak(bytes calldata _data) internal view returns (bytes32) { bytes memory returnData = staticCall(gasleft(), KECCAK256_SYSTEM_CONTRACT, _data); require(returnData.length == 32, "keccak256 returned invalid data"); return bytes32(returnData); } /// @notice Call the `sha256` precompile without copying calldata to memory. /// @param _data The preimage data. /// @return The `sha256` hash. function sha(bytes calldata _data) internal view returns (bytes32) { bytes memory returnData = staticCall(gasleft(), SHA256_SYSTEM_CONTRACT, _data); require(returnData.length == 32, "sha returned invalid data"); return bytes32(returnData); } /// @notice Perform a `call` without copying calldata to memory. /// @param _gas The gas to use for the call. /// @param _address The address to call. /// @param _value The `msg.value` to send. /// @param _data The calldata to use for the call. /// @param _isSystem Whether the call should contain the `isSystem` flag. /// @return returnData The copied to memory return data. function call( uint256 _gas, address _address, uint256 _value, bytes calldata _data, bool _isSystem ) internal returns (bytes memory returnData) { bool success = rawCall(_gas, _address, _value, _data, _isSystem); returnData = _verifyCallResult(success); } /// @notice Perform a `staticCall` without copying calldata to memory. /// @param _gas The gas to use for the call. /// @param _address The address to call. /// @param _data The calldata to use for the call. /// @return returnData The copied to memory return data. function staticCall( uint256 _gas, address _address, bytes calldata _data ) internal view returns (bytes memory returnData) { bool success = rawStaticCall(_gas, _address, _data); returnData = _verifyCallResult(success); } /// @notice Perform a `delegateCall` without copying calldata to memory. /// @param _gas The gas to use for the call. /// @param _address The address to call. /// @param _data The calldata to use for the call. /// @return returnData The copied to memory return data. function delegateCall( uint256 _gas, address _address, bytes calldata _data ) internal returns (bytes memory returnData) { bool success = rawDelegateCall(_gas, _address, _data); returnData = _verifyCallResult(success); } /// @notice Perform a `mimicCall` (a call with custom msg.sender) without copying calldata to memory. /// @param _gas The gas to use for the call. /// @param _address The address to call. /// @param _data The calldata to use for the call. /// @param _whoToMimic The `msg.sender` for the next call. /// @param _isConstructor Whether the call should contain the `isConstructor` flag. /// @param _isSystem Whether the call should contain the `isSystem` flag. /// @return returnData The copied to memory return data. function mimicCall( uint256 _gas, address _address, bytes calldata _data, address _whoToMimic, bool _isConstructor, bool _isSystem ) internal returns (bytes memory returnData) { bool success = rawMimicCall(_gas, _address, _data, _whoToMimic, _isConstructor, _isSystem); returnData = _verifyCallResult(success); } /// @notice Perform a `call` without copying calldata to memory. /// @param _gas The gas to use for the call. /// @param _address The address to call. /// @param _value The `msg.value` to send. /// @param _data The calldata to use for the call. /// @param _isSystem Whether the call should contain the `isSystem` flag. /// @return success whether the call was successful. function rawCall( uint256 _gas, address _address, uint256 _value, bytes calldata _data, bool _isSystem ) internal returns (bool success) { if (_value == 0) { _loadFarCallABIIntoActivePtr(_gas, _data, false, _isSystem); address callAddr = RAW_FAR_CALL_BY_REF_CALL_ADDRESS; assembly { success := call(_address, callAddr, 0, 0, 0xFFFF, 0, 0) } } else { _loadFarCallABIIntoActivePtr(_gas, _data, false, true); // If there is provided `msg.value` call the `MsgValueSimulator` to forward ether. address msgValueSimulator = MSG_VALUE_SYSTEM_CONTRACT; address callAddr = SYSTEM_CALL_BY_REF_CALL_ADDRESS; // We need to supply the mask to the MsgValueSimulator to denote // that the call should be a system one. uint256 forwardMask = _isSystem ? MSG_VALUE_SIMULATOR_IS_SYSTEM_BIT : 0; assembly { success := call(msgValueSimulator, callAddr, _value, _address, 0xFFFF, forwardMask, 0) } } } /// @notice Perform a `staticCall` without copying calldata to memory. /// @param _gas The gas to use for the call. /// @param _address The address to call. /// @param _data The calldata to use for the call. /// @return success whether the call was successful. function rawStaticCall(uint256 _gas, address _address, bytes calldata _data) internal view returns (bool success) { _loadFarCallABIIntoActivePtr(_gas, _data, false, false); address callAddr = RAW_FAR_CALL_BY_REF_CALL_ADDRESS; assembly { success := staticcall(_address, callAddr, 0, 0xFFFF, 0, 0) } } /// @notice Perform a `delegatecall` without copying calldata to memory. /// @param _gas The gas to use for the call. /// @param _address The address to call. /// @param _data The calldata to use for the call. /// @return success whether the call was successful. function rawDelegateCall(uint256 _gas, address _address, bytes calldata _data) internal returns (bool success) { _loadFarCallABIIntoActivePtr(_gas, _data, false, false); address callAddr = RAW_FAR_CALL_BY_REF_CALL_ADDRESS; assembly { success := delegatecall(_address, callAddr, 0, 0xFFFF, 0, 0) } } /// @notice Perform a `mimicCall` (call with custom msg.sender) without copying calldata to memory. /// @param _gas The gas to use for the call. /// @param _address The address to call. /// @param _data The calldata to use for the call. /// @param _whoToMimic The `msg.sender` for the next call. /// @param _isConstructor Whether the call should contain the `isConstructor` flag. /// @param _isSystem Whether the call should contain the `isSystem` flag. /// @return success whether the call was successful. /// @dev If called not in kernel mode, it will result in a revert (enforced by the VM) function rawMimicCall( uint256 _gas, address _address, bytes calldata _data, address _whoToMimic, bool _isConstructor, bool _isSystem ) internal returns (bool success) { _loadFarCallABIIntoActivePtr(_gas, _data, _isConstructor, _isSystem); address callAddr = MIMIC_CALL_BY_REF_CALL_ADDRESS; uint256 cleanupMask = ADDRESS_MASK; assembly { // Clearing values before usage in assembly, since Solidity // doesn't do it by default _whoToMimic := and(_whoToMimic, cleanupMask) success := call(_address, callAddr, 0, 0, _whoToMimic, 0, 0) } } /// @dev Verify that a low-level call was successful, and revert if it wasn't, by bubbling the revert reason. /// @param _success Whether the call was successful. /// @return returnData The copied to memory return data. function _verifyCallResult(bool _success) private pure returns (bytes memory returnData) { if (_success) { uint256 size; assembly { size := returndatasize() } returnData = new bytes(size); assembly { returndatacopy(add(returnData, 0x20), 0, size) } } else { propagateRevert(); } } /// @dev Propagate the revert reason from the current call to the caller. function propagateRevert() internal pure { assembly { let size := returndatasize() returndatacopy(0, 0, size) revert(0, size) } } /// @dev Load the far call ABI into active ptr, that will be used for the next call by reference. /// @param _gas The gas to be passed to the call. /// @param _data The calldata to be passed to the call. /// @param _isConstructor Whether the call is a constructor call. /// @param _isSystem Whether the call is a system call. function _loadFarCallABIIntoActivePtr( uint256 _gas, bytes calldata _data, bool _isConstructor, bool _isSystem ) private view { SystemContractHelper.loadCalldataIntoActivePtr(); // Currently, zkEVM considers the pointer valid if(ptr.offset < ptr.length || (ptr.length == 0 && ptr.offset == 0)), otherwise panics. // So, if the data is empty we need to make the `ptr.length = ptr.offset = 0`, otherwise follow standard logic. if (_data.length == 0) { // Safe to cast, offset is never bigger than `type(uint32).max` SystemContractHelper.ptrShrinkIntoActive(uint32(msg.data.length)); } else { uint256 dataOffset; assembly { dataOffset := _data.offset } // Safe to cast, offset is never bigger than `type(uint32).max` SystemContractHelper.ptrAddIntoActive(uint32(dataOffset)); // Safe to cast, `data.length` is never bigger than `type(uint32).max` uint32 shrinkTo = uint32(msg.data.length - (_data.length + dataOffset)); SystemContractHelper.ptrShrinkIntoActive(shrinkTo); } uint32 gas = Utils.safeCastToU32(_gas); uint256 farCallAbi = SystemContractsCaller.getFarCallABIWithEmptyFatPointer( gas, // Only rollup is supported for now 0, CalldataForwardingMode.ForwardFatPointer, _isConstructor, _isSystem ); SystemContractHelper.ptrPackIntoActivePtr(farCallAbi); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/IERC20Permit.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; function safeTransfer( IERC20 token, address to, uint256 value ) internal { _callOptionalReturn( token, abi.encodeWithSelector(token.transfer.selector, to, value) ); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn( token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value) ); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn( token, abi.encodeWithSelector(token.approve.selector, spender, value) ); } function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn( token, abi.encodeWithSelector( token.approve.selector, spender, newAllowance ) ); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require( oldAllowance >= value, "SafeERC20: decreased allowance below zero" ); uint256 newAllowance = oldAllowance - value; _callOptionalReturn( token, abi.encodeWithSelector( token.approve.selector, spender, newAllowance ) ); } } function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require( nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed" ); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall( data, "SafeERC20: low-level call failed" ); if (returndata.length > 0) { // Return data is optional require( abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed" ); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @author Matter Labs * @dev Interface of the nonce holder contract -- a contract used by the system to ensure * that there is always a unique identifier for a transaction with a particular account (we call it nonce). * In other words, the pair of (address, nonce) should always be unique. * @dev Custom accounts should use methods of this contract to store nonces or other possible unique identifiers * for the transaction. */ interface INonceHolder { event ValueSetUnderNonce(address indexed accountAddress, uint256 indexed key, uint256 value); /// @dev Returns the current minimal nonce for account. function getMinNonce(address _address) external view returns (uint256); /// @dev Returns the raw version of the current minimal nonce /// (equal to minNonce + 2^128 * deployment nonce). function getRawNonce(address _address) external view returns (uint256); /// @dev Increases the minimal nonce for the msg.sender. function increaseMinNonce(uint256 _value) external returns (uint256); /// @dev Sets the nonce value `key` as used. function setValueUnderNonce(uint256 _key, uint256 _value) external; /// @dev Gets the value stored inside a custom nonce. function getValueUnderNonce(uint256 _key) external view returns (uint256); /// @dev A convenience method to increment the minimal nonce if it is equal /// to the `_expectedNonce`. function incrementMinNonceIfEquals(uint256 _expectedNonce) external; /// @dev Returns the deployment nonce for the accounts used for CREATE opcode. function getDeploymentNonce(address _address) external view returns (uint256); /// @dev Increments the deployment nonce for the account and returns the previous one. function incrementDeploymentNonce(address _address) external returns (uint256); /// @dev Determines whether a certain nonce has been already used for an account. function validateNonceUsage(address _address, uint256 _key, bool _shouldBeUsed) external view; /// @dev Returns whether a nonce has been used for an account. function isNonceUsed(address _address, uint256 _nonce) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IAccountCodeStorage { function storeAccountConstructingCodeHash(address _address, bytes32 _hash) external; function storeAccountConstructedCodeHash(address _address, bytes32 _hash) external; function markAccountCodeHashAsConstructed(address _address) external; function getRawCodeHash(address _address) external view returns (bytes32 codeHash); function getCodeHash(uint256 _input) external view returns (bytes32 codeHash); function getCodeSize(uint256 _input) external view returns (uint256 codeSize); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IKnownCodesStorage { event MarkedAsKnown(bytes32 indexed bytecodeHash, bool indexed sendBytecodeToL1); function markFactoryDeps(bool _shouldSendToL1, bytes32[] calldata _hashes) external; function markBytecodeAsPublished( bytes32 _bytecodeHash, bytes32 _l1PreimageHash, uint256 _l1PreimageBytesLen ) external; function getMarker(bytes32 _hash) external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; struct ImmutableData { uint256 index; bytes32 value; } interface IImmutableSimulator { function getImmutable(address _dest, uint256 _index) external view returns (bytes32); function setImmutables(address _dest, ImmutableData[] calldata _immutables) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IL1Messenger { // Possibly in the future we will be able to track the messages sent to L1 with // some hooks in the VM. For now, it is much easier to track them with L2 events. event L1MessageSent(address indexed _sender, bytes32 indexed _hash, bytes _message); function sendToL1(bytes memory _message) external returns (bytes32); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IEthToken { function balanceOf(uint256) external view returns (uint256); function transferFromTo(address _from, address _to, uint256 _amount) external; function totalSupply() external view returns (uint256); function name() external pure returns (string memory); function symbol() external pure returns (string memory); function decimals() external pure returns (uint8); function mint(address _account, uint256 _amount) external; function withdraw(address _l1Receiver) external payable; event Mint(address indexed account, uint256 amount); event Transfer(address indexed from, address indexed to, uint256 value); event Withdrawal(address indexed _l2Sender, address indexed _l1Receiver, uint256 _amount); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IBytecodeCompressor { function publishCompressedBytecode( bytes calldata _bytecode, bytes calldata _rawCompressedData ) external payable returns (bytes32 bytecodeHash); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./interfaces/IBootloaderUtilities.sol"; import "./libraries/TransactionHelper.sol"; import "./libraries/RLPEncoder.sol"; import "./libraries/EfficientCall.sol"; /** * @author Matter Labs * @notice A contract that provides some utility methods for the bootloader * that is very hard to write in Yul. */ contract BootloaderUtilities is IBootloaderUtilities { using TransactionHelper for *; /// @notice Calculates the canonical transaction hash and the recommended transaction hash. /// @param _transaction The transaction. /// @return txHash and signedTxHash of the transaction, i.e. the transaction hash to be used in the explorer and commits to all /// the fields of the transaction and the recommended hash to be signed for this transaction. /// @dev txHash must be unique for all transactions. function getTransactionHashes( Transaction calldata _transaction ) external view override returns (bytes32 txHash, bytes32 signedTxHash) { signedTxHash = _transaction.encodeHash(); if (_transaction.txType == EIP_712_TX_TYPE) { txHash = keccak256(bytes.concat(signedTxHash, EfficientCall.keccak(_transaction.signature))); } else if (_transaction.txType == LEGACY_TX_TYPE) { txHash = encodeLegacyTransactionHash(_transaction); } else if (_transaction.txType == EIP_1559_TX_TYPE) { txHash = encodeEIP1559TransactionHash(_transaction); } else if (_transaction.txType == EIP_2930_TX_TYPE) { txHash = encodeEIP2930TransactionHash(_transaction); } else { revert("Unsupported tx type"); } } /// @notice Calculates the hash for a legacy transaction. /// @param _transaction The legacy transaction. /// @return txHash The hash of the transaction. function encodeLegacyTransactionHash(Transaction calldata _transaction) internal view returns (bytes32 txHash) { // Hash of legacy transactions are encoded as one of the: // - RLP(nonce, gasPrice, gasLimit, to, value, data, chainId, 0, 0) // - RLP(nonce, gasPrice, gasLimit, to, value, data) // // In this RLP encoding, only the first one above list appears, so we encode each element // inside list and then concatenate the length of all elements with them. bytes memory encodedNonce = RLPEncoder.encodeUint256(_transaction.nonce); // Encode `gasPrice` and `gasLimit` together to prevent "stack too deep error". bytes memory encodedGasParam; { bytes memory encodedGasPrice = RLPEncoder.encodeUint256(_transaction.maxFeePerGas); bytes memory encodedGasLimit = RLPEncoder.encodeUint256(_transaction.gasLimit); encodedGasParam = bytes.concat(encodedGasPrice, encodedGasLimit); } bytes memory encodedTo = RLPEncoder.encodeAddress(address(uint160(_transaction.to))); bytes memory encodedValue = RLPEncoder.encodeUint256(_transaction.value); // Encode only the length of the transaction data, and not the data itself, // so as not to copy to memory a potentially huge transaction data twice. bytes memory encodedDataLength; { // Safe cast, because the length of the transaction data can't be so large. uint64 txDataLen = uint64(_transaction.data.length); if (txDataLen != 1) { // If the length is not equal to one, then only using the length can it be encoded definitely. encodedDataLength = RLPEncoder.encodeNonSingleBytesLen(txDataLen); } else if (_transaction.data[0] >= 0x80) { // If input is a byte in [0x80, 0xff] range, RLP encoding will concatenates 0x81 with the byte. encodedDataLength = hex"81"; } // Otherwise the length is not encoded at all. } bytes memory rEncoded; { uint256 rInt = uint256(bytes32(_transaction.signature[0:32])); rEncoded = RLPEncoder.encodeUint256(rInt); } bytes memory sEncoded; { uint256 sInt = uint256(bytes32(_transaction.signature[32:64])); sEncoded = RLPEncoder.encodeUint256(sInt); } bytes memory vEncoded; { uint256 vInt = uint256(uint8(_transaction.signature[64])); require(vInt == 27 || vInt == 28, "Invalid v value"); // If the `chainId` is specified in the transaction, then the `v` value is encoded as // `35 + y + 2 * chainId == vInt + 8 + 2 * chainId`, where y - parity bit (see EIP-155). if (_transaction.reserved[0] != 0) { vInt += 8 + block.chainid * 2; } vEncoded = RLPEncoder.encodeUint256(vInt); } bytes memory encodedListLength; unchecked { uint256 listLength = encodedNonce.length + encodedGasParam.length + encodedTo.length + encodedValue.length + encodedDataLength.length + _transaction.data.length + rEncoded.length + sEncoded.length + vEncoded.length; // Safe cast, because the length of the list can't be so large. encodedListLength = RLPEncoder.encodeListLen(uint64(listLength)); } return keccak256( bytes.concat( encodedListLength, encodedNonce, encodedGasParam, encodedTo, encodedValue, encodedDataLength, _transaction.data, vEncoded, rEncoded, sEncoded ) ); } /// @notice Calculates the hash for an EIP2930 transaction. /// @param _transaction The EIP2930 transaction. /// @return txHash The hash of the transaction. function encodeEIP2930TransactionHash(Transaction calldata _transaction) internal view returns (bytes32) { // Encode all fixed-length params to avoid "stack too deep error" bytes memory encodedFixedLengthParams; { bytes memory encodedChainId = RLPEncoder.encodeUint256(block.chainid); bytes memory encodedNonce = RLPEncoder.encodeUint256(_transaction.nonce); bytes memory encodedGasPrice = RLPEncoder.encodeUint256(_transaction.maxFeePerGas); bytes memory encodedGasLimit = RLPEncoder.encodeUint256(_transaction.gasLimit); bytes memory encodedTo = RLPEncoder.encodeAddress(address(uint160(_transaction.to))); bytes memory encodedValue = RLPEncoder.encodeUint256(_transaction.value); encodedFixedLengthParams = bytes.concat( encodedChainId, encodedNonce, encodedGasPrice, encodedGasLimit, encodedTo, encodedValue ); } // Encode only the length of the transaction data, and not the data itself, // so as not to copy to memory a potentially huge transaction data twice. bytes memory encodedDataLength; { // Safe cast, because the length of the transaction data can't be so large. uint64 txDataLen = uint64(_transaction.data.length); if (txDataLen != 1) { // If the length is not equal to one, then only using the length can it be encoded definitely. encodedDataLength = RLPEncoder.encodeNonSingleBytesLen(txDataLen); } else if (_transaction.data[0] >= 0x80) { // If input is a byte in [0x80, 0xff] range, RLP encoding will concatenates 0x81 with the byte. encodedDataLength = hex"81"; } // Otherwise the length is not encoded at all. } // On zkSync, access lists are always zero length (at least for now). bytes memory encodedAccessListLength = RLPEncoder.encodeListLen(0); bytes memory rEncoded; { uint256 rInt = uint256(bytes32(_transaction.signature[0:32])); rEncoded = RLPEncoder.encodeUint256(rInt); } bytes memory sEncoded; { uint256 sInt = uint256(bytes32(_transaction.signature[32:64])); sEncoded = RLPEncoder.encodeUint256(sInt); } bytes memory vEncoded; { uint256 vInt = uint256(uint8(_transaction.signature[64])); require(vInt == 27 || vInt == 28, "Invalid v value"); vEncoded = RLPEncoder.encodeUint256(vInt - 27); } bytes memory encodedListLength; unchecked { uint256 listLength = encodedFixedLengthParams.length + encodedDataLength.length + _transaction.data.length + encodedAccessListLength.length + rEncoded.length + sEncoded.length + vEncoded.length; // Safe cast, because the length of the list can't be so large. encodedListLength = RLPEncoder.encodeListLen(uint64(listLength)); } return keccak256( bytes.concat( "\x01", encodedListLength, encodedFixedLengthParams, encodedDataLength, _transaction.data, encodedAccessListLength, vEncoded, rEncoded, sEncoded ) ); } /// @notice Calculates the hash for an EIP1559 transaction. /// @param _transaction The legacy transaction. /// @return txHash The hash of the transaction. function encodeEIP1559TransactionHash(Transaction calldata _transaction) internal view returns (bytes32) { // The formula for hash of EIP1559 transaction in the original proposal: // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1559.md // Encode all fixed-length params to avoid "stack too deep error" bytes memory encodedFixedLengthParams; { bytes memory encodedChainId = RLPEncoder.encodeUint256(block.chainid); bytes memory encodedNonce = RLPEncoder.encodeUint256(_transaction.nonce); bytes memory encodedMaxPriorityFeePerGas = RLPEncoder.encodeUint256(_transaction.maxPriorityFeePerGas); bytes memory encodedMaxFeePerGas = RLPEncoder.encodeUint256(_transaction.maxFeePerGas); bytes memory encodedGasLimit = RLPEncoder.encodeUint256(_transaction.gasLimit); bytes memory encodedTo = RLPEncoder.encodeAddress(address(uint160(_transaction.to))); bytes memory encodedValue = RLPEncoder.encodeUint256(_transaction.value); encodedFixedLengthParams = bytes.concat( encodedChainId, encodedNonce, encodedMaxPriorityFeePerGas, encodedMaxFeePerGas, encodedGasLimit, encodedTo, encodedValue ); } // Encode only the length of the transaction data, and not the data itself, // so as not to copy to memory a potentially huge transaction data twice. bytes memory encodedDataLength; { // Safe cast, because the length of the transaction data can't be so large. uint64 txDataLen = uint64(_transaction.data.length); if (txDataLen != 1) { // If the length is not equal to one, then only using the length can it be encoded definitely. encodedDataLength = RLPEncoder.encodeNonSingleBytesLen(txDataLen); } else if (_transaction.data[0] >= 0x80) { // If input is a byte in [0x80, 0xff] range, RLP encoding will concatenates 0x81 with the byte. encodedDataLength = hex"81"; } // Otherwise the length is not encoded at all. } // On zkSync, access lists are always zero length (at least for now). bytes memory encodedAccessListLength = RLPEncoder.encodeListLen(0); bytes memory rEncoded; { uint256 rInt = uint256(bytes32(_transaction.signature[0:32])); rEncoded = RLPEncoder.encodeUint256(rInt); } bytes memory sEncoded; { uint256 sInt = uint256(bytes32(_transaction.signature[32:64])); sEncoded = RLPEncoder.encodeUint256(sInt); } bytes memory vEncoded; { uint256 vInt = uint256(uint8(_transaction.signature[64])); require(vInt == 27 || vInt == 28, "Invalid v value"); vEncoded = RLPEncoder.encodeUint256(vInt - 27); } bytes memory encodedListLength; unchecked { uint256 listLength = encodedFixedLengthParams.length + encodedDataLength.length + _transaction.data.length + encodedAccessListLength.length + rEncoded.length + sEncoded.length + vEncoded.length; // Safe cast, because the length of the list can't be so large. encodedListLength = RLPEncoder.encodeListLen(uint64(listLength)); } return keccak256( bytes.concat( "\x02", encodedListLength, encodedFixedLengthParams, encodedDataLength, _transaction.data, encodedAccessListLength, vEncoded, rEncoded, sEncoded ) ); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @author Matter Labs * @notice Contract that stores some of the context variables, that may be either * block-scoped, tx-scoped or system-wide. */ interface ISystemContext { function chainId() external view returns (uint256); function origin() external view returns (address); function gasPrice() external view returns (uint256); function blockGasLimit() external view returns (uint256); function coinbase() external view returns (address); function difficulty() external view returns (uint256); function baseFee() external view returns (uint256); function blockHash(uint256 _block) external view returns (bytes32); function getBlockHashEVM(uint256 _block) external view returns (bytes32); function getBlockNumberAndTimestamp() external view returns (uint256 blockNumber, uint256 blockTimestamp); // Note, that for now, the implementation of the bootloader allows this variables to // be incremented multiple times inside a block, so it should not relied upon right now. function getBlockNumber() external view returns (uint256); function getBlockTimestamp() external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import "./EfficientCall.sol"; /** * @author Matter Labs * @dev Common utilities used in zkSync system contracts */ library Utils { /// @dev Bit mask of bytecode hash "isConstructor" marker bytes32 constant IS_CONSTRUCTOR_BYTECODE_HASH_BIT_MASK = 0x00ff000000000000000000000000000000000000000000000000000000000000; /// @dev Bit mask to set the "isConstructor" marker in the bytecode hash bytes32 constant SET_IS_CONSTRUCTOR_MARKER_BIT_MASK = 0x0001000000000000000000000000000000000000000000000000000000000000; function safeCastToU128(uint256 _x) internal pure returns (uint128) { require(_x <= type(uint128).max, "Overflow"); return uint128(_x); } function safeCastToU32(uint256 _x) internal pure returns (uint32) { require(_x <= type(uint32).max, "Overflow"); return uint32(_x); } function safeCastToU24(uint256 _x) internal pure returns (uint24) { require(_x <= type(uint24).max, "Overflow"); return uint24(_x); } /// @return codeLength The bytecode length in bytes function bytecodeLenInBytes(bytes32 _bytecodeHash) internal pure returns (uint256 codeLength) { codeLength = bytecodeLenInWords(_bytecodeHash) << 5; // _bytecodeHash * 32 } /// @return codeLengthInWords The bytecode length in machine words function bytecodeLenInWords(bytes32 _bytecodeHash) internal pure returns (uint256 codeLengthInWords) { unchecked { codeLengthInWords = uint256(uint8(_bytecodeHash[2])) * 256 + uint256(uint8(_bytecodeHash[3])); } } /// @notice Denotes whether bytecode hash corresponds to a contract that already constructed function isContractConstructed(bytes32 _bytecodeHash) internal pure returns (bool) { return _bytecodeHash[1] == 0x00; } /// @notice Denotes whether bytecode hash corresponds to a contract that is on constructor or has already been constructed function isContractConstructing(bytes32 _bytecodeHash) internal pure returns (bool) { return _bytecodeHash[1] == 0x01; } /// @notice Sets "isConstructor" flag to TRUE for the bytecode hash /// @param _bytecodeHash The bytecode hash for which it is needed to set the constructing flag /// @return The bytecode hash with "isConstructor" flag set to TRUE function constructingBytecodeHash(bytes32 _bytecodeHash) internal pure returns (bytes32) { // Clear the "isConstructor" marker and set it to 0x01. return constructedBytecodeHash(_bytecodeHash) | SET_IS_CONSTRUCTOR_MARKER_BIT_MASK; } /// @notice Sets "isConstructor" flag to FALSE for the bytecode hash /// @param _bytecodeHash The bytecode hash for which it is needed to set the constructing flag /// @return The bytecode hash with "isConstructor" flag set to FALSE function constructedBytecodeHash(bytes32 _bytecodeHash) internal pure returns (bytes32) { return _bytecodeHash & ~IS_CONSTRUCTOR_BYTECODE_HASH_BIT_MASK; } /// @notice Validate the bytecode format and calculate its hash. /// @param _bytecode The bytecode to hash. /// @return hashedBytecode The 32-byte hash of the bytecode. /// Note: The function reverts the execution if the bytecode has non expected format: /// - Bytecode bytes length is not a multiple of 32 /// - Bytecode bytes length is not less than 2^21 bytes (2^16 words) /// - Bytecode words length is not odd function hashL2Bytecode(bytes calldata _bytecode) internal view returns (bytes32 hashedBytecode) { // Note that the length of the bytecode must be provided in 32-byte words. require(_bytecode.length % 32 == 0, "po"); uint256 bytecodeLenInWords = _bytecode.length / 32; require(bytecodeLenInWords < 2 ** 16, "pp"); // bytecode length must be less than 2^16 words require(bytecodeLenInWords % 2 == 1, "pr"); // bytecode length in words must be odd hashedBytecode = EfficientCall.sha(_bytecode) & 0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; // Setting the version of the hash hashedBytecode = (hashedBytecode | bytes32(uint256(1 << 248))); // Setting the length hashedBytecode = hashedBytecode | bytes32(bytecodeLenInWords << 224); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require( address(this).balance >= amount, "Address: insufficient balance" ); (bool success, ) = recipient.call{value: amount}(""); require( success, "Address: unable to send value, recipient may have reverted" ); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue( target, data, 0, "Address: low-level call failed" ); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue( target, data, value, "Address: low-level call with value failed" ); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require( address(this).balance >= value, "Address: insufficient balance for call" ); (bool success, bytes memory returndata) = target.call{value: value}( data ); return verifyCallResultFromTarget( target, success, returndata, errorMessage ); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall( target, data, "Address: low-level static call failed" ); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget( target, success, returndata, errorMessage ); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall( target, data, "Address: low-level delegate call failed" ); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget( target, success, returndata, errorMessage ); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8; import {MAX_SYSTEM_CONTRACT_ADDRESS, MSG_VALUE_SYSTEM_CONTRACT} from "../Constants.sol"; import "./SystemContractsCaller.sol"; import "./Utils.sol"; uint256 constant UINT32_MASK = 0xffffffff; uint256 constant UINT128_MASK = 0xffffffffffffffffffffffffffffffff; /// @dev The mask that is used to convert any uint256 to a proper address. /// It needs to be padded with `00` to be treated as uint256 by Solidity uint256 constant ADDRESS_MASK = 0x00ffffffffffffffffffffffffffffffffffffffff; struct ZkSyncMeta { uint32 gasPerPubdataByte; uint32 heapSize; uint32 auxHeapSize; uint8 shardId; uint8 callerShardId; uint8 codeShardId; } enum Global { CalldataPtr, CallFlags, ExtraABIData1, ExtraABIData2, ReturndataPtr } /** * @author Matter Labs * @notice Library used for accessing zkEVM-specific opcodes, needed for the development * of system contracts. * @dev While this library will be eventually available to public, some of the provided * methods won't work for non-system contracts. We will not recommend this library * for external use. */ library SystemContractHelper { /// @notice Send an L2Log to L1. /// @param _isService The `isService` flag. /// @param _key The `key` part of the L2Log. /// @param _value The `value` part of the L2Log. /// @dev The meaning of all these parameters is context-dependent, but they /// have no intrinsic meaning per se. function toL1(bool _isService, bytes32 _key, bytes32 _value) internal { address callAddr = TO_L1_CALL_ADDRESS; assembly { // Ensuring that the type is bool _isService := and(_isService, 1) // This `success` is always 0, but the method always succeeds // (except for the cases when there is not enough gas) let success := call(_isService, callAddr, _key, _value, 0xFFFF, 0, 0) } } /// @notice Get address of the currently executed code. /// @dev This allows differentiating between `call` and `delegatecall`. /// During the former `this` and `codeAddress` are the same, while /// during the latter they are not. function getCodeAddress() internal view returns (address addr) { address callAddr = CODE_ADDRESS_CALL_ADDRESS; assembly { addr := staticcall(0, callAddr, 0, 0xFFFF, 0, 0) } } /// @notice Provide a compiler hint, by placing calldata fat pointer into virtual `ACTIVE_PTR`, /// that can be manipulated by `ptr.add`/`ptr.sub`/`ptr.pack`/`ptr.shrink` later. /// @dev This allows making a call by forwarding calldata pointer to the child call. /// It is a much more efficient way to forward calldata, than standard EVM bytes copying. function loadCalldataIntoActivePtr() internal view { address callAddr = LOAD_CALLDATA_INTO_ACTIVE_PTR_CALL_ADDRESS; assembly { pop(staticcall(0, callAddr, 0, 0xFFFF, 0, 0)) } } /// @notice Compiler simulation of the `ptr.pack` opcode for the virtual `ACTIVE_PTR` pointer. /// @dev Do the concatenation between lowest part of `ACTIVE_PTR` and highest part of `_farCallAbi` /// forming packed fat pointer for a far call or ret ABI when necessary. /// Note: Panics if the lowest 128 bits of `_farCallAbi` are not zeroes. function ptrPackIntoActivePtr(uint256 _farCallAbi) internal view { address callAddr = PTR_PACK_INTO_ACTIVE_CALL_ADDRESS; assembly { pop(staticcall(_farCallAbi, callAddr, 0, 0xFFFF, 0, 0)) } } /// @notice Compiler simulation of the `ptr.add` opcode for the virtual `ACTIVE_PTR` pointer. /// @dev Transforms `ACTIVE_PTR.offset` into `ACTIVE_PTR.offset + u32(_value)`. If overflow happens then it panics. function ptrAddIntoActive(uint32 _value) internal view { address callAddr = PTR_ADD_INTO_ACTIVE_CALL_ADDRESS; uint256 cleanupMask = UINT32_MASK; assembly { // Clearing input params as they are not cleaned by Solidity by default _value := and(_value, cleanupMask) pop(staticcall(_value, callAddr, 0, 0xFFFF, 0, 0)) } } /// @notice Compiler simulation of the `ptr.shrink` opcode for the virtual `ACTIVE_PTR` pointer. /// @dev Transforms `ACTIVE_PTR.length` into `ACTIVE_PTR.length - u32(_shrink)`. If underflow happens then it panics. function ptrShrinkIntoActive(uint32 _shrink) internal view { address callAddr = PTR_SHRINK_INTO_ACTIVE_CALL_ADDRESS; uint256 cleanupMask = UINT32_MASK; assembly { // Clearing input params as they are not cleaned by Solidity by default _shrink := and(_shrink, cleanupMask) pop(staticcall(_shrink, callAddr, 0, 0xFFFF, 0, 0)) } } /// @notice packs precompile parameters into one word /// @param _inputMemoryOffset The memory offset in 32-byte words for the input data for calling the precompile. /// @param _inputMemoryLength The length of the input data in words. /// @param _outputMemoryOffset The memory offset in 32-byte words for the output data. /// @param _outputMemoryLength The length of the output data in words. /// @param _perPrecompileInterpreted The constant, the meaning of which is defined separately for /// each precompile. For information, please read the documentation of the precompilecall log in /// the VM. function packPrecompileParams( uint32 _inputMemoryOffset, uint32 _inputMemoryLength, uint32 _outputMemoryOffset, uint32 _outputMemoryLength, uint64 _perPrecompileInterpreted ) internal pure returns (uint256 rawParams) { rawParams = _inputMemoryOffset; rawParams |= uint256(_inputMemoryLength) << 32; rawParams |= uint256(_outputMemoryOffset) << 64; rawParams |= uint256(_outputMemoryLength) << 96; rawParams |= uint256(_perPrecompileInterpreted) << 192; } /// @notice Call precompile with given parameters. /// @param _rawParams The packed precompile params. They can be retrieved by /// the `packPrecompileParams` method. /// @param _gasToBurn The number of gas to burn during this call. /// @return success Whether the call was successful. /// @dev The list of currently available precompiles sha256, keccak256, ecrecover. /// NOTE: The precompile type depends on `this` which calls precompile, which means that only /// system contracts corresponding to the list of precompiles above can do `precompileCall`. /// @dev If used not in the `sha256`, `keccak256` or `ecrecover` contracts, it will just burn the gas provided. function precompileCall(uint256 _rawParams, uint32 _gasToBurn) internal view returns (bool success) { address callAddr = PRECOMPILE_CALL_ADDRESS; // After `precompileCall` gas will be burned down to 0 if there are not enough of them, // thats why it should be checked before the call. require(gasleft() >= _gasToBurn); uint256 cleanupMask = UINT32_MASK; assembly { // Clearing input params as they are not cleaned by Solidity by default _gasToBurn := and(_gasToBurn, cleanupMask) success := staticcall(_rawParams, callAddr, _gasToBurn, 0xFFFF, 0, 0) } } /// @notice Set `msg.value` to next far call. /// @param _value The msg.value that will be used for the *next* call. /// @dev If called not in kernel mode, it will result in a revert (enforced by the VM) function setValueForNextFarCall(uint128 _value) internal returns (bool success) { uint256 cleanupMask = UINT128_MASK; address callAddr = SET_CONTEXT_VALUE_CALL_ADDRESS; assembly { // Clearing input params as they are not cleaned by Solidity by default _value := and(_value, cleanupMask) success := call(0, callAddr, _value, 0, 0xFFFF, 0, 0) } } /// @notice Initialize a new event. /// @param initializer The event initializing value. /// @param value1 The first topic or data chunk. function eventInitialize(uint256 initializer, uint256 value1) internal { address callAddr = EVENT_INITIALIZE_ADDRESS; assembly { pop(call(initializer, callAddr, value1, 0, 0xFFFF, 0, 0)) } } /// @notice Continue writing the previously initialized event. /// @param value1 The first topic or data chunk. /// @param value2 The second topic or data chunk. function eventWrite(uint256 value1, uint256 value2) internal { address callAddr = EVENT_WRITE_ADDRESS; assembly { pop(call(value1, callAddr, value2, 0, 0xFFFF, 0, 0)) } } /// @notice Get the packed representation of the `ZkSyncMeta` from the current context. /// @return meta The packed representation of the ZkSyncMeta. /// @dev The fields in ZkSyncMeta are NOT tightly packed, i.e. there is a special rule on how /// they are packed. For more information, please read the documentation on ZkSyncMeta. function getZkSyncMetaBytes() internal view returns (uint256 meta) { address callAddr = META_CALL_ADDRESS; assembly { meta := staticcall(0, callAddr, 0, 0xFFFF, 0, 0) } } /// @notice Returns the bits [offset..offset+size-1] of the meta. /// @param meta Packed representation of the ZkSyncMeta. /// @param offset The offset of the bits. /// @param size The size of the extracted number in bits. /// @return result The extracted number. function extractNumberFromMeta(uint256 meta, uint256 offset, uint256 size) internal pure returns (uint256 result) { // Firstly, we delete all the bits after the field uint256 shifted = (meta << (256 - size - offset)); // Then we shift everything back result = (shifted >> (256 - size)); } /// @notice Given the packed representation of `ZkSyncMeta`, retrieves the number of gas /// that a single byte sent to L1 as pubdata costs. /// @param meta Packed representation of the ZkSyncMeta. /// @return gasPerPubdataByte The current price in gas per pubdata byte. function getGasPerPubdataByteFromMeta(uint256 meta) internal pure returns (uint32 gasPerPubdataByte) { gasPerPubdataByte = uint32(extractNumberFromMeta(meta, META_GAS_PER_PUBDATA_BYTE_OFFSET, 32)); } /// @notice Given the packed representation of `ZkSyncMeta`, retrieves the number of the current size /// of the heap in bytes. /// @param meta Packed representation of the ZkSyncMeta. /// @return heapSize The size of the memory in bytes byte. /// @dev The following expression: getHeapSizeFromMeta(getZkSyncMetaBytes()) is /// equivalent to the MSIZE in Solidity. function getHeapSizeFromMeta(uint256 meta) internal pure returns (uint32 heapSize) { heapSize = uint32(extractNumberFromMeta(meta, META_HEAP_SIZE_OFFSET, 32)); } /// @notice Given the packed representation of `ZkSyncMeta`, retrieves the number of the current size /// of the auxilary heap in bytes. /// @param meta Packed representation of the ZkSyncMeta. /// @return auxHeapSize The size of the auxilary memory in bytes byte. /// @dev You can read more on auxilary memory in the VM1.2 documentation. function getAuxHeapSizeFromMeta(uint256 meta) internal pure returns (uint32 auxHeapSize) { auxHeapSize = uint32(extractNumberFromMeta(meta, META_AUX_HEAP_SIZE_OFFSET, 32)); } /// @notice Given the packed representation of `ZkSyncMeta`, retrieves the shardId of `this`. /// @param meta Packed representation of the ZkSyncMeta. /// @return shardId The shardId of `this`. /// @dev Currently only shard 0 (zkRollup) is supported. function getShardIdFromMeta(uint256 meta) internal pure returns (uint8 shardId) { shardId = uint8(extractNumberFromMeta(meta, META_SHARD_ID_OFFSET, 8)); } /// @notice Given the packed representation of `ZkSyncMeta`, retrieves the shardId of /// the msg.sender. /// @param meta Packed representation of the ZkSyncMeta. /// @return callerShardId The shardId of the msg.sender. /// @dev Currently only shard 0 (zkRollup) is supported. function getCallerShardIdFromMeta(uint256 meta) internal pure returns (uint8 callerShardId) { callerShardId = uint8(extractNumberFromMeta(meta, META_CALLER_SHARD_ID_OFFSET, 8)); } /// @notice Given the packed representation of `ZkSyncMeta`, retrieves the shardId of /// the currently executed code. /// @param meta Packed representation of the ZkSyncMeta. /// @return codeShardId The shardId of the currently executed code. /// @dev Currently only shard 0 (zkRollup) is supported. function getCodeShardIdFromMeta(uint256 meta) internal pure returns (uint8 codeShardId) { codeShardId = uint8(extractNumberFromMeta(meta, META_CODE_SHARD_ID_OFFSET, 8)); } /// @notice Retrieves the ZkSyncMeta structure. /// @return meta The ZkSyncMeta execution context parameters. function getZkSyncMeta() internal view returns (ZkSyncMeta memory meta) { uint256 metaPacked = getZkSyncMetaBytes(); meta.gasPerPubdataByte = getGasPerPubdataByteFromMeta(metaPacked); meta.shardId = getShardIdFromMeta(metaPacked); meta.callerShardId = getCallerShardIdFromMeta(metaPacked); meta.codeShardId = getCodeShardIdFromMeta(metaPacked); } /// @notice Returns the call flags for the current call. /// @return callFlags The bitmask of the callflags. /// @dev Call flags is the value of the first register /// at the start of the call. /// @dev The zero bit of the callFlags indicates whether the call is /// a constructor call. The first bit of the callFlags indicates whether /// the call is a system one. function getCallFlags() internal view returns (uint256 callFlags) { address callAddr = CALLFLAGS_CALL_ADDRESS; assembly { callFlags := staticcall(0, callAddr, 0, 0xFFFF, 0, 0) } } /// @notice Returns the current calldata pointer. /// @return ptr The current calldata pointer. /// @dev NOTE: This file is just an integer and it can not be used /// to forward the calldata to the next calls in any way. function getCalldataPtr() internal view returns (uint256 ptr) { address callAddr = PTR_CALLDATA_CALL_ADDRESS; assembly { ptr := staticcall(0, callAddr, 0, 0xFFFF, 0, 0) } } /// @notice Returns the N-th extraAbiParam for the current call. /// @return extraAbiData The value of the N-th extraAbiParam for this call. /// @dev It is equal to the value of the (N+2)-th register /// at the start of the call. function getExtraAbiData(uint256 index) internal view returns (uint256 extraAbiData) { require(index < 10, "There are only 10 accessible registers"); address callAddr = GET_EXTRA_ABI_DATA_ADDRESS; assembly { extraAbiData := staticcall(index, callAddr, 0, 0xFFFF, 0, 0) } } /// @notice Retuns whether the current call is a system call. /// @return `true` or `false` based on whether the current call is a system call. function isSystemCall() internal view returns (bool) { uint256 callFlags = getCallFlags(); // When the system call is passed, the 2-bit it set to 1 return (callFlags & 2) != 0; } /// @notice Returns whether the address is a system contract. /// @param _address The address to test /// @return `true` or `false` based on whether the `_address` is a system contract. function isSystemContract(address _address) internal pure returns (bool) { return uint160(_address) <= uint160(MAX_SYSTEM_CONTRACT_ADDRESS); } } /// @dev Solidity does not allow exporting modifiers via libraries, so /// the only way to do reuse modifiers is to have a base contract abstract contract ISystemContract { /// @notice Modifier that makes sure that the method /// can only be called via a system call. modifier onlySystemCall() { require( SystemContractHelper.isSystemCall() || SystemContractHelper.isSystemContract(msg.sender), "This method require system call flag" ); _; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../libraries/TransactionHelper.sol"; interface IBootloaderUtilities { function getTransactionHashes( Transaction calldata _transaction ) external view returns (bytes32 txHash, bytes32 signedTxHash); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8; import {MSG_VALUE_SYSTEM_CONTRACT, MSG_VALUE_SIMULATOR_IS_SYSTEM_BIT} from "../Constants.sol"; import "./Utils.sol"; // Addresses used for the compiler to be replaced with the // zkSync-specific opcodes during the compilation. // IMPORTANT: these are just compile-time constants and are used // only if used in-place by Yul optimizer. address constant TO_L1_CALL_ADDRESS = address((1 << 16) - 1); address constant CODE_ADDRESS_CALL_ADDRESS = address((1 << 16) - 2); address constant PRECOMPILE_CALL_ADDRESS = address((1 << 16) - 3); address constant META_CALL_ADDRESS = address((1 << 16) - 4); address constant MIMIC_CALL_CALL_ADDRESS = address((1 << 16) - 5); address constant SYSTEM_MIMIC_CALL_CALL_ADDRESS = address((1 << 16) - 6); address constant MIMIC_CALL_BY_REF_CALL_ADDRESS = address((1 << 16) - 7); address constant SYSTEM_MIMIC_CALL_BY_REF_CALL_ADDRESS = address((1 << 16) - 8); address constant RAW_FAR_CALL_CALL_ADDRESS = address((1 << 16) - 9); address constant RAW_FAR_CALL_BY_REF_CALL_ADDRESS = address((1 << 16) - 10); address constant SYSTEM_CALL_CALL_ADDRESS = address((1 << 16) - 11); address constant SYSTEM_CALL_BY_REF_CALL_ADDRESS = address((1 << 16) - 12); address constant SET_CONTEXT_VALUE_CALL_ADDRESS = address((1 << 16) - 13); address constant SET_PUBDATA_PRICE_CALL_ADDRESS = address((1 << 16) - 14); address constant INCREMENT_TX_COUNTER_CALL_ADDRESS = address((1 << 16) - 15); address constant PTR_CALLDATA_CALL_ADDRESS = address((1 << 16) - 16); address constant CALLFLAGS_CALL_ADDRESS = address((1 << 16) - 17); address constant PTR_RETURNDATA_CALL_ADDRESS = address((1 << 16) - 18); address constant EVENT_INITIALIZE_ADDRESS = address((1 << 16) - 19); address constant EVENT_WRITE_ADDRESS = address((1 << 16) - 20); address constant LOAD_CALLDATA_INTO_ACTIVE_PTR_CALL_ADDRESS = address((1 << 16) - 21); address constant LOAD_LATEST_RETURNDATA_INTO_ACTIVE_PTR_CALL_ADDRESS = address((1 << 16) - 22); address constant PTR_ADD_INTO_ACTIVE_CALL_ADDRESS = address((1 << 16) - 23); address constant PTR_SHRINK_INTO_ACTIVE_CALL_ADDRESS = address((1 << 16) - 24); address constant PTR_PACK_INTO_ACTIVE_CALL_ADDRESS = address((1 << 16) - 25); address constant MULTIPLICATION_HIGH_ADDRESS = address((1 << 16) - 26); address constant GET_EXTRA_ABI_DATA_ADDRESS = address((1 << 16) - 27); // All the offsets are in bits uint256 constant META_GAS_PER_PUBDATA_BYTE_OFFSET = 0 * 8; uint256 constant META_HEAP_SIZE_OFFSET = 8 * 8; uint256 constant META_AUX_HEAP_SIZE_OFFSET = 12 * 8; uint256 constant META_SHARD_ID_OFFSET = 28 * 8; uint256 constant META_CALLER_SHARD_ID_OFFSET = 29 * 8; uint256 constant META_CODE_SHARD_ID_OFFSET = 30 * 8; /// @notice The way to forward the calldata: /// - Use the current heap (i.e. the same as on EVM). /// - Use the auxiliary heap. /// - Forward via a pointer /// @dev Note, that currently, users do not have access to the auxiliary /// heap and so the only type of forwarding that will be used by the users /// are UseHeap and ForwardFatPointer for forwarding a slice of the current calldata /// to the next call. enum CalldataForwardingMode { UseHeap, ForwardFatPointer, UseAuxHeap } /** * @author Matter Labs * @notice A library that allows calling contracts with the `isSystem` flag. * @dev It is needed to call ContractDeployer and NonceHolder. */ library SystemContractsCaller { /// @notice Makes a call with the `isSystem` flag. /// @param gasLimit The gas limit for the call. /// @param to The address to call. /// @param value The value to pass with the transaction. /// @param data The calldata. /// @return success Whether the transaction has been successful. /// @dev Note, that the `isSystem` flag can only be set when calling system contracts. function systemCall(uint32 gasLimit, address to, uint256 value, bytes memory data) internal returns (bool success) { address callAddr = SYSTEM_CALL_CALL_ADDRESS; uint32 dataStart; assembly { dataStart := add(data, 0x20) } uint32 dataLength = uint32(Utils.safeCastToU32(data.length)); uint256 farCallAbi = SystemContractsCaller.getFarCallABI( 0, 0, dataStart, dataLength, gasLimit, // Only rollup is supported for now 0, CalldataForwardingMode.UseHeap, false, true ); if (value == 0) { // Doing the system call directly assembly { success := call(to, callAddr, 0, 0, farCallAbi, 0, 0) } } else { address msgValueSimulator = MSG_VALUE_SYSTEM_CONTRACT; // We need to supply the mask to the MsgValueSimulator to denote // that the call should be a system one. uint256 forwardMask = MSG_VALUE_SIMULATOR_IS_SYSTEM_BIT; assembly { success := call(msgValueSimulator, callAddr, value, to, farCallAbi, forwardMask, 0) } } } /// @notice Makes a call with the `isSystem` flag. /// @param gasLimit The gas limit for the call. /// @param to The address to call. /// @param value The value to pass with the transaction. /// @param data The calldata. /// @return success Whether the transaction has been successful. /// @return returnData The returndata of the transaction (revert reason in case the transaction has failed). /// @dev Note, that the `isSystem` flag can only be set when calling system contracts. function systemCallWithReturndata( uint32 gasLimit, address to, uint128 value, bytes memory data ) internal returns (bool success, bytes memory returnData) { success = systemCall(gasLimit, to, value, data); uint256 size; assembly { size := returndatasize() } returnData = new bytes(size); assembly { returndatacopy(add(returnData, 0x20), 0, size) } } /// @notice Makes a call with the `isSystem` flag. /// @param gasLimit The gas limit for the call. /// @param to The address to call. /// @param value The value to pass with the transaction. /// @param data The calldata. /// @return returnData The returndata of the transaction. In case the transaction reverts, the error /// bubbles up to the parent frame. /// @dev Note, that the `isSystem` flag can only be set when calling system contracts. function systemCallWithPropagatedRevert( uint32 gasLimit, address to, uint128 value, bytes memory data ) internal returns (bytes memory returnData) { bool success; (success, returnData) = systemCallWithReturndata(gasLimit, to, value, data); if (!success) { assembly { let size := mload(returnData) revert(add(returnData, 0x20), size) } } } /// @notice Calculates the packed representation of the FarCallABI. /// @param dataOffset Calldata offset in memory. Provide 0 unless using custom pointer. /// @param memoryPage Memory page to use. Provide 0 unless using custom pointer. /// @param dataStart The start of the calldata slice. Provide the offset in memory /// if not using custom pointer. /// @param dataLength The calldata length. Provide the length of the calldata in bytes /// unless using custom pointer. /// @param gasPassed The gas to pass with the call. /// @param shardId Of the account to call. Currently only 0 is supported. /// @param forwardingMode The forwarding mode to use: /// - provide CalldataForwardingMode.UseHeap when using your current memory /// - provide CalldataForwardingMode.ForwardFatPointer when using custom pointer. /// @param isConstructorCall Whether the call will be a call to the constructor /// (ignored when the caller is not a system contract). /// @param isSystemCall Whether the call will have the `isSystem` flag. /// @return farCallAbi The far call ABI. /// @dev The `FarCallABI` has the following structure: /// pub struct FarCallABI { /// pub memory_quasi_fat_pointer: FatPointer, /// pub gas_passed: u32, /// pub shard_id: u8, /// pub forwarding_mode: FarCallForwardPageType, /// pub constructor_call: bool, /// pub to_system: bool, /// } /// /// The FatPointer struct: /// /// pub struct FatPointer { /// pub offset: u32, // offset relative to `start` /// pub memory_page: u32, // memory page where slice is located /// pub start: u32, // absolute start of the slice /// pub length: u32, // length of the slice /// } /// /// @dev Note, that the actual layout is the following: /// /// [0..32) bits -- the calldata offset /// [32..64) bits -- the memory page to use. Can be left blank in most of the cases. /// [64..96) bits -- the absolute start of the slice /// [96..128) bits -- the length of the slice. /// [128..192) bits -- empty bits. /// [192..224) bits -- gasPassed. /// [224..232) bits -- forwarding_mode /// [232..240) bits -- shard id. /// [240..248) bits -- constructor call flag /// [248..256] bits -- system call flag function getFarCallABI( uint32 dataOffset, uint32 memoryPage, uint32 dataStart, uint32 dataLength, uint32 gasPassed, uint8 shardId, CalldataForwardingMode forwardingMode, bool isConstructorCall, bool isSystemCall ) internal pure returns (uint256 farCallAbi) { // Fill in the call parameter fields farCallAbi = getFarCallABIWithEmptyFatPointer( gasPassed, shardId, forwardingMode, isConstructorCall, isSystemCall ); // Fill in the fat pointer fields farCallAbi |= dataOffset; farCallAbi |= (uint256(memoryPage) << 32); farCallAbi |= (uint256(dataStart) << 64); farCallAbi |= (uint256(dataLength) << 96); } /// @notice Calculates the packed representation of the FarCallABI with zero fat pointer fields. /// @param gasPassed The gas to pass with the call. /// @param shardId Of the account to call. Currently only 0 is supported. /// @param forwardingMode The forwarding mode to use: /// - provide CalldataForwardingMode.UseHeap when using your current memory /// - provide CalldataForwardingMode.ForwardFatPointer when using custom pointer. /// @param isConstructorCall Whether the call will be a call to the constructor /// (ignored when the caller is not a system contract). /// @param isSystemCall Whether the call will have the `isSystem` flag. /// @return farCallAbiWithEmptyFatPtr The far call ABI with zero fat pointer fields. function getFarCallABIWithEmptyFatPointer( uint32 gasPassed, uint8 shardId, CalldataForwardingMode forwardingMode, bool isConstructorCall, bool isSystemCall ) internal pure returns (uint256 farCallAbiWithEmptyFatPtr) { farCallAbiWithEmptyFatPtr |= (uint256(gasPassed) << 192); farCallAbiWithEmptyFatPtr |= (uint256(forwardingMode) << 224); farCallAbiWithEmptyFatPtr |= (uint256(shardId) << 232); if (isConstructorCall) { farCallAbiWithEmptyFatPtr |= (1 << 240); } if (isSystemCall) { farCallAbiWithEmptyFatPtr |= (1 << 248); } } }
{ "evmVersion": "cancun", "optimizer": { "enabled": true, "mode": "3" }, "outputSelection": { "*": { "*": [ "abi" ] } }, "detectMissingLibraries": false, "forceEVMLA": false, "enableEraVMExtensions": true, "libraries": {} }
[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"Disabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"Inited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"bytes32","name":"sessionHash","type":"bytes32"},{"components":[{"internalType":"address","name":"signer","type":"address"},{"internalType":"uint256","name":"expiresAt","type":"uint256"},{"components":[{"internalType":"enum SessionLib.LimitType","name":"limitType","type":"uint8"},{"internalType":"uint256","name":"limit","type":"uint256"},{"internalType":"uint256","name":"period","type":"uint256"}],"internalType":"struct SessionLib.UsageLimit","name":"feeLimit","type":"tuple"},{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes4","name":"selector","type":"bytes4"},{"internalType":"uint256","name":"maxValuePerUse","type":"uint256"},{"components":[{"internalType":"enum SessionLib.LimitType","name":"limitType","type":"uint8"},{"internalType":"uint256","name":"limit","type":"uint256"},{"internalType":"uint256","name":"period","type":"uint256"}],"internalType":"struct SessionLib.UsageLimit","name":"valueLimit","type":"tuple"},{"components":[{"internalType":"enum SessionLib.Condition","name":"condition","type":"uint8"},{"internalType":"uint64","name":"index","type":"uint64"},{"internalType":"bytes32","name":"refValue","type":"bytes32"},{"components":[{"internalType":"enum SessionLib.LimitType","name":"limitType","type":"uint8"},{"internalType":"uint256","name":"limit","type":"uint256"},{"internalType":"uint256","name":"period","type":"uint256"}],"internalType":"struct SessionLib.UsageLimit","name":"limit","type":"tuple"}],"internalType":"struct SessionLib.Constraint[]","name":"constraints","type":"tuple[]"}],"internalType":"struct SessionLib.CallSpec[]","name":"callPolicies","type":"tuple[]"},{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint256","name":"maxValuePerUse","type":"uint256"},{"components":[{"internalType":"enum SessionLib.LimitType","name":"limitType","type":"uint8"},{"internalType":"uint256","name":"limit","type":"uint256"},{"internalType":"uint256","name":"period","type":"uint256"}],"internalType":"struct SessionLib.UsageLimit","name":"valueLimit","type":"tuple"}],"internalType":"struct SessionLib.TransferSpec[]","name":"transferPolicies","type":"tuple[]"}],"indexed":false,"internalType":"struct SessionLib.SessionSpec","name":"sessionSpec","type":"tuple"}],"name":"SessionCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"bytes32","name":"sessionHash","type":"bytes32"}],"name":"SessionRevoked","type":"event"},{"inputs":[{"internalType":"bytes","name":"sessionData","type":"bytes"}],"name":"addValidationKey","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"signer","type":"address"},{"internalType":"uint256","name":"expiresAt","type":"uint256"},{"components":[{"internalType":"enum SessionLib.LimitType","name":"limitType","type":"uint8"},{"internalType":"uint256","name":"limit","type":"uint256"},{"internalType":"uint256","name":"period","type":"uint256"}],"internalType":"struct SessionLib.UsageLimit","name":"feeLimit","type":"tuple"},{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes4","name":"selector","type":"bytes4"},{"internalType":"uint256","name":"maxValuePerUse","type":"uint256"},{"components":[{"internalType":"enum SessionLib.LimitType","name":"limitType","type":"uint8"},{"internalType":"uint256","name":"limit","type":"uint256"},{"internalType":"uint256","name":"period","type":"uint256"}],"internalType":"struct SessionLib.UsageLimit","name":"valueLimit","type":"tuple"},{"components":[{"internalType":"enum SessionLib.Condition","name":"condition","type":"uint8"},{"internalType":"uint64","name":"index","type":"uint64"},{"internalType":"bytes32","name":"refValue","type":"bytes32"},{"components":[{"internalType":"enum SessionLib.LimitType","name":"limitType","type":"uint8"},{"internalType":"uint256","name":"limit","type":"uint256"},{"internalType":"uint256","name":"period","type":"uint256"}],"internalType":"struct SessionLib.UsageLimit","name":"limit","type":"tuple"}],"internalType":"struct SessionLib.Constraint[]","name":"constraints","type":"tuple[]"}],"internalType":"struct SessionLib.CallSpec[]","name":"callPolicies","type":"tuple[]"},{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint256","name":"maxValuePerUse","type":"uint256"},{"components":[{"internalType":"enum SessionLib.LimitType","name":"limitType","type":"uint8"},{"internalType":"uint256","name":"limit","type":"uint256"},{"internalType":"uint256","name":"period","type":"uint256"}],"internalType":"struct SessionLib.UsageLimit","name":"valueLimit","type":"tuple"}],"internalType":"struct SessionLib.TransferSpec[]","name":"transferPolicies","type":"tuple[]"}],"internalType":"struct SessionLib.SessionSpec","name":"sessionSpec","type":"tuple"}],"name":"createSession","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"disable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum OperationType","name":"operationType","type":"uint8"},{"internalType":"bytes32","name":"signedHash","type":"bytes32"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"handleValidation","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"}],"name":"init","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"smartAccount","type":"address"}],"name":"isInited","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"sessionHash","type":"bytes32"}],"name":"revokeKey","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"sessionHashes","type":"bytes32[]"}],"name":"revokeKeys","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"components":[{"internalType":"address","name":"signer","type":"address"},{"internalType":"uint256","name":"expiresAt","type":"uint256"},{"components":[{"internalType":"enum SessionLib.LimitType","name":"limitType","type":"uint8"},{"internalType":"uint256","name":"limit","type":"uint256"},{"internalType":"uint256","name":"period","type":"uint256"}],"internalType":"struct SessionLib.UsageLimit","name":"feeLimit","type":"tuple"},{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes4","name":"selector","type":"bytes4"},{"internalType":"uint256","name":"maxValuePerUse","type":"uint256"},{"components":[{"internalType":"enum SessionLib.LimitType","name":"limitType","type":"uint8"},{"internalType":"uint256","name":"limit","type":"uint256"},{"internalType":"uint256","name":"period","type":"uint256"}],"internalType":"struct SessionLib.UsageLimit","name":"valueLimit","type":"tuple"},{"components":[{"internalType":"enum SessionLib.Condition","name":"condition","type":"uint8"},{"internalType":"uint64","name":"index","type":"uint64"},{"internalType":"bytes32","name":"refValue","type":"bytes32"},{"components":[{"internalType":"enum SessionLib.LimitType","name":"limitType","type":"uint8"},{"internalType":"uint256","name":"limit","type":"uint256"},{"internalType":"uint256","name":"period","type":"uint256"}],"internalType":"struct SessionLib.UsageLimit","name":"limit","type":"tuple"}],"internalType":"struct SessionLib.Constraint[]","name":"constraints","type":"tuple[]"}],"internalType":"struct SessionLib.CallSpec[]","name":"callPolicies","type":"tuple[]"},{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint256","name":"maxValuePerUse","type":"uint256"},{"components":[{"internalType":"enum SessionLib.LimitType","name":"limitType","type":"uint8"},{"internalType":"uint256","name":"limit","type":"uint256"},{"internalType":"uint256","name":"period","type":"uint256"}],"internalType":"struct SessionLib.UsageLimit","name":"valueLimit","type":"tuple"}],"internalType":"struct SessionLib.TransferSpec[]","name":"transferPolicies","type":"tuple[]"}],"internalType":"struct SessionLib.SessionSpec","name":"spec","type":"tuple"}],"name":"sessionState","outputs":[{"components":[{"internalType":"uint256","name":"expiresAt","type":"uint256"},{"internalType":"enum SessionLib.Status","name":"status","type":"uint8"},{"internalType":"uint256","name":"feesRemaining","type":"uint256"},{"components":[{"internalType":"uint256","name":"remaining","type":"uint256"},{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes4","name":"selector","type":"bytes4"},{"internalType":"uint256","name":"index","type":"uint256"}],"internalType":"struct SessionLib.LimitState[]","name":"transferValue","type":"tuple[]"},{"components":[{"internalType":"uint256","name":"remaining","type":"uint256"},{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes4","name":"selector","type":"bytes4"},{"internalType":"uint256","name":"index","type":"uint256"}],"internalType":"struct SessionLib.LimitState[]","name":"callValue","type":"tuple[]"},{"components":[{"internalType":"uint256","name":"remaining","type":"uint256"},{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes4","name":"selector","type":"bytes4"},{"internalType":"uint256","name":"index","type":"uint256"}],"internalType":"struct SessionLib.LimitState[]","name":"callParams","type":"tuple[]"}],"internalType":"struct SessionLib.SessionState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"sessionHash","type":"bytes32"}],"name":"sessionStatus","outputs":[{"internalType":"enum SessionLib.Status","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"signedHash","type":"bytes32"},{"components":[{"internalType":"uint256","name":"txType","type":"uint256"},{"internalType":"uint256","name":"from","type":"uint256"},{"internalType":"uint256","name":"to","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"gasPerPubdataByteLimit","type":"uint256"},{"internalType":"uint256","name":"maxFeePerGas","type":"uint256"},{"internalType":"uint256","name":"maxPriorityFeePerGas","type":"uint256"},{"internalType":"uint256","name":"paymaster","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256[4]","name":"reserved","type":"uint256[4]"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"bytes32[]","name":"factoryDeps","type":"bytes32[]"},{"internalType":"bytes","name":"paymasterInput","type":"bytes"},{"internalType":"bytes","name":"reservedDynamic","type":"bytes"}],"internalType":"struct Transaction","name":"transaction","type":"tuple"},{"internalType":"bytes","name":"hookData","type":"bytes"}],"name":"validationHook","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"}]
Contract Creation Code
3cda3351000000000000000000000000000000000000000000000000000000000000000001000701859a0357cde0497c6725f4413e3fbee6165146a5863175bb8b233bda00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x00030000000000020017000000000002000200000001035500000060031002700000068b0030019d0000008004000039000000400040043f0000000100200190000000a00000c13d0000068b02300197000000040020008c000006fd0000413d000000000301043b000000e0033002700000068d0030009c000000a80000213d000006970030009c000001b40000a13d000006980030009c000001e20000213d0000069b0030009c000002160000613d0000069c0030009c000006fd0000c13d000000240020008c000006fd0000413d0000000003000416000000000003004b000006fd0000c13d0000000403100370000000000303043b000006a00030009c000006fd0000213d0000002304300039000000000024004b000006fd0000813d0000000404300039000000000141034f000000000101043b001400000001001d000006a00010009c000006fd0000213d001300240030003d000000140100002900000005011002100000001301100029000000000021004b000006fd0000213d000000140000006b000005c80000613d0000000001000411001706a80010019b0000000002000019001500000002001d000000050120021000000013011000290000000201100367000000000101043b001600000001001d000000000010043f0000000101000039000000200010043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000006fd0000613d000000000101043b0000001702000029000000000020043f0000000101100039000000200010043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000006fd0000613d000000000101043b000000000101041a000000ff0110018f000000040010008c000005900000813d000000010010008c000007900000c13d0000001601000029000000000010043f0000000101000039000000200010043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000006fd0000613d000000000101043b0000001702000029000000000020043f0000000101100039000000200010043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000006fd0000613d000000000101043b000000000201041a000006f10220019700000002022001bf000000000021041b0000001701000029000000000010043f000000200000043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000006fd0000613d000000000101043b000000000201041a000000000002004b0000052b0000613d000000010220008a000000000021041b00000000010004140000068b0010009c0000068b01008041000000c001100210000006b8011001c70000800d020000390000000303000039000006e704000041000000000500041100000016060000291a0f1a050000040f0000000100200190000006fd0000613d00000015020000290000000102200039000000140020006c000000350000413d000005c80000013d0000000001000416000000000001004b000006fd0000c13d0000002001000039000001000010044300000120000004430000068c0100004100001a100001042e0000068e0030009c000001ce0000a13d0000068f0030009c000001ef0000213d000006920030009c000002270000613d000006930030009c000006fd0000c13d000000240020008c000006fd0000413d0000000003000416000000000003004b000006fd0000c13d0000000403100370000000000403043b000006a00040009c000006fd0000213d0000002303400039000000000023004b000006fd0000813d0000000405400039000000000351034f000000000303043b000006a00030009c000002100000213d0000001f07300039000006f2077001970000003f07700039000006f207700197000006a10070009c000002100000213d0000008007700039000000400070043f000000800030043f00000000043400190000002404400039000000000024004b000006fd0000213d0000002002500039000000000221034f000006f2043001980000001f0530018f000000a001400039000000da0000613d000000a006000039000000000702034f000000007807043c0000000006860436000000000016004b000000d60000c13d000000000005004b000000e70000613d000000000242034f0000000304500210000000000501043300000000054501cf000000000545022f000000000202043b0000010004400089000000000242022f00000000024201cf000000000252019f0000000000210435000000a0013000390000000000010435000000800100043d000000000001004b000001c40000613d001700000001001d000006a90010009c000006fd0000213d0000001701000029000000200010008c000006fd0000413d000000a00300043d000006a00030009c000006fd0000213d00000017010000290000008005100039001400800030003d000000140150006a000006a90010009c000006fd0000213d000000e00010008c000006fd0000413d000000400100043d001300000001001d000006b50010009c000002100000213d0000001301000029000000a001100039000000400010043f000000a0013000390000000001010433000006a80010009c000006fd0000213d0000001702000029000000a00220003900000013040000290000000001140436000000c00430003900000000040404330000000000410435000000e0043000390000000001420049000006a90010009c000006fd0000213d000000600010008c000006fd0000413d000000400100043d000006b20010009c000002100000213d0000006006100039000000400060043f0000000004040433000000020040008c000006fd0000213d0000000004410436000001000630003900000000060604330000000000640435000001200430003900000000040404330000004006100039000000000046043500000013040000290000004004400039000000000014043500000140013000390000000001010433000006a00010009c000006fd0000213d00000014041000290000003f01400039000000000021004b0000000007000019000006aa07008041000006aa01100197000006aa06200197000000000861013f000000000061004b0000000001000019000006aa01004041000006aa0080009c000000000107c019000000000001004b000006fd0000c13d0000002001400039001600000001001d0000000008010433000006a00080009c000002100000213d00000005018002100000003f07100039000006b107700197000000400a00043d00000000097a001900120000000a001d0000000000a9004b00000000070000390000000107004039000006a00090009c000002100000213d0000000100700190000002100000c13d000000400090043f000000120700002900000000008704350000004009400039001500000091001d000000150020006b000006fd0000213d000000000008004b000009130000c13d000000130100002900000060011000390000001204000029000000000041043500000160013000390000000001010433000006a00010009c000006fd0000213d00000014011000290000003f03100039000000000023004b0000000004000019000006aa04008041000006aa03300197000000000563013f000000000063004b0000000003000019000006aa03004041000006aa0050009c000000000304c019000000000003004b000006fd0000c13d00000020031000390000000005030433000006a00050009c000002100000213d00000005035002100000003f03300039000006b104300197000000400300043d0000000004430019000000000034004b00000000060000390000000106004039000006a00040009c000002100000213d0000000100600190000002100000c13d000000400040043f00000000005304350000004004100039000000a0015000c90000000005410019000000000025004b000006fd0000213d000000000054004b000001ae0000813d00000000060300190000000001420049000006a90010009c000006fd0000213d000000a00010008c000006fd0000413d000000400100043d000006b20010009c000002100000213d0000006007100039000000400070043f0000000078040434000006a80080009c000006fd0000213d000000000881043600000000070704330000000000780435000000400700043d000006b20070009c000002100000213d0000006008700039000000400080043f00000040084000390000000008080433000000020080008c000006fd0000213d000000200660003900000000088704360000006009400039000000000909043300000000009804350000008008400039000000000808043300000040097000390000000000890435000000400810003900000000007804350000000000160435000000a004400039000000000054004b000001860000413d0000001301000029000000800210003900000000003204351a0f15d00000040f0000001701000029000001c40000013d0000069d0030009c000005310000613d0000069e0030009c000005500000613d0000069f0030009c000006fd0000c13d000000240020008c000006fd0000413d0000000002000416000000000002004b000006fd0000c13d0000000401100370000000000101043b000006a80010009c000006fd0000213d1a0f18640000040f000000000001004b0000000001000039000000010100c039000000400200043d00000000001204350000068b0020009c0000068b020080410000004001200210000006a7011001c700001a100001042e000006940030009c000005460000613d000006950030009c000005640000613d000006960030009c000006fd0000c13d000000240020008c000006fd0000413d0000000003000416000000000003004b000006fd0000c13d0000000401100370000000000101043b000006a00010009c000006fd0000213d00000004011000391a0f13d20000040f1a0f15d00000040f000000000100001900001a100001042e000006990030009c000002e90000613d0000069a0030009c000006fd0000c13d0000000001000416000000000001004b000006fd0000c13d000000c001000039000000400010043f0000000501000039000000800010043f000006dc01000041000005580000013d000006900030009c0000030e0000613d000006910030009c000006fd0000c13d000000640020008c000006fd0000413d0000000003000416000000000003004b000006fd0000c13d0000000403100370000000000303043b000000010030008c000006fd0000213d0000002404100370000000000404043b0000004405100370000000000605043b000006a00060009c000006fd0000213d0000002305600039000000000025004b000006fd0000813d0000000407600039000000000571034f000000000505043b000006a00050009c000002100000213d0000001f09500039000006f2099001970000003f09900039000006f209900197000006a10090009c000006f60000a13d000006b601000041000000000010043f0000004101000039000000040010043f000006b70100004100001a11000104300000000001000416000000000001004b000006fd0000c13d000006de01000041000000800010043f0000000001000410000000840010043f00000000010004140000000002000411000006a802200197000000040020008c000005960000c13d0000000103000031000000200030008c00000020040000390000000004034019000005ba0000013d000000640020008c000006fd0000413d0000000003000416000000000003004b000006fd0000c13d0000000403100370000000000303043b001600000003001d0000002403100370000000000303043b001700000003001d000006a00030009c000006fd0000213d000000170720006a000006a90070009c000006fd0000213d000002640070008c000006fd0000413d0000004403100370000000000403043b000006a00040009c000006fd0000213d0000002303400039000000000023004b000006fd0000813d0000000403400039000000000331034f000000000603043b000006a00060009c000006fd0000213d001300240040003d0000001303600029001400000003001d000000000023004b000006fd0000213d000000000006004b000005c80000613d0000001703000029000001e403300039000000000331034f000000000303043b000000230570008a000006aa07300197000006aa08500197000000000987013f000000000087004b0000000007000019000006aa07004041000000000053004b0000000005000019000006aa05008041000006aa0090009c000000000705c019000000000007004b000006fd0000c13d0000001705000029001000040050003d0000001003300029000000000531034f000000000705043b000006a00070009c000006fd0000213d0000000002720049000000200a300039000006aa03200197000006aa05a00197000000000835013f000000000035004b0000000003000019000006aa0300404100000000002a004b0000000002000019000006aa02002041000006aa0080009c000000000302c019000000000003004b000006fd0000c13d000000600070008c000006fd0000413d0000000002a1034f000000000202043b000006a00020009c000006fd0000213d0000000007a700190000000002a200190000001f03200039000000000073004b0000000005000019000006aa05008041000006aa03300197001500000007001d000006aa08700197000000000983013f000000000083004b0000000003000019000006aa03004041000006aa0090009c000000000305c019000000000003004b000006fd0000c13d000000000321034f000000000903043b000006a00090009c000002100000213d0000001f03900039000006f2033001970000003f03300039000006f203300197000006a10030009c000002100000213d0000008003300039000000400030043f000000800090043f00000020022000390000000003290019000000150030006c000006fd0000213d000000000321034f000006f20b9001980000001f0c90018f000000a002b00039000002a70000613d000000a005000039000000000d03034f00000000de0d043c0000000005e50436000000000025004b000002a30000c13d00000000000c004b000002b40000613d0000000003b3034f0000000305c00210000000000b020433000000000b5b01cf000000000b5b022f000000000303043b0000010005500089000000000353022f00000000035301cf0000000003b3019f0000000000320435000000a00290003900000000000204350000002002a00039000000000321034f000000000303043b000f00000003001d000006a80030009c000006fd0000213d0000002002200039000000000221034f000000000202043b000006a00020009c000006fd0000213d0000000002a20019001200000002001d0000001f02200039000000150020006c0000000003000019000006aa03008041000006aa02200197000000000582013f000000000082004b0000000002000019000006aa02004041000006aa0050009c000000000203c019000000000002004b000006fd0000c13d0000001202100360000000000202043b000006a00020009c000002100000213d00000005032002100000003f05300039000006b105500197000000400b00043d00000000055b00190000000000b5004b00000000090000390000000109004039000006a00050009c000002100000213d0000000100900190000002100000c13d000000400050043f00000000002b04350000001202000029000000200c2000390000000003c30019001100000003001d000000150030006c000007040000a13d000006fd0000013d000000240020008c000006fd0000413d0000000003000416000000000003004b000006fd0000c13d0000000403100370000000000303043b000006a00030009c000006fd0000213d0000002304300039000000000024004b000006fd0000813d001600040030003d0000001601100360000000000101043b001700000001001d000006a00010009c000006fd0000213d00000017013000290000002401100039000000000021004b000006fd0000213d000006de01000041000000800010043f0000000001000410000000840010043f00000000010004140000000002000411000006a802200197000000040020008c001500000002001d000006540000c13d0000000103000031000000200030008c00000020040000390000000004034019000006780000013d000000440020008c000006fd0000413d0000000003000416000000000003004b000006fd0000c13d0000000403100370000000000303043b001500000003001d000006a80030009c000006fd0000213d0000002403100370000000000303043b001400000003001d000006a00030009c000006fd0000213d000000140320006a000006a90030009c000006fd0000213d000000e40030008c000006fd0000413d0000001404000029001300040040003d0000014004000039000000400040043f000000800000043f000000a00000043f000000c00000043f0000006004000039000000e00040043f000001000040043f000001200040043f00000013041003600000002005000039000001600050043f000000000404043b000006a80040009c000006fd0000213d000001800040043f00000013050000290000002004500039000000000441034f000000000404043b000001a00040043f0000004004500039000000000541034f000000000505043b000000020050008c000006fd0000213d000001c00050043f0000002005400039000000000551034f000000000505043b000001e00050043f0000004005400039000000000551034f000000000505043b000002000050043f001200600040003d0000001204100360000000000404043b000000230630008a000006aa03400197001006aa0060019b000000100530014f000000100030006c0000000003000019000006aa03004041001100000006001d000000000064004b0000000006000019000006aa06008041000006aa0050009c000000000306c019000000000003004b000006fd0000c13d00000014034000290000000404300039000000000441034f000000000404043b001700000004001d000006a00040009c000006fd0000213d0000002407300039000000170400002900000005044002100000000005420049000000000057004b0000000006000019000006aa06002041000006aa05500197001600000007001d000006aa07700197000000000857013f000000000057004b0000000005000019000006aa05004041000006aa0080009c000000000506c019000000000005004b000006fd0000c13d000000e005000039000002200050043f00000280054000390000001704000029000002600040043f000000000004004b000007bf0000c13d0000001203000029000f00200030003d0000000f03100360000000000303043b000006aa04300197000000100640014f000000100040006c0000000004000019000006aa04004041000000110030006c0000000007000019000006aa07008041000006aa0060009c000000000407c019000000000004004b000006fd0000c13d0000001304300029000000000341034f000000000303043b000006a00030009c000006fd0000213d0000002004400039000006f3063000d10000000002260019000000000024004b0000000006000019000006aa06002041000006aa02200197000006aa07400197000000000827013f000000000027004b0000000002000019000006aa02004041000006aa0080009c000000000206c019000000000002004b000006fd0000c13d000001800250008a000002400020043f0000000002350436000000000003004b000003c30000613d0000000005000019000000000641034f000000000606043b000006a80060009c000006fd0000213d00000000066204360000002007400039000000000771034f000000000707043b00000000007604350000004006400039000000000761034f000000000707043b000000020070008c000006fd0000213d000000400820003900000000007804350000002007600039000000000771034f000000000707043b000000600820003900000000007804350000004006600039000000000661034f000000000606043b00000080072000390000000000670435000000a004400039000000a0022000390000000105500039000000000035004b000003a40000413d000001210120008a000006f203100197000001600120008a000001400010043f000006ad0030009c000002100000213d0000014002300039000000400020043f0000068b0010009c0000068b01008041000000600110021000000000020004140000068b0020009c0000068b02008041000000c002200210000000000121019f000006ae011001c700008010020000391a0f1a0a0000040f0000000100200190000006fd0000613d000000000101043b000000000010043f0000000101000039000000200010043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000006fd0000613d000000000101043b000400000001001d000000400100043d000006b00010009c000002100000213d000000c002100039000000400020043f000000a0021000390000006003000039000000000032043500000080021000390000000000320435000000600210003900000000003204350000004002100039000000000002043500000020021000390000000000020435000000000001043500000002010003670000001202100360000000000302043b0000001302000029001700000000003500000000042000790000001f0240008a001206aa0020019b000006aa04300197000000120540014f000000120040006c0000000004000019000006aa04004041001600000002001d000000000023004b0000000006000019000006aa06008041000006aa0050009c000000000406c019000000000004004b000006fd0000c13d000000130a3000290000000003a1034f000000000603043b000006a00060009c000006fd0000213d0000002003a000390000000504600210001100000004001d0000001705400069000000000053004b0000000009000019000006aa09002041000006aa05500197000006aa0b300197000000000c5b013f00000000005b004b0000000005000019000006aa05004041000006aa00c0009c000000000509c019000000000005004b000006fd0000c13d000000000006004b0000000005000019000009aa0000c13d0000000f02100360000000000302043b000006aa02300197000000120420014f000000120020006c0000000002000019000006aa02004041000000160030006c0000000007000019000006aa07008041000006aa0040009c000000000207c019000000000002004b000006fd0000c13d0000001307300029000000000271034f000000000802043b000006a00080009c000006fd0000213d000006f3028000d100000017022000290000002004700039000000000024004b0000000007000019000006aa07002041000006aa02200197000006aa04400197000000000924013f000000000024004b0000000002000019000006aa02004041000006aa0090009c000000000207c019000000000002004b000006fd0000c13d00000005078002100000003f02700039000006b102200197000000400400043d0000000009240019000e00000004001d000000000049004b000000000a000039000000010a004039000006a00090009c000002100000213d0000000100a00190000002100000c13d000000400090043f0000000e020000290000000002820436001600000002001d000000000008004b0000046e0000613d0000000008000019000000400900043d000006a10090009c000002100000213d0000008002900039000000400020043f0000006002900039000000000002043500000040029000390000000000020435000000200290003900000000000204350000000000090435000000160280002900000000009204350000002008800039000000000078004b0000045d0000413d00000011020000290000003f02200039000006b102200197000000400400043d0000000007240019000300000004001d000000000047004b00000000080000390000000108004039000006a00070009c000002100000213d0000000100800190000002100000c13d000000400070043f00000003020000290000000002620436001200000002001d000000000006004b000004930000613d0000000006000019000000400700043d000006a10070009c000002100000213d0000008002700039000000400020043f0000006002700039000000000002043500000040027000390000000000020435000000200270003900000000000204350000000000070435000000120260002900000000007204350000002006600039000000110060006c000004820000413d000006a00050009c000002100000213d00000005045002100000003f02400039000006b102200197000000400700043d0000000006270019000900000007001d000000000076004b00000000070000390000000107004039000006a00060009c000002100000213d0000000100700190000002100000c13d000000400060043f00000009020000290000000002520436001100000002001d000000000005004b000004ba0000613d0000000005000019000000400600043d000006a10060009c000002100000213d0000008002600039000000400020043f0000006002600039000000000002043500000040026000390000000000020435000000200260003900000000000204350000000000060435000000110250002900000000006204350000002005500039000000000045004b000004a90000413d0000000e020000290000000002020433000000000002004b00000b0d0000c13d0000001501000029000606a80010019b00000003010000290000000001010433000000000001004b001600000000001d00000c140000c13d0000000901000029000000160200002900000000002104350000000601000029000000000010043f00000004010000290000000101100039000000200010043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000006fd0000613d000000000101043b000000000101041a000000ff0110018f001700000001001d000000030010008c000005900000213d0000001701000029000000010010008c000004f20000c13d0000000401000029000000000101041a001700000001001d000006b301000041000000000010044300000000010004140000068b0010009c0000068b01008041000000c001100210000006b4011001c70000800b020000391a0f1a0a0000040f0000000100200190000010c10000613d000000000101043b000000170010006c001700010000003d000004f20000a13d001700030000003d000000140100002900000044011000390000000001100079000006a90010009c000006fd0000213d000000600010008c000006fd0000413d000000400100043d000006b20010009c000002100000213d0000000402000029000000000202041a001600000002001d0000006002100039000000400020043f0000000f02000029000000800420008a0000000203000367000000000243034f000000000202043b000000020020008c000006fd0000213d00000020054000390000004004400039000000000443034f000000000353034f0000000005210436000000000303043b001300000005001d001400000003001d0000000000350435000000000304043b0000004001100039001500000003001d0000000000310435000000000002004b00000e420000613d000000010020008c00000ec90000c13d000000040100002900000002011000390000000602000029000000000020043f000000200010043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000006fd0000613d000000000101043b000000000101041a000000140110006b00000e430000813d000006b601000041000000000010043f0000001101000039000000040010043f000006b70100004100001a1100010430000000240020008c000006fd0000413d0000000002000416000000000002004b000006fd0000c13d0000000401100370000000000201043b000006ab00200198000006fd0000c13d000006eb0020009c0000000001000019000005ed0000213d0000000101000039000006ac02200197000006ec0020009c000005e80000213d000000000002004b000005ed0000613d000006ef0020009c000005ed0000613d000005ec0000013d000000240020008c000006fd0000413d0000000002000416000000000002004b000006fd0000c13d0000000401100370000000000101043b1a0f154c0000040f000000000100001900001a100001042e0000000001000416000000000001004b000006fd0000c13d000000c001000039000000400010043f0000001301000039000000800010043f000006ea01000041000000a00010043f0000002001000039000000c00010043f0000008001000039000000e0020000391a0f13a00000040f000000c00110008a0000068b0010009c0000068b010080410000006001100210000006dd011001c700001a100001042e000000440020008c000006fd0000413d0000000002000416000000000002004b000006fd0000c13d0000000402100370000000000202043b001700000002001d000006a80020009c000006fd0000213d0000002401100370000000000101043b001600000001001d000000000010043f0000000101000039000000200010043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000006fd0000613d000000000101043b0000001702000029000000000020043f0000000101100039000000200010043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000006fd0000613d000000000101043b000000000101041a000000ff0110018f000000030010008c000006d40000a13d000006b601000041000000000010043f0000002101000039000000040010043f000006b70100004100001a11000104300000068b0010009c0000068b01008041000000c001100210000006df011001c71a0f1a0a0000040f00000060031002700000068b03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000080057001bf000005aa0000613d0000008008000039000000000901034f000000009a09043c0000000008a80436000000000058004b000005a60000c13d000000000006004b000005b70000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000100000003001f0000000100200190000005ca0000613d0000001f01400039000000600110018f00000080011001bf000000400010043f000000200030008c000006fd0000413d000000800100043d000000000001004b0000000002000039000000010200c039000000000021004b000006fd0000c13d000000000001004b000005f00000c13d000000000100001900001a100001042e0000001f0530018f000006c206300198000000400200043d0000000004620019000005d50000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000005d10000c13d000000000005004b000005e20000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f000000000014043500000060013002100000068b0020009c0000068b020080410000004002200210000000000112019f00001a1100010430000006ed0020009c000005ed0000613d000006ee0020009c000005ed0000613d0000000001000019000000800010043f000006f00100004100001a100001042e000006bc0100004100000000001004430000000001000411000000040010044300000000010004140000068b0010009c0000068b01008041000000c001100210000006bf011001c700008002020000391a0f1a0a0000040f0000000100200190000010c10000613d000000000101043b000000000001004b000006fd0000613d000000400400043d000006e80100004100000000001404350000000001000410000006a8021001970000000401400039001700000002001d000000000021043500000000010004140000000002000411000000040020008c0000061d0000613d0000068b0040009c0000068b02000041000000000204401900000040022002100000068b0010009c0000068b01008041000000c001100210000000000121019f000006b7011001c70000000002000411001600000004001d1a0f1a050000040f000000160400002900000060031002700001068b0030019d0000000100200190000007a10000613d000006a00040009c000002100000213d000000400040043f000006bc0100004100000000001004430000000001000411000000040010044300000000010004140000068b0010009c0000068b01008041000000c001100210000006bf011001c700008002020000391a0f1a0a0000040f0000000100200190000010c10000613d000000000101043b000000000001004b000006fd0000613d000000400300043d000000240130003900000001020000390000000000210435000006e9010000410000000000130435001600000003001d00000004013000390000001702000029000000000021043500000000010004140000000002000411000000040020008c0000064d0000613d00000016020000290000068b0020009c0000068b0200804100000040022002100000068b0010009c0000068b01008041000000c001100210000000000121019f000006c1011001c700000000020004111a0f1a050000040f00000060031002700001068b0030019d0000000100200190000008550000613d0000001601000029000006a00010009c000002100000213d0000001601000029000000400010043f000000000100001900001a100001042e0000068b0010009c0000068b01008041000000c001100210000006df011001c71a0f1a0a0000040f000000800a00003900000060031002700000068b03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000080057001bf000006680000613d000000000801034f000000008908043c000000000a9a043600000000005a004b000006640000c13d000000000006004b000006750000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000100000003001f0000000100200190000007490000613d0000001f01400039000000600110018f00000080011001bf000000400010043f000000200030008c000006fd0000413d000000800100043d000000000001004b0000000002000039000000010200c039000000000021004b000006fd0000c13d000000000001004b000005c80000c13d0000001501000029000000000010043f000000200000043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000006fd0000613d000000400200043d001500000002001d000000000101043b000000000101041a000000000001004b000007ae0000c13d00000014010000390000001503000029000000000213043600000000010004100000006001100210001400000002001d0000000000120435000006e10030009c000002100000213d00000015010000290000004001100039000000400010043f000006bc0100004100000000001004430000000001000411000000040010044300000000010004140000068b0010009c0000068b01008041000000c001100210000006bf011001c700008002020000391a0f1a0a0000040f0000000100200190000010c10000613d000000000101043b000000000001004b000006fd0000613d000000400500043d000006e20100004100000000001504350000000401500039000000400200003900000000002104350000001501000029000000000101043300000044025000390000000000120435000006f2041001970000001f0310018f001500000005001d0000006402500039000000140020006b000008620000813d000000000004004b000006d00000613d00000014063000290000000005320019000000200550008a000000200660008a0000000007450019000000000846001900000000080804330000000000870435000000200440008c000006ca0000c13d000000000003004b000008790000613d00000000050200190000086e0000013d000000010010008c000001c70000c13d0000001601000029000000000010043f0000000101000039000000200010043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000006fd0000613d000000000101043b000000000101041a001700000001001d000006b301000041000000000010044300000000010004140000068b0010009c0000068b01008041000000c001100210000006b4011001c70000800b020000391a0f1a0a0000040f0000000100200190000010c10000613d000000000101043b000000170010006c00000001010000390000000301002039000001c70000013d0000008009900039000000400090043f000000800050043f00000000065600190000002406600039000000000026004b000007550000a13d000000000100001900001a1100010430000000200bb000390000000002ed001900000000000204350000000000fb0435000000200cc000390000001100c0006c000009ef0000813d0000000002c1034f000000000202043b000006a00020009c000006fd0000213d00000012022000290000003f03200039000000150030006c0000000005000019000006aa05008041000006aa03300197000000000983013f000000000083004b0000000003000019000006aa03004041000006aa0090009c000000000305c019000000000003004b000006fd0000c13d0000002003200039000000000531034f000000000e05043b000006a000e0009c000002100000213d0000001f05e00039000006f2055001970000003f05500039000006f205500197000000400f00043d00000000055f00190000000000f5004b00000000090000390000000109004039000006a00050009c000002100000213d0000000100900190000002100000c13d000000400050043f000000000def04360000000002e200190000004002200039000000150020006c000006fd0000213d0000002002300039000000000a21034f000006f205e0019800000000025d00190000073b0000613d00000000030a034f00000000090d0019000000003703043c0000000009790436000000000029004b000007370000c13d0000001f03e00190000006ff0000613d00000000055a034f0000000303300210000000000702043300000000073701cf000000000737022f000000000505043b0000010003300089000000000535022f00000000033501cf000000000373019f0000000000320435000006ff0000013d0000001f0530018f000006c206300198000000400200043d0000000004620019000005d50000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000007500000c13d000005d50000013d0000002002700039000000000221034f000006f2065001980000001f0750018f000000a001600039000007610000613d000000a008000039000000000902034f000000009a09043c0000000008a80436000000000018004b0000075d0000c13d000000000007004b0000076e0000613d000000000262034f0000000306700210000000000701043300000000076701cf000000000767022f000000000202043b0000010006600089000000000262022f00000000026201cf000000000272019f0000000000210435000000a0015000390000000000010435000000010030008c000007750000c13d0000000001040446000000010010008c000007790000c13d000000010030008c00000000010000390000000101006039000001c70000013d000000400100043d0000008402100039000006a20300004100000000003204350000006402100039000006a30300004100000000003204350000004402100039000006a4030000410000000000320435000000240210003900000046030000390000000000320435000006a50200004100000000002104350000000402100039000000200300003900000000003204350000068b0010009c0000068b010080410000004001100210000006a6011001c700001a1100010430000000400100043d0000004402100039000006e6030000410000000000320435000000240210003900000011030000390000000000320435000006a50200004100000000002104350000000402100039000000200300003900000000003204350000068b0010009c0000068b010080410000004001100210000006ba011001c700001a11000104300000068b033001970000001f0530018f000006c206300198000000400200043d0000000004620019000005d50000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000007a90000c13d000005d50000013d00000015030000290000004401300039000006e0020000410000000000210435000000240130003900000015020000390000000000210435000006a50100004100000000001304350000000401300039000000200200003900000000002104350000068b0030009c0000068b030080410000004001300210000006ba011001c700001a1100010430000002600900003900000000033200490000001f0a20008a000001030b30008a000006aa0cb00197000000000e000019000000160f000029000007cb0000013d000000200ff00039000000010ee000390000001700e0006c000003790000813d000002800350008a000000200990003900000000003904350000000003f1034f000000000303043b000006aa043001970000000006c4013f0000000000c4004b0000000004000019000006aa040040410000000000b3004b0000000007000019000006aa07008041000006aa0060009c000000000407c019000000000004004b000006fd0000c13d0000001603300029000000000431034f000000000404043b000006a80040009c000006fd0000213d00000000084504360000002004300039000000000641034f000000000606043b000006ab00600198000006fd0000c13d000006ac0660019700000000006804350000002006400039000000000661034f000000000606043b000000400750003900000000006704350000004004400039000000000641034f000000000606043b000000020060008c000006fd0000213d000000600750003900000000006704350000002006400039000000000661034f000000000606043b000000800750003900000000006704350000004006400039000000000661034f000000000606043b000000a007500039000000000067043500000000063a00490000006004400039000000000441034f000000000404043b000006aa07600197000006aa08400197000000000d78013f000000000078004b0000000007000019000006aa07004041000000000064004b0000000006000019000006aa06008041000006aa00d0009c000000000706c019000000000007004b000006fd0000c13d0000000004340019000000000341034f000000000303043b000006a00030009c000006fd0000213d0000002004400039000006f4063000d10000000006260019000000000064004b0000000007000019000006aa07002041000006aa06600197000006aa08400197000000000d68013f000000000068004b0000000006000019000006aa06004041000006aa00d0009c000000000607c019000000000006004b000006fd0000c13d000000c006500039000000e0070000390000000000760435000000e00650003900000000003604350000010005500039000000000003004b000007c70000613d0000000008000019000000000641034f000000000606043b000000060060008c000006fd0000213d0000000006650436000000200d4000390000000007d1034f000000000707043b000006a00070009c000006fd0000213d00000000007604350000002006d00039000000000661034f000000000606043b00000040075000390000000000670435000000400dd000390000000006d1034f000000000606043b000000020060008c000006fd0000213d000000600750003900000000006704350000002006d00039000000000661034f000000000606043b000000800750003900000000006704350000004006d00039000000000661034f000000000606043b000000a0075000390000000000670435000000c004400039000000c0055000390000000108800039000000000038004b0000082e0000413d000007c70000013d0000068b033001970000001f0530018f000006c206300198000000400200043d0000000004620019000005d50000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000085d0000c13d000005d50000013d0000000005420019000000000004004b0000086b0000613d0000001406000029000000000702001900000000680604340000000007870436000000000057004b000008670000c13d000000000003004b000008790000613d001400140040002d0000000303300210000000000405043300000000043401cf000000000434022f000000140600002900000000060604330000010003300089000000000636022f00000000033601cf000000000343019f000000000035043500000000022100190000000000020435000000150200002900000024022000390000000103000039000000000032043500000000020004140000000003000411000000040030008c000008980000613d0000001f01100039000006f20110019700000064011000390000068b0010009c0000068b01008041000000600110021000000015030000290000068b0030009c0000068b030080410000004003300210000000000131019f0000068b0020009c0000068b02008041000000c002200210000000000112019f00000000020004111a0f1a050000040f00000060031002700001068b0030019d0000000100200190000008f90000613d0000001501000029000006a00010009c000002100000213d0000001501000029000000400010043f000006bc0100004100000000001004430000000001000411000000040010044300000000010004140000068b0010009c0000068b01008041000000c001100210000006bf011001c700008002020000391a0f1a0a0000040f0000000100200190000010c10000613d000000000101043b000000000001004b000006fd0000613d000000400500043d000000240150003900000040020000390000000000210435000006e30100004100000000001504350000000001000410000006a80110019700000004025000390000000000120435000000440150003900000017020000290000000000210435000006f2032001980000001f0420018f001500000005001d00000064015000390000000002310019000000160500002900000020055000390000000205500367000008c90000613d000000000605034f0000000007010019000000006806043c0000000007870436000000000027004b000008c50000c13d000000000004004b000008d60000613d000000000335034f0000000304400210000000000502043300000000054501cf000000000545022f000000000303043b0000010004400089000000000343022f00000000034301cf000000000353019f00000000003204350000001701100029000000000001043500000000010004140000000002000411000000040020008c000008f20000613d00000017020000290000001f02200039000006f202200197000006e40020009c000006e402008041000000600220021000000015030000290000068b0030009c0000068b030080410000004003300210000000000232019f0000068b0010009c0000068b01008041000000c001100210000000000112019f000006e50110009a00000000020004111a0f1a050000040f00000060031002700001068b0030019d0000000100200190000009060000613d0000001501000029000006a00010009c000002100000213d0000001501000029000000400010043f000000000100001900001a100001042e0000068b033001970000001f0530018f000006c206300198000000400200043d0000000004620019000005d50000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000009010000c13d000005d50000013d0000068b033001970000001f0530018f000006c206300198000000400200043d0000000004620019000005d50000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000090e0000c13d000005d50000013d000000120b0000290000091b0000013d000000200bb000390000008001c0003900000000008104350000000000cb0435000000150090006c000001560000813d0000000091090434000006a00010009c000006fd0000213d000000160d1000290000000001d50049000006a90010009c000006fd0000213d000000e00010008c000006fd0000413d000000400c00043d000006b500c0009c000002100000213d000000a001c00039000000400010043f0000002001d000390000000001010433000006a80010009c000006fd0000213d00000000011c04360000004004d000390000000004040433000006ab00400198000006fd0000c13d00000000004104350000004001c000390000006004d00039000000000404043300000000004104350000008004d000390000000001420049000006a90010009c000006fd0000213d000000600010008c000006fd0000413d000000400100043d000006b20010009c000002100000213d0000006007100039000000400070043f0000000004040433000000020040008c000006fd0000213d0000000004410436000000a007d0003900000000070704330000000000740435000000c004d000390000000004040433000000400710003900000000004704350000006004c000390000000000140435000000e001d000390000000001010433000006a00010009c000006fd0000213d0000000004d100190000003f01400039000000000021004b0000000007000019000006aa07008041000006aa01100197000000000861013f000000000061004b0000000001000019000006aa01004041000006aa0080009c000000000107c019000000000001004b000006fd0000c13d0000002001400039000000000d010433000006a000d0009c000002100000213d0000000501d002100000003f01100039000006b101100197000000400800043d0000000001180019000000000081004b00000000070000390000000107004039000006a00010009c000002100000213d0000000100700190000002100000c13d000000400010043f0000000000d80435000000400e400039000000c001d000c9000000000fe1001900000000002f004b000006fd0000213d0000000000fe004b000009150000813d000000000d0800190000000001e20049000006a90010009c000006fd0000213d000000c00010008c000006fd0000413d000000400400043d000006a10040009c000002100000213d0000008001400039000000400010043f00000000170e0434000000060070008c000006fd0000213d00000000077404360000000001010433000006a00010009c000006fd0000213d000000000017043500000040014000390000004007e0003900000000070704330000000000710435000000400100043d000006b20010009c000002100000213d0000006007100039000000400070043f0000006007e000390000000007070433000000020070008c000006fd0000213d000000200dd000390000000007710436000000800ae00039000000000a0a04330000000000a70435000000a007e000390000000007070433000000400a10003900000000007a04350000006007400039000000000017043500000000004d0435000000c00ee000390000000000fe004b0000097b0000413d000009150000013d00000017020000290000001f0920008a0000000005a20049000000ff0a50008a000006aa0ba001970000000005000019000000000d000019000000050ed00210000000000e3e0019000000000ee1034f000000000e0e043b000006aa0fe001970000000007bf013f0000000000bf004b000000000f000019000006aa0f0040410000000000ae004b0000000008000019000006aa08008041000006aa0070009c000000000f08c01900000000000f004b000006fd0000c13d000000000e3e0019000000c007e00039000000000771034f000000000f07043b0000000007e90049000006aa08700197000006aa04f00197000000000284013f000000000084004b0000000004000019000006aa0400404100000000007f004b0000000007000019000006aa07008041000006aa0020009c000000000407c019000000000004004b000006fd0000c13d000000000fef00190000000002f1034f000000000e02043b000006a000e0009c000006fd0000213d000006f402e000d100000017022000290000002004f00039000000000024004b0000000007000019000006aa07002041000006aa02200197000006aa04400197000000000824013f000000000024004b0000000002000019000006aa02004041000006aa0080009c000000000207c019000000000002004b000006fd0000c13d00000000005e001a0000052b0000413d00000000055e0019000000010dd0003900000000006d004b000009b10000413d000004260000013d0000000f02000029000006a8022001970000000003000410000000000032004b000005c80000c13d000006a90060009c000006fd0000213d000000400060008c000006fd0000413d0000001302100360000000000202043b000006a00020009c000006fd0000213d0000001303200029001100000003001d0000001402300069000006a90020009c000006fd0000213d000000e00020008c000006fd0000413d000000400300043d000f00000003001d000006b50030009c000002100000213d0000000f03000029000000a003300039000000400030043f0000001103100360000000000303043b000006a80030009c000006fd0000213d0000000f05000029000000000635043600000011030000290000002003300039000000000531034f000000000505043b000e00000006001d0000000000560435000000400220008a000006a90020009c000006fd0000213d000000600020008c000006fd0000413d000000400200043d000006b20020009c000002100000213d0000006005200039000000400050043f0000002003300039000000000531034f000000000505043b000000020050008c000006fd0000213d00000000055204360000002006300039000000000661034f000000000606043b00000000006504350000004005300039000000000551034f000000000505043b000000400620003900000000005604350000000f050000290000004005500039000d00000005001d00000000002504350000006002300039000000000221034f000000000202043b000006a00020009c000006fd0000213d0000001102200029001500000002001d0000001f022000390000001405000029000000000052004b0000000003000019000006aa03008041000006aa02200197000006aa06500197000000000562013f000000000062004b0000000002000019000006aa02004041000006aa0050009c000000000203c019000000000002004b000006fd0000c13d0000001502100360000000000202043b000006a00020009c000002100000213d00000005032002100000003f05300039000006b105500197000000400700043d0000000005570019000c00000007001d000000000075004b00000000070000390000000107004039000006a00050009c000002100000213d0000000100700190000002100000c13d000000400050043f0000000c0500002900000000002504350000001502000029000000200a2000390000000003a30019001200000003001d000000140030006c000006fd0000213d0000001200a0006c00000edc0000813d0000000c0c00002900000a6e0000013d000000200cc000390000008002d0003900000000007204350000000000dc0435000000200aa000390000001200a0006c00000edc0000813d0000000002a1034f000000000202043b000006a00020009c000006fd0000213d000000150220002900000020092000390000001403900069000006a90030009c000006fd0000213d000000e00030008c000006fd0000413d000000400d00043d000006b500d0009c000002100000213d000000a003d00039000000400030043f000000000391034f000000000303043b000006a80030009c000006fd0000213d00000000053d04360000002003900039000000000731034f000000000707043b000006ab00700198000006fd0000c13d00000000007504350000002003300039000000000531034f000000000505043b0000004007d0003900000000005704350000001402200069000000800220008a000006a90020009c000006fd0000213d000000600020008c000006fd0000413d000000400200043d000006b20020009c000002100000213d0000006005200039000000400050043f0000002003300039000000000531034f000000000505043b000000020050008c000006fd0000213d00000000055204360000002007300039000000000771034f000000000707043b00000000007504350000004005300039000000000551034f000000000505043b000000400720003900000000005704350000006005d0003900000000002504350000006002300039000000000221034f000000000202043b000006a00020009c000006fd0000213d00000000029200190000001f03200039000000140030006c0000000005000019000006aa05008041000006aa03300197000000000763013f000000000063004b0000000003000019000006aa03004041000006aa0070009c000000000305c019000000000003004b000006fd0000c13d000000000321034f000000000303043b000006a00030009c000002100000213d00000005053002100000003f05500039000006b105500197000000400700043d0000000005570019000000000075004b00000000080000390000000108004039000006a00050009c000002100000213d0000000100800190000002100000c13d000000400050043f0000000000370435000000200f200039000000c0023000c90000000009f20019000000140090006c000006fd0000213d00000000009f004b00000a670000813d000000000e0700190000001402f00069000006a90020009c000006fd0000213d000000c00020008c000006fd0000413d000000400800043d000006a10080009c000002100000213d0000008002800039000000400020043f0000000002f1034f000000000202043b000000060020008c000006fd0000213d00000000032804360000002002f00039000000000521034f000000000505043b000006a00050009c000006fd0000213d00000000005304350000002003200039000000000231034f000000000202043b00000040058000390000000000250435000000400200043d000006b20020009c000002100000213d0000006005200039000000400050043f0000002003300039000000000531034f000000000505043b000000020050008c000006fd0000213d000000200ee000390000000005520436000000200b300039000000000bb1034f000000000b0b043b0000000000b504350000004003300039000000000331034f000000000303043b000000400520003900000000003504350000006003800039000000000023043500000000008e0435000000c00ff0003900000000009f004b00000ad70000413d00000a670000013d0000001402000029000700c40020003d0000001502000029000606a80020019b0000000402000029000800040020003d001000000000001d0000001704000029000000140240006a000000230220008a000000000023004b0000000004000019000006aa04008041000006aa02200197000006aa05300197000000000625013f000000000025004b0000000002000019000006aa02004041000006aa0060009c000000000204c019000000000002004b000006fd0000c13d0000001304300029000000000241034f000000000302043b000006a00030009c000006fd0000213d000006f3023000d100000017022000290000002004400039000006aa05200197000006aa06400197000000000756013f000000000056004b0000000005000019000006aa05004041000000000024004b0000000002000019000006aa02002041000006aa0070009c000000000502c019000000000005004b000006fd0000c13d000000100030006b000012940000813d0000001002000029000d00a0002000cd0000000d044000290000001703400069000006a90030009c000006fd0000213d000000a00030008c000006fd0000413d000000400200043d000006b20020009c000002100000213d0000006005200039000000400050043f000000000541034f000000000505043b000006a80050009c000006fd0000213d00000000055204360000002004400039000000000641034f000000000606043b0000000000650435000000400330008a000006a90030009c000006fd0000213d000000600030008c000006fd0000413d000000400300043d001700000003001d000006b20030009c000002100000213d00000017030000290000006003300039000000400030043f0000002003400039000000000431034f000000000404043b000000020040008c000006fd0000213d000000170600002900000000054604360000002004300039000000000441034f000000000404043b000c00000005001d00000000004504350000004003300039000000000131034f000000000101043b0000004003600039000a00000003001d0000000000130435000000400120003900000000006104350000000001020433000006a801100197000000000010043f0000000801000029000000200010043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000006fd0000613d000000000101043b000b00000001001d00000017010000290000000001010433000000020010008c000005900000213d000000000001004b000000010400008a00000bc70000613d000000010010008c00000b930000c13d0000000c010000290000000001010433001700000001001d0000000601000029000000000010043f0000000b01000029000000200010043f000000000100041400000bbb0000013d0000000a010000290000000001010433001700000001001d000006b301000041000000000010044300000000010004140000068b0010009c0000068b01008041000000c001100210000006b4011001c70000800b020000391a0f1a0a0000040f0000000100200190000010c10000613d000000170000006b00000ed60000613d000000000101043b00000017011000fa000006a0011001970000000c020000290000000002020433001700000002001d000000000010043f0000000b010000290000000101100039000000200010043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000006fd0000613d000000000101043b0000000602000029000000000020043f000000200010043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000006fd0000613d000000000101043b000000000101041a000000170410006b0000052b0000413d00000002010003670000000702100360000000000302043b000000140200002900170000000000350000000002200079000000230220008a000006aa05200197000006aa06300197000000000756013f000000000056004b0000000005000019000006aa05004041000000000023004b0000000002000019000006aa02008041000006aa0070009c000000000502c019000000000005004b000006fd0000c13d0000001306300029000000000261034f000000000502043b000006a00050009c000006fd0000213d000006f3025000d100000017022000290000002006600039000006aa07200197000006aa08600197000000000978013f000000000078004b0000000007000019000006aa07004041000000000026004b0000000002000019000006aa02002041000006aa0090009c000000000702c019000000000007004b000006fd0000c13d000000100050006b000012940000813d0000000d02600029000000000221034f000000000602043b000006a80060009c000006fd0000213d000000400500043d000006a10050009c000002100000213d0000008002500039000000400020043f00000020025000390000000000620435000000000045043500000060025000390000000000020435000000400250003900000000000204350000000e020000290000000002020433000000100020006c000012940000a13d00000010060000290000000502600210000000160220002900000000005204350000000e020000290000000004020433000000000064004b000012940000a13d0000001002000029001000010020003d000000100040006b00000b140000413d000004be0000013d0000001401000029000200a40010003d0000000401000029000700060010003d000100050010003d000500000000001d001600000000001d00000c220000013d000000030100002900000000020104330000000501000029000500010010003d000000050020006b000004c50000813d00000002010003670000000202100360000000000302043b0000000002000031000000140420006a000000230440008a000006aa05400197000006aa06300197000000000756013f000000000056004b0000000005000019000006aa05004041000000000043004b0000000004000019000006aa04008041000006aa0070009c000000000504c019000000000005004b000006fd0000c13d0000001304300029000000000341034f000000000503043b000006a00050009c000006fd0000213d000000050350021000000000063200490000002003400039000006aa07600197000006aa08300197000000000978013f000000000078004b0000000007000019000006aa07004041000000000063004b0000000006000019000006aa06002041000006aa0090009c000000000706c019000000000007004b000006fd0000c13d000000050050006b000012940000813d0000000005420049000000050400002900150005004002180000001504300029000000000441034f000000000404043b000000ff0550008a000006aa06500197000006aa07400197000000000867013f000000000067004b0000000006000019000006aa06004041000000000054004b0000000005000019000006aa05008041000006aa0080009c000000000605c019000000000006004b000006fd0000c13d00000000043400190000000003420049000006a90030009c000006fd0000213d000000e00030008c000006fd0000413d000000400300043d000d00000003001d000006b50030009c000002100000213d0000000d03000029000000a003300039000000400030043f000000000341034f000000000303043b000006a80030009c000006fd0000213d0000000d050000290000000003350436000c00000003001d0000002003400039000000000531034f000000000505043b000006ab00500198000006fd0000c13d0000000c0600002900000000005604350000002003300039000000000531034f000000000505043b0000000d0600002900000040066000390000000000560435000000400500043d000006b20050009c000002100000213d0000006006500039000000400060043f0000002006300039000000000361034f000000000303043b000000020030008c000006fd0000213d00000000033504360000002007600039000000000771034f000000000707043b00000000007304350000004003600039000000000331034f000000000303043b000000400750003900000000003704350000000d03000029000000600330003900000000005304350000006005600039000000000551034f000000000505043b000006a00050009c000006fd0000213d00000000054500190000001f04500039000000000024004b0000000006000019000006aa06008041000006aa04400197000006aa07200197000000000874013f000000000074004b0000000004000019000006aa04004041000006aa0080009c000000000406c019000000000004004b000006fd0000c13d000000000451034f000000000604043b000006a00060009c000002100000213d00000005046002100000003f04400039000006b107400197000000400400043d0000000007740019000000000047004b00000000080000390000000108004039000006a00070009c000002100000213d0000000100800190000002100000c13d000000400070043f00000000006404350000002005500039000000c0066000c90000000006560019000000000026004b000006fd0000213d000000000065004b00000cfb0000813d00000000070400190000000008520049000006a90080009c000006fd0000213d000000c00080008c000006fd0000413d000000400800043d000006a10080009c000002100000213d0000008009800039000000400090043f000000000951034f000000000909043b000000060090008c000006fd0000213d000000000a9804360000002009500039000000000b91034f000000000b0b043b000006a000b0009c000006fd0000213d0000000000ba0435000000200a9000390000000009a1034f000000000909043b000000400b80003900000000009b0435000000400900043d000006b20090009c000002100000213d000000600b9000390000004000b0043f000000200aa00039000000000ba1034f000000000b0b043b0000000200b0008c000006fd0000213d0000002007700039000000000bb90436000000200ca00039000000000cc1034f000000000c0c043b0000000000cb0435000000400aa00039000000000aa1034f000000000a0a043b000000400b9000390000000000ab0435000000600a80003900000000009a04350000000000870435000000c005500039000000000065004b00000cc60000413d0000000d010000290000008002100039000a00000002001d00000000004204350000000002030433001700000002001d0000000001010433000006a801100197000000000010043f0000000101000029000000200010043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000006fd0000613d000000000101043b0000000c020000290000000002020433000006ac02200197000000000020043f000000200010043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000006fd0000613d000000000101043b001000000001001d00000017010000290000000012010434000b00000001001d000000020020008c000005900000213d000000000002004b000000010100008a00000d680000613d000000010020008c00000d330000c13d0000000b010000290000000001010433001700000001001d0000000601000029000000000010043f0000001001000029000000200010043f000000000100041400000d5c0000013d000000170100002900000040011000390000000001010433001700000001001d000006b301000041000000000010044300000000010004140000068b0010009c0000068b01008041000000c001100210000006b4011001c70000800b020000391a0f1a0a0000040f0000000100200190000010c10000613d000000170000006b00000ed60000613d000000000101043b00000017011000fa000006a0011001970000000b020000290000000002020433001700000002001d000000000010043f00000010010000290000000101100039000000200010043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000006fd0000613d000000000101043b0000000602000029000000000020043f000000200010043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000006fd0000613d000000000101043b000000000101041a000000170110006b0000052b0000413d000000400200043d000006a10020009c000002100000213d0000000d0300002900000000030304330000000c0400002900000000040404330000008005200039000000400050043f000006ac0440019700000040052000390000000000450435000006a8033001970000002004200039000000000034043500000000001204350000006001200039000000000001043500000003010000290000000001010433000000050010006c000012940000a13d00000015030000290000001201300029000000000021043500000003010000290000000002010433000000050020006c000012940000a13d0000000a0100002900000000010104330000000003010433000000000003004b00000c1e0000613d001700000000001d00000d910000013d0000001703000029001700010030003d0000000002010433000000170020006b00000c1c0000813d00000017020000290000000502200210001000200020003d0000001002100029000000000202043300000060022000390000000002020433001500000002001d0000000032020434000b00000003001d000000020020008c000005900000213d000000000002004b00000d8c0000613d0000000d010000290000000001010433000006a801100197000000000010043f0000000701000029000000200010043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000006fd0000613d000000000101043b0000000c020000290000000002020433000006ac02200197000000000020043f000000200010043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000006fd0000613d000000000101043b0000001702000029000000000020043f000000200010043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000006fd0000613d000000000101043b000800000001001d00000015010000290000000002010433000000020020008c000005900000213d000000000002004b000000010100008a00000e130000613d000000010020008c00000dde0000c13d0000000b010000290000000001010433001500000001001d0000000601000029000000000010043f0000000801000029000000200010043f000000000100041400000e070000013d000000150100002900000040011000390000000001010433001500000001001d000006b301000041000000000010044300000000010004140000068b0010009c0000068b01008041000000c001100210000006b4011001c70000800b020000391a0f1a0a0000040f0000000100200190000010c10000613d000000150000006b00000ed60000613d000000000101043b00000015011000fa000006a0011001970000000b020000290000000002020433001500000002001d000000000010043f00000008010000290000000101100039000000200010043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000006fd0000613d000000000101043b0000000602000029000000000020043f000000200010043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000006fd0000613d000000000101043b000000000101041a000000150110006b0000052b0000413d0000000a0200002900000000030204330000000002030433000000170020006c000012940000a13d000000400200043d000006a10020009c000002100000213d0000000c040000290000000004040433000006ac044001970000000d050000290000000005050433000006a80550019700000010033000290000000003030433000000200330003900000000030304330000008006200039000000400060043f000006a00330019700000060062000390000000000360435000000400320003900000000004304350000002003200039000000000053043500000000001204350000001601000029000000010310003a0000052b0000613d00000009010000290000000001010433000000160010006c000012940000a13d000000160500002900000005015002100000001101100029000000000021043500000009010000290000000001010433000000000051004b000012940000a13d0000000a010000290000000001010433001600000003001d00000d8c0000013d000000010100008a000000400500043d000006b00050009c000002100000213d000000c002500039000000400020043f000000a0025000390000000903000029000000000032043500000080035000390000000304000029000000000043043500000060045000390000000e0600002900000000006404350000004006500039000000000016043500000020075000390000001701000029000000000017043500000016010000290000000000150435000000400100043d00000020080000390000000008810436000000000505043300000000005804350000000005070433000000030050008c000005900000213d0000004007100039000000000057043500000000050604330000006006100039000000000056043500000000050404330000008004100039000000c0060000390000000000640435000000e004100039000000000605043300000000006404350000010004100039000000000006004b00000e840000613d00000000070000190000002005500039000000000805043300000000a90804340000000009940436000000000a0a0433000006a80aa001970000000000a9043500000040098000390000000009090433000006ac09900197000000400a40003900000000009a0435000000600880003900000000080804330000006009400039000000000089043500000080044000390000000107700039000000000067004b00000e700000413d0000000005140049000000200650008a0000000005030433000000a003100039000000000063043500000000060504330000000003640436000000000006004b00000ea20000613d000000000400001900000020055000390000000007050433000000009807043400000000088304360000000009090433000006a809900197000000000098043500000040087000390000000008080433000006ac0880019700000040093000390000000000890435000000600770003900000000070704330000006008300039000000000078043500000080033000390000000104400039000000000064004b00000e8e0000413d0000000004130049000000200540008a0000000004020433000000c002100039000000000052043500000000050404330000000002530436000000000005004b00000ec00000613d000000000300001900000020044000390000000006040433000000008706043400000000077204360000000008080433000006a808800197000000000087043500000040076000390000000007070433000006ac0770019700000040082000390000000000780435000000600660003900000000060604330000006007200039000000000067043500000080022000390000000103300039000000000053004b00000eac0000413d00000000021200490000068b0020009c0000068b0200804100000060022002100000068b0010009c0000068b010080410000004001100210000000000112019f00001a100001042e000006b301000041000000000010044300000000010004140000068b0010009c0000068b01008041000000c001100210000006b4011001c70000800b020000391a0f1a0a0000040f0000000100200190000010c10000613d000000150000006b00000f840000c13d000006b601000041000000000010043f0000001201000039000000040010043f000006b70100004100001a11000104300000000f020000290000006002200039001200000002001d0000000c0300002900000000003204350000001102000029000000c002200039000000000221034f000000000202043b000006a00020009c000006fd0000213d00000011022000290000001f03200039000000140030006c0000000005000019000006aa05008041000006aa03300197000000000763013f000000000063004b0000000003000019000006aa03004041000006aa0070009c000000000305c019000000000003004b000006fd0000c13d000000000321034f000000000303043b000006a00030009c000002100000213d00000005053002100000003f05500039000006b105500197000000400700043d0000000005570019000000000075004b00000000080000390000000108004039000006a00050009c000002100000213d0000000100800190000002100000c13d000000400050043f00000000003704350000002008200039000000a0023000c90000000009820019000000140090006c000006fd0000213d000000000098004b00000f3d0000813d000000000a0700190000001402800069000006a90020009c000006fd0000213d000000a00020008c000006fd0000413d000000400b00043d000006b200b0009c000002100000213d0000006002b00039000000400020043f000000000281034f000000000202043b000006a80020009c000006fd0000213d00000000022b04360000002003800039000000000531034f000000000505043b0000000000520435000000400200043d000006b20020009c000002100000213d0000006005200039000000400050043f0000002003300039000000000531034f000000000505043b000000020050008c000006fd0000213d000000200aa000390000000005520436000000200c300039000000000cc1034f000000000c0c043b0000000000c504350000004003300039000000000331034f000000000303043b000000400520003900000000003504350000004003b0003900000000002304350000000000ba0435000000a008800039000000000098004b00000f0f0000413d0000000f020000290000008002200039000b00000002001d00000000007204350000004402400039000000000221034f000000000202043b000006a00020009c000006fd0000213d00000013022000290000001f03200039000000140030006c0000000004000019000006aa04008041000006aa03300197000000000563013f000000000063004b0000000003000019000006aa03004041000006aa0050009c000000000304c019000000000003004b000006fd0000c13d000000000321034f000000000303043b000006a00030009c000002100000213d00000005043002100000003f05400039000006b105500197000000400600043d0000000005560019001100000006001d000000000065004b00000000060000390000000106004039000006a00050009c000002100000213d0000000100600190000002100000c13d000000400050043f00000011050000290000000003350436000c00000003001d00000020022000390000000003240019000000140030006c000006fd0000213d000000000032004b00000f790000813d0000001104000029000000000521034f000000000505043b000006a00050009c000006fd0000213d000000200440003900000000005404350000002002200039000000000032004b00000f700000413d000000400100043d0000000f020000290000000002020433000006a80020019800000fa90000c13d0000004402100039000006db03000041000000000032043500000024021000390000001603000039000007960000013d000000000101043b00000015011000fa000006a00110019700000013020000290000000002020433001500000002001d000000000010043f00000004010000290000000301100039000000200010043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000006fd0000613d000000000101043b0000000602000029000000000020043f000000200010043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000006fd0000613d000000000101043b000000000101041a000000150110006b0000052b0000413d00000e430000013d0000002003100039000000200200003900000000002304350000000f020000290000000002020433000006a8022001970000004004100039000000000024043500000060021000390000000e04000029000000000404043300000000004204350000000d0200002900000000020204330000000045020434000000020050008c000005900000213d000000800610003900000000005604350000000004040433000000a005100039000000000045043500000040022000390000000002020433000000c004100039000000000024043500000012020000290000000005020433000000e002100039000000e0060000390000000000620435000001200210003900000000070504330000000000720435000001400810003900000005027002100000000004820019000000000007004b000010c20000c13d0000000002140049000000400220008a0000000b0500002900000000050504330000010006100039000000000026043500000000060504330000000004640436000000000006004b00000ff40000613d0000000002000019000000200550003900000000070504330000000098070434000006a808800197000000000884043600000000090904330000000000980435000000400770003900000000070704330000000089070434000000020090008c000005900000213d000000400a40003900000000009a04350000000008080433000000600940003900000000008904350000004007700039000000000707043300000080084000390000000000780435000000a0044000390000000102200039000000000062004b00000fdb0000413d0000000002140049000000200420008a00000000004104350000001f02200039000006f2042001970000000002140019000000000042004b00000000040000390000000104004039000006a00020009c000002100000213d0000000100400190000002100000c13d000000400020043f0000068b0030009c0000068b03008041000000400230021000000000010104330000068b0010009c0000068b010080410000006001100210000000000121019f00000000020004140000068b0020009c0000068b02008041000000c002200210000000000112019f000006b8011001c700008010020000391a0f1a0a0000040f0000000100200190000006fd0000613d000000000101043b000600000001001d000000000010043f0000000101000039000000200010043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000006fd0000613d000000000201043b0000000001000411000006a801100197000000000010043f001300000002001d0000000101200039000000200010043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000006fd0000613d000000000101043b000000000101041a000000ff0110018f000000030010008c000005900000213d000000010010008c0000110f0000c13d000006bb01000041000000000010044300000000010004140000068b0010009c0000068b01008041000000c001100210000006b4011001c70000800b020000391a0f1a0a0000040f0000000100200190000010c10000613d0000000e020000290000000002020433001400000002001d000000000101043b000006bc020000410000000000200443000001040010008c000006be01000041000006bd01006041001500000001001d000000040010044300000000010004140000068b0010009c0000068b01008041000000c001100210000006bf011001c700008002020000391a0f1a0a0000040f0000000100200190000010c10000613d000000000101043b000000000001004b000006fd0000613d000000400200043d000006c0010000410000000001120436000700000001001d0000002401200039000a00000001001d000000140300002900000000003104350000000401200039000900000001001d00000000000104350000068b0020009c001400000002001d0000068b010000410000000001024019000e00400010021800000000010004140000068b0010009c0000068b01008041000000c0011002100000000e011001af000006c1011001c700000015020000291a0f1a0a0000040f00000060031002700001068b0030019d0000000100200190000011160000613d0000001401000029000006a00010009c000002100000213d0000001401000029000000400010043f000000170a0000290000022402a000390000000201000367000000000321034f000000000703043b0000000004000031000000100340006a0000001f0530008a000006aa06500197000006aa03700197000000000863013f000000000063004b0000000009000019000006aa09004041000000000057004b0000000003000019000006aa03008041000006aa0080009c000000000903c0190000004403a00039000000000331034f000000000303043b000000000009004b000006fd0000c13d0000001008700029000000000781034f000000000707043b000006a00070009c000006fd0000213d00000000097400490000002008800039000006aa0a900197000006aa0b800197000000000cab013f0000000000ab004b000000000a000019000006aa0a004041000000000098004b0000000009000019000006aa09002041000006aa00c0009c000000000a09c01900000000000a004b000006fd0000c13d000000040070008c000011230000413d000000000781034f000000000707043b000006ac07700197000006c30070009c000011230000c13d000006a5010000410000001403000029000000000013043500000020010000390000000902000029000000000012043500000029010000390000000a0200002900000000001204350000006401300039000006d90200004100000000002104350000004401300039000006da0200004100000000002104350000000e01000029000006cb011001c700001a1100010430000000000001042f0000000009000019000010c70000013d0000000109900039000000000079004b00000fd00000813d0000000002140049000001400220008a00000000082804360000002005500039000000000205043300000000ba020434000006a80aa00197000000000aa40436000000000b0b0433000006ac0bb001970000000000ba0435000000400a400039000000400b200039000000000b0b04330000000000ba0435000000600a200039000000000a0a043300000000bc0a04340000000200c0008c000005900000213d000000600d4000390000000000cd0435000000000b0b0433000000800c4000390000000000bc0435000000400aa00039000000000a0a0433000000a00b4000390000000000ab04350000008002200039000000000a020433000000c0024000390000000000620435000000e002400039000000000b0a04330000000000b20435000001000440003900000000000b004b000010c40000613d000000000c000019000000200aa0003900000000020a043300000000de0204340000000600e0008c000005900000213d000000000ee40436000000000d0d0433000006a00dd001970000000000de0435000000400d400039000000400e200039000000000e0e04330000000000ed04350000006002200039000000000202043300000000de0204340000000200e0008c000005900000213d000000600f4000390000000000ef0435000000000d0d0433000000800e4000390000000000de043500000040022000390000000002020433000000a00d40003900000000002d0435000000c004400039000000010cc000390000000000bc004b000010ef0000413d000010c40000013d000000400100043d0000004402100039000006b903000041000000000032043500000024021000390000001503000039000007960000013d0000068b033001970000001f0530018f000006c206300198000000400200043d0000000004620019000005d50000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000111e0000c13d000005d50000013d000000600220008a000000000721034f000000000707043b000006aa08700197000000000968013f000000000068004b0000000006000019000006aa06004041000000000057004b0000000005000019000006aa05008041000006aa0090009c000000000605c019000000000006004b000006fd0000c13d0000001005700029000000000651034f000000000606043b000006a00060009c000006fd0000213d00000000046400490000002005500039000006aa07400197000006aa08500197000000000978013f000000000078004b0000000007000019000006aa07004041000000000045004b0000000004000019000006aa04002041000006aa0090009c000000000704c019000000000007004b000006fd0000c13d001506a80030019b000000030060008c0000001404000029000000600340003900000040044000390000001106000029000800400060003d0000117b0000213d0000001405000029000006b20050009c000002100000213d000000400030043f0000000703000029000000000003043500000014030000290000000000030435000000400300043d000006b20030009c000002100000213d0000006005300039000000400050043f0000004005300039000000000005043500000020053000390000000000050435000000000003043500000000003404350000000b0300002900000000030304330000000043030434000000000003004b000011710000613d00000000050000190000000506500210000000000664001900000000060604330000000078060434000006a808800197000000150080006c0000118a0000613d0000000105500039000000000035004b000011670000413d000000400100043d0000006402100039000006d70300004100000000003204350000004402100039000006d803000041000000000032043500000024021000390000002703000039000013950000013d0000000006000411000000150060006b000011ae0000c13d000006a5010000410000001402000029000000000012043500000020010000390000000903000029000000000013043500000013010000390000000a0300002900000000001304350000004401200039000006d202000041000011bc0000013d000000a00220008a000000000121034f000000000201043b0000000001070433001400000002001d000000000012004b000012060000213d00000040016000390000000001010433001200000001001d0000001501000029000000000010043f00000013010000290000000401100039000000200010043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000006fd0000613d00000011020000290000000002020433000000010020008c000012940000a13d000000000201043b00000008010000290000000001010433000006a004100197000000120100002900000014030000291a0f18d90000040f0000123e0000013d0000000002000410000000150020006b000011c00000c13d000006a501000041000000140200002900000000001204350000002001000039000000090300002900000000001304350000001b010000390000000a0300002900000000001304350000004401200039000006d10200004100000000002104350000000e01000029000006ba011001c700001a1100010430000000000251034f000000000202043b0000001405000029000006b50050009c000002100000213d0000001406000029000000a005600039000000400050043f0000000000040435000000070400002900000000000404350000000000060435000000400400043d000006b20040009c000002100000213d0000006005400039000000400050043f0000004005400039000000000005043500000020054000390000000000050435000000000004043500000014050000290000008005500039000000600600003900000000006504350000000000430435000000120300002900000000030304330000000043030434000000000003004b000011ea0000c13d000000400100043d0000006402100039000006cf0300004100000000003204350000004402100039000006d003000041000000000032043500000024021000390000002403000039000013950000013d001206ac0020019b0000000005000019000011f00000013d0000000105500039000000000035004b000011e00000813d000000050650021000000000066400190000000006060433001400000006001d0000000067060434000006a807700197000000150070006c000011ed0000c13d0000000006060433000000000626013f000006c40060009c000011ed0000813d0000001702000029000b01240020003d0000000b01100360000000000201043b000000140100002900000040011000390000000001010433000e00000002001d000000000012004b0000120d0000a13d000000400100043d0000004402100039000006d603000041000000000032043500000024021000390000001303000039000007960000013d000000140100002900000060011000390000000001010433000a00000001001d0000001501000029000000000010043f00000013010000290000000501100039000000200010043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000006fd0000613d000000000101043b0000001202000029000000000020043f000000200010043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000006fd0000613d00000011020000290000000002020433000000020020008c000012940000413d000000000201043b00000008010000290000000001010433000006a0041001970000000a010000290000000e030000291a0f18d90000040f00000014010000290000008001100039000e00000001001d00000000010104330000000002010433000000000002004b0000129a0000c13d000000800100043d000000410010008c000005c80000c13d000000c00100043d000006d30010009c000005c80000213d000000400200043d0000006003200039000000e00400043d000000a00500043d000000000013043500000040012000390000000000510435000000f8014002700000002003200039000000000013043500000016010000290000000000120435000000000000043f0000068b0020009c0000068b02008041000000400120021000000000020004140000068b0020009c0000068b02008041000000c002200210000000000112019f000006d4011001c700000001020000391a0f1a0a0000040f00000060031002700000068b03300197000000200030008c000000200400003900000000040340190000001f0540018f00000020044001900000126a0000613d000000000601034f0000000007000019000000006806043c0000000007870436000000000047004b000012660000c13d000000000005004b000012770000613d000000000641034f0000000305500210000000000704043300000000075701cf000000000757022f000000000606043b0000010005500089000000000656022f00000000055601cf000000000575019f0000000000540435000100000003001f00000001002001900000133e0000613d000000000100043d000006a801100198000005c80000613d0000000f020000290000000002020433000006a802200197000000000021004b0000134a0000c13d0000000601000029000000000010043f0000000101000039000000200010043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000006fd0000613d000000000201043b00000011010000290000000001010433000000000001004b000013510000c13d000006b601000041000000000010043f0000003201000039000000040010043f000006b70100004100001a11000104300000000b02000029000b00a00020003d0000001302000029000a00060020003d001400000000001d000012ae0000013d000000000013004b000013700000613d000006a0044001970000001301000029000000600110003900000000010104331a0f18d90000040f0000001403000029001400010030003d0000000e0100002900000000010104330000000002010433000000140020006b0000123e0000813d00000014020000290000000502200210000000000121001900000020011000390000000001010433001300000001001d0000001501000029000000000010043f0000000a01000029000000200010043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000006fd0000613d000000000101043b0000001202000029000000000020043f000000200010043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000006fd0000613d000000000101043b0000001402000029000000000020043f000000200010043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000006fd0000613d00000002030003670000000b02300360000000000402043b0000000005000031000000170250006a000000230220008a000006aa06200197000006aa07400197000000000867013f000000000067004b0000000006000019000006aa06004041000000000024004b0000000002000019000006aa02008041000006aa0080009c000000000602c019000000000201043b000000000006004b000006fd0000c13d0000001001400029000000000413034f000000000404043b000006a00040009c000006fd0000213d00000000054500490000002006100039000000000056004b0000000007000019000006aa07002041000006aa05500197000006aa06600197000000000856013f000000000056004b0000000005000019000006aa05004041000006aa0080009c000000000507c019000000000005004b000006fd0000c13d0000001405000029000000020550003900000011060000290000000006060433000000000056004b000012940000a13d0000001306000029000000200660003900000000060604330000000507600210000006c506700197000006c607700197000000000067004b0000052b0000c13d0000002406600039000000000046004b000006fd0000213d00000005045002100000000c0440002900000000040404330000000001160019000000000113034f000000000301043b00000013010000290000000001010433000000060010008c000005900000213d000000010510008a000000050050008c000012a20000213d000000130100002900000040011000390000000001010433000006850005013e000000000013004b000012a20000613d000013770000013d000000000013004b000012a20000213d0000137e0000013d000000000013004b000012a20000413d000013850000013d000000000013004b000012a20000813d0000138c0000013d000000000013004b000012a20000a13d000000400100043d0000004402100039000006c8030000410000000000320435000006a502000041000000000021043500000024021000390000002003000039000000000032043500000004021000390000079b0000013d0000001f0530018f000006c206300198000000400200043d0000000004620019000005d50000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000013450000c13d000005d50000013d000000400100043d0000004402100039000006d503000041000000000032043500000024021000390000001903000039000007960000013d0000001701000029000000e4031000390000000204000367000000000534034f0000000c010000290000000001010433000000000505043b000000000005004b0000136b0000c13d000000400530008a000000000554034f000000800330008a000000000334034f000000000403043b000000000505043b00000000035400a9000000000005004b000013660000613d00000000055300d9000000000045004b0000052b0000c13d000006a0041001970000000d01000029000000000101043300000002022000391a0f18d90000040f000000160100002900000001020000390000000000210447000000000100001900001a100001042e000000400100043d0000004402100039000006c703000041000000000032043500000024021000390000001c03000039000007960000013d000000400100043d0000004402100039000006ce03000041000000000032043500000024021000390000001803000039000007960000013d000000400100043d0000004402100039000006cd03000041000000000032043500000024021000390000001a03000039000007960000013d000000400100043d0000004402100039000006cc03000041000000000032043500000024021000390000001703000039000007960000013d000000400100043d0000006402100039000006c90300004100000000003204350000004402100039000006ca030000410000000000320435000000240210003900000023030000390000000000320435000006a50200004100000000002104350000000402100039000000200300003900000000003204350000068b0010009c0000068b010080410000004001100210000006cb011001c700001a110001043000000000430104340000000001320436000006f2063001970000001f0530018f000000000014004b000013b60000813d000000000006004b000013b20000613d00000000085400190000000007510019000000200770008a000000200880008a0000000009670019000000000a680019000000000a0a04330000000000a90435000000200660008c000013ac0000c13d000000000005004b000013cc0000613d0000000007010019000013c20000013d0000000007610019000000000006004b000013bf0000613d00000000080400190000000009010019000000008a0804340000000009a90436000000000079004b000013bb0000c13d000000000005004b000013cc0000613d00000000046400190000000305500210000000000607043300000000065601cf000000000656022f00000000040404330000010005500089000000000454022f00000000045401cf000000000464019f0000000000470435000000000431001900000000000404350000001f03300039000006f2023001970000000001210019000000000001042d0005000000000002000300000001001d0000000003120049000006a90030009c000015440000213d000000df0030008c000015440000a13d000000400100043d000200000001001d000006f50010009c000015460000813d0000000201000029000000a001100039000000400010043f00000002040003670000000301400360000000000101043b000006a80010009c000015440000213d0000000205000029000000000115043600000003050000290000002005500039000000000654034f000000000606043b0000000000610435000000400130008a000006a90010009c000015440000213d000000600010008c000015440000413d000000400100043d000006b20010009c000015460000213d0000006003100039000000400030043f0000002003500039000000000534034f000000000505043b000000020050008c000015440000213d00000000055104360000002006300039000000000664034f000000000606043b00000000006504350000004005300039000000000554034f000000000505043b000000400610003900000000005604350000000205000029000000400550003900000000001504350000006001300039000000000114034f000000000101043b000006a00010009c000015440000213d0000000301100029000500000001001d0000001f01100039000000000021004b0000000003000019000006aa03008041000006aa01100197000006aa05200197000000000651013f000000000051004b0000000001000019000006aa01004041000006aa0060009c000000000103c019000000000001004b000015440000c13d0000000501400360000000000301043b000006a00030009c000015460000213d00000005073002100000003f01700039000006b101100197000000400600043d0000000001160019000100000006001d000000000061004b00000000060000390000000106004039000006a00010009c000015460000213d0000000100600190000015460000c13d000000400010043f0000000101000029000000000031043500000005010000290000002008100039000400000087001d000000040020006b000015440000213d000000040080006c000014e00000813d000000010a000029000014410000013d000000200aa000390000008001b000390000000000c104350000000000ba04350000002008800039000000040080006c000014e00000813d000000000184034f000000000101043b000006a00010009c000015440000213d0000000503100029000000200c3000390000000001c20049000006a90010009c000015440000213d000000e00010008c000015440000413d000000400b00043d000006b500b0009c000015460000213d000000a001b00039000000400010043f0000000001c4034f000000000101043b000006a80010009c000015440000213d00000000071b04360000002001c00039000000000614034f000000000606043b000006ab00600198000015440000c13d00000000006704350000002007100039000000000174034f000000000101043b0000004006b0003900000000001604350000000001320049000000800110008a000006a90010009c000015440000213d000000600010008c000015440000413d000000400300043d000006b20030009c000015460000213d0000006001300039000000400010043f0000002007700039000000000174034f000000000101043b000000020010008c000015440000213d00000000011304360000002006700039000000000664034f000000000606043b00000000006104350000004001700039000000000114034f000000000101043b000000400630003900000000001604350000006001b0003900000000003104350000006001700039000000000114034f000000000101043b000006a00010009c000015440000213d0000000003c100190000001f01300039000000000021004b0000000006000019000006aa06008041000006aa01100197000000000751013f000000000051004b0000000001000019000006aa01004041000006aa0070009c000000000106c019000000000001004b000015440000c13d000000000134034f000000000701043b000006a00070009c000015460000213d00000005017002100000003f01100039000006b101100197000000400c00043d00000000011c00190000000000c1004b00000000060000390000000106004039000006a00010009c000015460000213d0000000100600190000015460000c13d000000400010043f00000000007c0435000000200d300039000000c0017000c9000000000ed1001900000000002e004b000015440000213d0000000000ed004b0000143a0000813d000000000f0c00190000000001d20049000006a90010009c000015440000213d000000c00010008c000015440000413d000000400300043d000006a10030009c000015460000213d0000008001300039000000400010043f0000000001d4034f000000000101043b000000060010008c000015440000213d00000000071304360000002001d00039000000000614034f000000000606043b000006a00060009c000015440000213d00000000006704350000002001100039000000000614034f000000000606043b00000040073000390000000000670435000000400700043d000006b20070009c000015460000213d0000006006700039000000400060043f0000002001100039000000000614034f000000000606043b000000020060008c000015440000213d000000200ff0003900000000066704360000002009100039000000000994034f000000000909043b00000000009604350000004001100039000000000114034f000000000101043b000000400670003900000000001604350000006001300039000000000071043500000000003f0435000000c00dd000390000000000ed004b000014aa0000413d0000143a0000013d00000002010000290000006001100039000000010300002900000000003104350000000301000029000000c001100039000000000114034f000000000101043b000006a00010009c000015440000213d00000003011000290000001f03100039000000000023004b0000000006000019000006aa06008041000006aa03300197000000000753013f000000000053004b0000000003000019000006aa03004041000006aa0070009c000000000306c019000000000003004b000015440000c13d000000000314034f000000000603043b000006a00060009c000015460000213d00000005036002100000003f03300039000006b105300197000000400300043d0000000005530019000000000035004b00000000070000390000000107004039000006a00050009c000015460000213d0000000100700190000015460000c13d000000400050043f00000000006304350000002005100039000000a0016000c90000000006510019000000000026004b000015440000213d000000000065004b000015400000813d00000000070300190000000001520049000006a90010009c000015440000213d000000a00010008c000015440000413d000000400100043d000006b20010009c000015460000213d0000006008100039000000400080043f000000000854034f000000000808043b000006a80080009c000015440000213d00000000088104360000002009500039000000000a94034f000000000a0a043b0000000000a80435000000400800043d000006b20080009c000015460000213d000000600a8000390000004000a0043f0000002009900039000000000a94034f000000000a0a043b0000000200a0008c000015440000213d0000002007700039000000000aa80436000000200b900039000000000bb4034f000000000b0b043b0000000000ba04350000004009900039000000000994034f000000000909043b000000400a80003900000000009a0435000000400910003900000000008904350000000000170435000000a005500039000000000065004b000015120000413d000000020100002900000080021000390000000000320435000000000001042d000000000100001900001a1100010430000006b601000041000000000010043f0000004101000039000000040010043f000006b70100004100001a11000104300002000000000002000200000001001d000000000010043f0000000101000039000000200010043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000015b10000613d000000000101043b0000000002000411000006a802200197000100000002001d000000000020043f0000000101100039000000200010043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000015b10000613d000000000101043b000000000101041a000000ff0110018f000000040010008c000015b30000813d000000010010008c000015b90000c13d0000000201000029000000000010043f0000000101000039000000200010043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000015b10000613d000000000101043b0000000102000029000000000020043f0000000101100039000000200010043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000015b10000613d000000000101043b000000000201041a000006f10220019700000002022001bf000000000021041b0000000101000029000000000010043f000000200000043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000015b10000613d000000000101043b000000000201041a000000000002004b000015ca0000613d000000010220008a000000000021041b00000000010004140000068b0010009c0000068b01008041000000c001100210000006b8011001c70000800d020000390000000303000039000006e704000041000000000500041100000002060000291a0f1a050000040f0000000100200190000015b10000613d000000000001042d000000000100001900001a1100010430000006b601000041000000000010043f0000002101000039000000040010043f000006b70100004100001a1100010430000000400100043d0000004402100039000006e6030000410000000000320435000000240210003900000011030000390000000000320435000006a50200004100000000002104350000000402100039000000200300003900000000003204350000068b0010009c0000068b010080410000004001100210000006ba011001c700001a1100010430000006b601000041000000000010043f0000001101000039000000040010043f000006b70100004100001a11000104300008000000000002000000400f00043d0000002002f00039000000200300003900000000003204350000000053010434000006a8033001970000004004f0003900000000003404350000006003f00039000400000005001d00000000040504330000000000430435000800000001001d0000004001100039000500000001001d00000000030104330000000045030434000000030050008c000018010000813d0000008006f0003900000000005604350000000004040433000000a005f00039000000000045043500000040033000390000000003030433000000c004f00039000000000034043500000008010000290000006004100039000000e003f00039000000e001000039000300000004001d000000000404043300000000001304350000012003f00039000000000504043300000000005304350000014006f0003900000005035002100000000003630019000000000005004b000016490000613d0000000007000019000016010000013d0000000107700039000000000057004b000016490000813d0000000008f30049000001400880008a00000000068604360000002004400039000000000804043300000000a9080434000006a8099001970000000009930436000000000a0a0433000006ac0aa001970000000000a904350000004009300039000000400a800039000000000a0a04330000000000a904350000006009800039000000000909043300000000ab0904340000000200b0008c000018010000213d000000600c3000390000000000bc0435000000000a0a0433000000800b3000390000000000ab043500000040099000390000000009090433000000a00a30003900000000009a043500000080088000390000000008080433000000c0093000390000000000190435000000e00a300039000000000908043300000000009a04350000010003300039000000000009004b000015fe0000613d000000000a0000190000002008800039000000000b08043300000000cd0b04340000000600d0008c000018010000213d000000000dd30436000000000c0c0433000006a00cc001970000000000cd0435000000400c300039000000400db00039000000000d0d04330000000000dc0435000000600bb00039000000000b0b043300000000cd0b04340000000200d0008c000018010000213d000000600e3000390000000000de0435000000000c0c0433000000800d3000390000000000cd0435000000400bb00039000000000b0b0433000000a00c3000390000000000bc0435000000c003300039000000010aa0003900000000009a004b000016290000413d000015fe0000013d0000000004f30049000000400540008a0000010006f0003900000008010000290000008001100039000200000001001d0000000004010433000000000056043500000000050404330000000003530436000000000005004b0000166f0000613d0000000006000019000000200440003900000000070404330000000098070434000006a808800197000000000883043600000000090904330000000000980435000000400770003900000000070704330000000089070434000000020090008c000018010000213d000000400a30003900000000009a04350000000008080433000000600930003900000000008904350000004007700039000000000707043300000080083000390000000000780435000000a0033000390000000106600039000000000056004b000016560000413d0000000003f30049000000200430008a00000000004f04350000001f03300039000006f2043001970000000003f40019000000000043004b00000000040000390000000104004039000006a00030009c000018090000213d0000000100400190000018090000c13d000000400030043f0000068b0020009c0000068b02008041000000400220021000000000010f04330000068b0010009c0000068b010080410000006001100210000000000121019f00000000020004140000068b0020009c0000068b02008041000000c002200210000000000112019f000006b8011001c700008010020000391a0f1a0a0000040f0000000100200190000018070000613d000000000101043b000700000001001d000000400b00043d000006de0100004100000000001b04350000000401b000390000000002000410000000000021043500000000010004140000000002000411000006a802200197000000040020008c000600000002001d000016a20000c13d0000000103000031000000200030008c00000020040000390000000004034019000016cd0000013d0000068b00b0009c0000068b0300004100000000030b401900000040033002100000068b0010009c0000068b01008041000000c001100210000000000131019f000006b7011001c700010000000b001d1a0f1a0a0000040f000000010b00002900000060031002700000068b03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000016bd0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000016b90000c13d000000000006004b000016ca0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000100000003001f0000000100200190000018460000613d0000001f01400039000000600210018f0000000001b20019000000000021004b00000000020000390000000102004039000006a00010009c000018090000213d0000000100200190000018090000c13d000000400010043f000000200030008c000018070000413d00000000020b0433000000000002004b0000000003000039000000010300c039000000000032004b000018070000c13d000000000002004b0000180f0000613d00000008020000290000000002020433000006a800200198000018150000613d0000000701000029000000000010043f0000000101000039000000200010043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000018070000613d000000000101043b0000000602000029000000000020043f0000000101100039000000200010043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000018070000613d000000000101043b000000000101041a000000ff0110018f000000030010008c0000000602000029000018010000213d000000000001004b0000181b0000c13d000000050100002900000000010104330000000001010433000000020010008c000018010000213d000000000001004b0000182c0000613d000000000020043f000000200000043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000018070000613d000000000101043b000000000201041a000000010220003a000018400000613d000000000021041b0000000701000029000000000010043f0000000101000039000000200010043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000018070000613d000000000101043b0000000602000029000000000020043f0000000101100039000000200010043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000018070000613d000000000101043b000000000201041a000006f10220019700000001022001bf000000000021041b00000004010000290000000001010433000600000001001d0000000701000029000000000010043f0000000101000039000000200010043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000018070000613d000000000101043b0000000602000029000000000021041b000000400100043d0000002002000039000000000221043600000008030000290000000003030433000006a80330019700000000003204350000000402000029000000000202043300000040031000390000000000230435000000050200002900000000020204330000000034020434000000020040008c000000e00e000039000018010000213d0000006005100039000000000045043500000000030304330000008004100039000000000034043500000040022000390000000002020433000000a003100039000000000023043500000003020000290000000003020433000000c0021000390000000000e20435000001000210003900000000040304330000000000420435000001200510003900000005024002100000000002520019000000000004004b000017c60000613d00000000060000190000177e0000013d0000000106600039000000000046004b000017c60000813d0000000007120049000001200770008a0000000005750436000000200330003900000000070304330000000098070434000006a80880019700000000088204360000000009090433000006ac099001970000000000980435000000400820003900000040097000390000000009090433000000000098043500000060087000390000000008080433000000009a0804340000000200a0008c000018010000213d000000600b2000390000000000ab04350000000009090433000000800a20003900000000009a043500000040088000390000000008080433000000a009200039000000000089043500000080077000390000000007070433000000c0082000390000000000e80435000000e009200039000000000807043300000000008904350000010002200039000000000008004b0000177b0000613d00000000090000190000002007700039000000000a07043300000000bc0a04340000000600c0008c000018010000213d000000000cc20436000000000b0b0433000006a00bb001970000000000bc0435000000400b200039000000400ca00039000000000c0c04330000000000cb0435000000600aa00039000000000a0a043300000000bc0a04340000000200c0008c000018010000213d000000600d2000390000000000cd0435000000000b0b0433000000800c2000390000000000bc0435000000400aa00039000000000a0a0433000000a00b2000390000000000ab0435000000c0022000390000000109900039000000000089004b000017a60000413d0000177b0000013d0000000003120049000000200430008a00000002030000290000000003030433000000e005100039000000000045043500000000040304330000000002420436000000000004004b000017ea0000613d0000000005000019000000200330003900000000060304330000000087060434000006a807700197000000000772043600000000080804330000000000870435000000400660003900000000060604330000000078060434000000020080008c000018010000213d000000400920003900000000008904350000000007070433000000600820003900000000007804350000004006600039000000000606043300000080072000390000000000670435000000a0022000390000000105500039000000000045004b000017d10000413d00000000021200490000068b0020009c0000068b0200804100000060022002100000068b0010009c0000068b010080410000004001100210000000000112019f00000000020004140000068b0020009c0000068b02008041000000c002200210000000000121019f000006b8011001c70000800d020000390000000303000039000006f704000041000000000500041100000007060000291a0f1a050000040f0000000100200190000018070000613d000000000001042d000006b601000041000000000010043f0000002101000039000000040010043f000006b70100004100001a1100010430000000000100001900001a1100010430000006b601000041000000000010043f0000004101000039000000040010043f000006b70100004100001a11000104300000004402100039000006fb03000041000000000032043500000024021000390000001703000039000018210000013d0000004402100039000006fa03000041000000000032043500000024021000390000000e03000039000018210000013d000000400100043d0000004402100039000006f6030000410000000000320435000000240210003900000016030000390000000000320435000006a50200004100000000002104350000000402100039000000200300003900000000003204350000068b0010009c0000068b010080410000004001100210000006ba011001c700001a1100010430000000400100043d0000006402100039000006f80300004100000000003204350000004402100039000006f9030000410000000000320435000000240210003900000023030000390000000000320435000006a50200004100000000002104350000000402100039000000200300003900000000003204350000068b0010009c0000068b010080410000004001100210000006cb011001c700001a1100010430000006b601000041000000000010043f0000001101000039000000040010043f000006b70100004100001a11000104300000001f0530018f000006c206300198000000400200043d0000000004620019000018510000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000184d0000c13d000000000005004b0000185e0000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f000000000014043500000060013002100000068b0020009c0000068b020080410000004002200210000000000112019f00001a11000104300001000000000002000000400b00043d000006de0200004100000000002b04350000000402b00039000000000300041000000000003204350000000003000414000006a802100197000000040020008c000018740000c13d0000000103000031000000200030008c000000200400003900000000040340190000189f0000013d0000068b00b0009c0000068b0100004100000000010b401900000040011002100000068b0030009c0000068b03008041000000c003300210000000000113019f000006b7011001c700010000000b001d1a0f1a0a0000040f000000010b00002900000060031002700000068b03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b00190000188f0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b0000188b0000c13d000000000006004b0000189c0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000100000003001f0000000100200190000018bb0000613d0000001f01400039000000600210018f0000000001b20019000000000021004b00000000020000390000000102004039000006a00010009c000018b50000213d0000000100200190000018b50000c13d000000400010043f000000200030008c000018b30000413d00000000010b0433000000000001004b0000000002000039000000010200c039000000000021004b000018b30000c13d000000000001042d000000000100001900001a1100010430000006b601000041000000000010043f0000004101000039000000040010043f000006b70100004100001a11000104300000001f0530018f000006c206300198000000400200043d0000000004620019000018c60000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000018c20000c13d000000000005004b000018d30000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f000000000014043500000060013002100000068b0020009c0000068b020080410000004002200210000000000112019f00001a11000104300009000000000002000300000004001d000700000003001d000600000002001d0000000023010434000400000002001d000000030030008c000019ba0000813d000000010030008c000500000001001d000019130000c13d0000000001000411000006a801100197000200000001001d000000000010043f0000000601000029000000200010043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000019b80000613d000000000101043b000000000101041a000000070010002a000019c10000413d000000070110002900000004020000290000000002020433000000000021004b000019c70000213d0000000201000029000000000010043f0000000601000029000000200010043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000019b80000613d000000000101043b000000000201041a000000070020002a000019c10000413d0000000702200029000000000021041b00000005010000290000000003010433000000020030008c000019ba0000213d000000020030008c000019b70000c13d000006bb01000041000000000010044300000000010004140000068b0010009c0000068b01008041000000c001100210000006b4011001c70000800b020000391a0f1a0a0000040f0000000100200190000019c00000613d0000000002000415000000090220008a0000000502200210000000000101043b000001040010008c000006be05000041000006bd050060410000000501000029000000400110003900000000010104330000000303000029000006a00430019800000000064100a9000019380000613d00000000024600d9000000000012004b000019c10000c13d000006a00040009c000019c10000613d0000000002000415000000080220008a00000005022002100000000103400039000019390000013d000000010300003900000000071300a900000000033700d9000000000013004b000019c10000c13d000300000006001d000500000004001d0000000501200270000100000007001d000000000107001f000006bc010000410000000000100443000200000005001d000000040050044300000000010004140000068b0010009c0000068b01008041000000c001100210000006bf011001c700008002020000391a0f1a0a0000040f0000000100200190000019c00000613d000000000101043b000000000001004b0000000302000029000019b80000613d000000400400043d000000240140003900000001030000290000000000310435000006c0010000410000000000140435000000040140003900000000002104350000068b0040009c000300000004001d0000068b010000410000000001044019000000400110021000000000020004140000068b0020009c0000068b02008041000000c002200210000000000112019f000006c1011001c700000002020000291a0f1a0a0000040f00000060031002700001068b0030019d0000000100200190000019ce0000613d0000000302000029000006fc0020009c0000000501000029000019ed0000813d000000400020043f000000000010043f00000006010000290000000101100039000600000001001d000000200010043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000019b80000613d000000000101043b0000000002000411000006a802200197000300000002001d000000000020043f000000200010043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000019b80000613d000000000101043b000000000101041a000000070010002a0000000503000029000019c10000413d000000070110002900000004020000290000000002020433000000000021004b000019f30000213d000000000030043f0000000601000029000000200010043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000019b80000613d000000000101043b0000000302000029000000000020043f000000200010043f00000000010004140000068b0010009c0000068b01008041000000c001100210000006af011001c700008010020000391a0f1a0a0000040f0000000100200190000019b80000613d000000000101043b000000000201041a000000070020002a000019c10000413d0000000702200029000000000021041b000000000001042d000000000100001900001a1100010430000006b601000041000000000010043f0000002101000039000000040010043f000006b70100004100001a1100010430000000000001042f000006b601000041000000000010043f0000001101000039000000040010043f000006b70100004100001a1100010430000000400100043d0000004402100039000006fe03000041000000000032043500000024021000390000001703000039000019f90000013d0000068b033001970000001f0530018f000006c206300198000000400200043d0000000004620019000019da0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000019d60000c13d000000000005004b000019e70000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f000000000014043500000060013002100000068b0020009c0000068b020080410000004002200210000000000112019f00001a1100010430000006b601000041000000000010043f0000004101000039000000040010043f000006b70100004100001a1100010430000000400100043d0000004402100039000006fd030000410000000000320435000000240210003900000018030000390000000000320435000006a50200004100000000002104350000000402100039000000200300003900000000003204350000068b0010009c0000068b010080410000004001100210000006ba011001c700001a1100010430000000000001042f00001a08002104210000000102000039000000000001042d0000000002000019000000000001042d00001a0d002104230000000102000039000000000001042d0000000002000019000000000001042d00001a0f0000043200001a100001042e00001a11000104300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013250000000000000000000000000000000000000000000000000000000000001328000000000000000000000000000000000000000000000000000000000000132b000000000000000000000000000000000000000000000000000000000000132e000000000000000000000000000000000000000000000000000000000000133100000000000000000000000000000000000000000000000000000000000012a000000000000000000000000000000000000000000000000000000000ffffffff000000020000000000000000000000000000004000000100000000000000000000000000000000000000000000000000000000000000000000000000572f220f000000000000000000000000000000000000000000000000000000006d8bb27700000000000000000000000000000000000000000000000000000000b6d7501800000000000000000000000000000000000000000000000000000000b6d7501900000000000000000000000000000000000000000000000000000000d6443abb000000000000000000000000000000000000000000000000000000006d8bb27800000000000000000000000000000000000000000000000000000000a88b89a700000000000000000000000000000000000000000000000000000000572f22100000000000000000000000000000000000000000000000000000000059130708000000000000000000000000000000000000000000000000000000005a0694d2000000000000000000000000000000000000000000000000000000002f2770da000000000000000000000000000000000000000000000000000000004ddf47d3000000000000000000000000000000000000000000000000000000004ddf47d40000000000000000000000000000000000000000000000000000000054fd4d50000000000000000000000000000000000000000000000000000000002f2770db000000000000000000000000000000000000000000000000000000003ec592790000000000000000000000000000000000000000000000000000000001ffc9a70000000000000000000000000000000000000000000000000000000006fdde03000000000000000000000000000000000000000000000000000000000f23795f000000000000000000000000000000000000000000000000ffffffffffffffff000000000000000000000000000000000000000000000000ffffffffffffff7f696d6974732e00000000000000000000000000000000000000000000000000006c6561736520636865636b2073657373696f6e2073746174757320616e64206c53657373696f6e206b65792076616c69646174696f6e206661696c65642e205008c379a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a40000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff800000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fffffffffffffebf02000000000000000000000000000000000000000000016000000000000000000200000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff3f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0000000000000000000000000000000000000000000000000ffffffffffffff9f796b89b91644bc98cd93958e4c9038275d622183e25ac5af08cc6b5d955391320200000200000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff5f4e487b71000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000000000000000000000020000000000000000000000000000000000000000000000000000000000000053657373696f6e206973206e6f7420616374697665000000000000000000000000000000000000000000000000000000000000640000000000000000000000009a8a0592ac89c5ad3bc6df8224c17b485976f597df104ee20d0df415241f670b1806aa1896bbf26568e884a7374b41e002500962caba6a15023a8d90e8508b830000000000000000000000000000000000000000000000000000000000808012000000000000000000000000958f70e4fd676c9ceaafe5c48cb78cdd08b4880d02000002000000000000000000000000000000240000000000000000000000005b1a0c9100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004400000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffe0949431dc00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001fffffffffffffffe0000000000000000000000000000000000000000000000000ffffffffffffffe04e4f545f455155414c20636f6e73747261696e74206e6f74206d6574000000004c4553535f4f525f455155414c20636f6e73747261696e74206e6f74206d65746d65740000000000000000000000000000000000000000000000000000000000475245415445525f4f525f455155414c20636f6e73747261696e74206e6f742000000000000000000000000000000000000000840000000000000000000000004c45535320636f6e73747261696e74206e6f74206d65740000000000000000004752454154455220636f6e73747261696e74206e6f74206d6574000000000000455155414c20636f6e73747261696e74206e6f74206d657400000000000000006f7765640000000000000000000000000000000000000000000000000000000043616c6c20746f207468697320636f6e7472616374206973206e6f7420616c6c43616e206e6f74206d616e6167652073657373696f6e206b657973000000000043616e206e6f74207461726765742073656c66000000000000000000000000007fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a00000000000000000000000000000000000000080000000000000000000000000496e76616c6964207369676e657220286d69736d61746368290000000000000056616c75652065786365656473206c696d697400000000000000000000000000616c6c6f776564000000000000000000000000000000000000000000000000005472616e7366657220746f20746869732061646472657373206973206e6f74207420616c6c6f7765640000000000000000000000000000000000000000000000417070726f76616c206261736564207061796d617374657220666c6f77206e6f496e76616c6964207369676e65722028656d7074792900000000000000000000302e302e300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000d26765290000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000240000008000000000000000005265766f6b6520616c6c206b6579732066697273740000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffbf25f761f5000000000000000000000000000000000000000000000000000000002e0b437d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffff9bffffffffffffffffffffffffffffffffffffff9c0000000000000000000000004e6f7468696e6720746f207265766f6b65000000000000000000000000000000006be5f629d8df9f032986474cfc3bfc82c9b1cd74dcb2fcb5b3d48f98a50024cf23b00500000000000000000000000000000000000000000000000000000000be9c57030000000000000000000000000000000000000000000000000000000053657373696f6e4b657956616c696461746f7200000000000000000000000000fffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffff6d8bb277ffffffffffffffffffffffffffffffffffffffffffffffffffffffff7ecfb31c000000000000000000000000000000000000000000000000000000006d8bb2780000000000000000000000000000000000000000000000000000000001ffc9a7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000800000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff40000000000000000000000000000000000000000000000000ffffffffffffff6053657373696f6e20616c72656164792065786973747300000000000000000000225b7c57a9711566a3a2dabe5ba5d2c5965272461cd8af89883376ecb2f69ac46166650000000000000000000000000000000000000000000000000000000000556e6c696d697465642066656520616c6c6f77616e6365206973206e6f742073496e76616c6964207369676e65720000000000000000000000000000000000004163636f756e74206e6f7420696e697469616c697a65640000000000000000000000000000000000000000000000000000000000000000010000000000000000416c6c6f77616e6365206c696d697420657863656564656400000000000000004c69666574696d65206c696d69742065786365656465640000000000000000000000000000000000000000000000000000000000000000000000000000000000932b7814ed4070b927ea276499b7d26638ede27b00dc319054444ee11f6f1e3c
Loading...
Loading
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.