Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multichain Info
N/A
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
24795018 | 12 hrs ago | Contract Creation | 0 ETH |
Loading...
Loading
Similar Match Source Code This contract matches the deployed Bytecode of the Source Code for Contract 0xDE32690d...472bf7AFB The constructor portion of the code might be different and could alter the actual behaviour of the contract
Contract Name:
Bootstrap
Compiler Version
v0.8.28+commit.7893614a
Optimization Enabled:
Yes with 999 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; import {IBootstrap, BootstrapConfig} from "src/interfaces/IBootstrap.sol"; import {ModuleManager} from "src/core/ModuleManager.sol"; /// @title Bootstrap /// @notice Provides configuration and initialization for smart accounts contract Bootstrap is IBootstrap, ModuleManager { /// @inheritdoc IBootstrap function initialize( BootstrapConfig calldata rootValidator, BootstrapConfig[] calldata validators, BootstrapConfig[] calldata executors, BootstrapConfig[] calldata fallbacks, BootstrapConfig[] calldata hooks, BootstrapConfig calldata preValidationHook1271, BootstrapConfig calldata preValidationHook4337, address registry, address[] calldata attesters, uint8 threshold ) external payable { if (registry != address(0)) _configureRegistry(registry, attesters, threshold); _configureRootValidator(rootValidator.module, rootValidator.data); uint256 length = validators.length; for (uint256 i; i < length; ) { _installModule(MODULE_TYPE_VALIDATOR, validators[i].module, validators[i].data); unchecked { i = i + 1; } } length = executors.length; for (uint256 i; i < length; ) { _installModule(MODULE_TYPE_EXECUTOR, executors[i].module, executors[i].data); unchecked { i = i + 1; } } length = fallbacks.length; for (uint256 i; i < length; ) { _installModule(MODULE_TYPE_FALLBACK, fallbacks[i].module, fallbacks[i].data); unchecked { i = i + 1; } } length = hooks.length; for (uint256 i; i < length; ) { _installModule(MODULE_TYPE_HOOK, hooks[i].module, hooks[i].data); unchecked { i = i + 1; } } if (preValidationHook1271.module != address(0)) { _installModule( MODULE_TYPE_PREVALIDATION_HOOK_ERC1271, preValidationHook1271.module, preValidationHook1271.data ); } if (preValidationHook4337.module != address(0)) { _installModule( MODULE_TYPE_PREVALIDATION_HOOK_ERC4337, preValidationHook4337.module, preValidationHook4337.data ); } } /// @inheritdoc IBootstrap function initializeScoped( BootstrapConfig calldata rootValidator, BootstrapConfig[] calldata validators, BootstrapConfig[] calldata executors, BootstrapConfig[] calldata fallbacks, BootstrapConfig[] calldata hooks, address registry, address[] calldata attesters, uint8 threshold ) external payable { if (registry != address(0)) _configureRegistry(registry, attesters, threshold); _configureRootValidator(rootValidator.module, rootValidator.data); uint256 length = validators.length; for (uint256 i; i < length; ) { _installModule(MODULE_TYPE_VALIDATOR, validators[i].module, validators[i].data); unchecked { i = i + 1; } } length = executors.length; for (uint256 i; i < length; ) { _installModule(MODULE_TYPE_EXECUTOR, executors[i].module, executors[i].data); unchecked { i = i + 1; } } length = fallbacks.length; for (uint256 i; i < length; ) { _installModule(MODULE_TYPE_FALLBACK, fallbacks[i].module, fallbacks[i].data); unchecked { i = i + 1; } } length = hooks.length; for (uint256 i; i < length; ) { _installModule(MODULE_TYPE_HOOK, hooks[i].module, hooks[i].data); unchecked { i = i + 1; } } } /// @inheritdoc IBootstrap function initializeWithRootValidator( BootstrapConfig calldata rootValidator, address registry, address[] calldata attesters, uint8 threshold ) external payable { if (registry != address(0)) _configureRegistry(registry, attesters, threshold); _configureRootValidator(rootValidator.module, rootValidator.data); } /// @inheritdoc IBootstrap function getInitializeCalldata( BootstrapConfig calldata rootValidator, BootstrapConfig[] calldata validators, BootstrapConfig[] calldata executors, BootstrapConfig[] calldata fallbacks, BootstrapConfig[] calldata hooks, BootstrapConfig calldata preValidationHook1271, BootstrapConfig calldata preValidationHook4337, address registry, address[] calldata attesters, uint8 threshold ) external view returns (bytes memory callData) { callData = abi.encodePacked( address(this), abi.encodeCall( this.initialize, ( rootValidator, validators, executors, fallbacks, hooks, preValidationHook1271, preValidationHook4337, registry, attesters, threshold ) ) ); } /// @inheritdoc IBootstrap function getInitializeScopedCalldata( BootstrapConfig calldata rootValidator, BootstrapConfig[] calldata validators, BootstrapConfig[] calldata executors, BootstrapConfig[] calldata fallbacks, BootstrapConfig[] calldata hooks, address registry, address[] calldata attesters, uint8 threshold ) external view returns (bytes memory callData) { callData = abi.encodePacked( address(this), abi.encodeCall( this.initializeScoped, (rootValidator, validators, executors, fallbacks, hooks, registry, attesters, threshold) ) ); } /// @inheritdoc IBootstrap function getInitializeWithRootValidatorCalldata( BootstrapConfig calldata rootValidator, address registry, address[] calldata attesters, uint8 threshold ) external view returns (bytes memory callData) { callData = abi.encodePacked( address(this), abi.encodeCall(this.initializeWithRootValidator, (rootValidator, registry, attesters, threshold)) ); } /// @notice Returns the name of the the contract /// @return The name of the the contract function name() external pure returns (string memory) { return "Bootstrap"; } /// @notice Returns the version of the the contract /// @return The version of the the contract function version() external pure returns (string memory) { return "1.0.0"; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; struct BootstrapConfig { address module; bytes data; } interface IBootstrap { /// @notice Initializes the smart account with the root validator and other modules /// @param rootValidator Bootstrap configuration for the root validator module /// @param validators Bootstrap configurations for validator modules /// @param executors Bootstrap configurations for executor modules /// @param fallbacks Bootstrap configurations for fallback modules /// @param hooks Bootstrap configurations for hook modules /// @param preValidationHook1271 Bootstrap configurations for ERC-1271 preValidation hook module /// @param preValidationHook4337 Bootstrap configurations for ERC-4337 preValidation hook module /// @param registry The address of the ERC-7484 registry to be associated with the smart account /// @param attesters The list of trusted attester addresses for identity or permission verification /// @param threshold The minimum number of attesters required to validate an assertion or operation function initialize( BootstrapConfig calldata rootValidator, BootstrapConfig[] calldata validators, BootstrapConfig[] calldata executors, BootstrapConfig[] calldata fallbacks, BootstrapConfig[] calldata hooks, BootstrapConfig calldata preValidationHook1271, BootstrapConfig calldata preValidationHook4337, address registry, address[] calldata attesters, uint8 threshold ) external payable; /// @notice Initializes the smart account with the root validator and other modules /// @param rootValidator Bootstrap configuration for the root validator module /// @param validators Bootstrap configurations for validator modules /// @param executors Bootstrap configurations for executor modules /// @param fallbacks Bootstrap configurations for fallback modules /// @param hooks Bootstrap configurations for hook modules /// @param registry The address of the ERC-7484 registry to be associated with the smart account /// @param attesters The list of trusted attester addresses for identity or permission verification /// @param threshold The minimum number of attesters required to validate an assertion or operation function initializeScoped( BootstrapConfig calldata rootValidator, BootstrapConfig[] calldata validators, BootstrapConfig[] calldata executors, BootstrapConfig[] calldata fallbacks, BootstrapConfig[] calldata hooks, address registry, address[] calldata attesters, uint8 threshold ) external payable; /// @notice Initializes the smart account with the root validator /// @param rootValidator Bootstrap configuration for the root validator module /// @param registry The address of the ERC-7484 registry to be associated with the smart account /// @param attesters The list of trusted attester addresses for identity or permission verification /// @param threshold The minimum number of attesters required to validate an assertion or operation function initializeWithRootValidator( BootstrapConfig calldata rootValidator, address registry, address[] calldata attesters, uint8 threshold ) external payable; /// @notice Prepares calldata for the initialize function /// @param rootValidator Bootstrap configuration for the root validator module /// @param validators Bootstrap configurations for validator modules /// @param executors Bootstrap configurations for executor modules /// @param fallbacks Bootstrap configurations for fallback modules /// @param hooks Bootstrap configurations for hook modules /// @param preValidationHook1271 Bootstrap configurations for ERC-1271 preValidation hook module /// @param preValidationHook4337 Bootstrap configurations for ERC-4337 preValidation hook module /// @param registry The address of the ERC-7484 registry to be associated with the smart account /// @param attesters The list of trusted attester addresses for identity or permission verification /// @param threshold The minimum number of attesters required to validate an assertion or operation /// @return callData The prepared calldata for initialize function getInitializeCalldata( BootstrapConfig calldata rootValidator, BootstrapConfig[] calldata validators, BootstrapConfig[] calldata executors, BootstrapConfig[] calldata fallbacks, BootstrapConfig[] calldata hooks, BootstrapConfig calldata preValidationHook1271, BootstrapConfig calldata preValidationHook4337, address registry, address[] calldata attesters, uint8 threshold ) external view returns (bytes memory callData); /// @notice Prepares calldata for the initializeScoped function /// @param rootValidator Bootstrap configuration for the root validator module /// @param validators Bootstrap configurations for validator modules /// @param executors Bootstrap configurations for executor modules /// @param fallbacks Bootstrap configurations for fallback modules /// @param hooks Bootstrap configurations for hook modules /// @param registry The address of the ERC-7484 registry to be associated with the smart account /// @param attesters The list of trusted attester addresses for identity or permission verification /// @param threshold The minimum number of attesters required to validate an assertion or operation /// @return callData The prepared calldata for initializeScoped function getInitializeScopedCalldata( BootstrapConfig calldata rootValidator, BootstrapConfig[] calldata validators, BootstrapConfig[] calldata executors, BootstrapConfig[] calldata fallbacks, BootstrapConfig[] calldata hooks, address registry, address[] calldata attesters, uint8 threshold ) external view returns (bytes memory callData); /// @notice Prepares calldata for the initializeWithRootValidator function /// @param rootValidator Bootstrap configuration for the root validator module /// @param registry The address of the ERC-7484 registry to be associated with the smart account /// @param attesters The list of trusted attester addresses for identity or permission verification /// @param threshold The minimum number of attesters required to validate an assertion or operation /// @return callData The prepared calldata for initializeScoped function getInitializeWithRootValidatorCalldata( BootstrapConfig calldata rootValidator, address registry, address[] calldata attesters, uint8 threshold ) external view returns (bytes memory callData); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; import {EnumerableSetLib} from "solady/utils/EnumerableSetLib.sol"; import {Calldata} from "src/libraries/Calldata.sol"; import {CalldataDecoder} from "src/libraries/CalldataDecoder.sol"; import {CallType, ModuleType} from "src/types/DataTypes.sol"; import {AccessControl} from "./AccessControl.sol"; import {ERC7201} from "./ERC7201.sol"; import {RegistryAdapter} from "./RegistryAdapter.sol"; /// @title ModuleManager /// @notice Implements ERC-7579 standards for module management abstract contract ModuleManager is AccessControl, ERC7201, RegistryAdapter { using CalldataDecoder for bytes; using EnumerableSetLib for EnumerableSetLib.AddressSet; error ModuleAlreadyInstalled(ModuleType moduleTypeId, address module); error ModuleNotInstalled(ModuleType moduleTypeId, address module); error UnsupportedPreValidationHookType(ModuleType moduleTypeId); error InvalidRootValidator(); error RootValidatorCannotBeRemoved(); event RootValidatorConfigured(address indexed rootValidator); /// @dev keccak256("ModuleInstalled(uint256,address)") bytes32 private constant MODULE_INSTALLED_TOPIC = 0xd21d0b289f126c4b473ea641963e766833c2f13866e4ff480abd787c100ef123; /// @dev keccak256("ModuleUninstalled(uint256,address)") bytes32 private constant MODULE_UNINSTALLED_TOPIC = 0x341347516a9de374859dfda710fa4828b2d48cb57d4fbe4c1149612b8e02276e; /// @dev keccak256(abi.encode(uint256(keccak256("eip7579.vortex.storage.fallbacks")) - 1)) & ~bytes32(uint256(0xff)) bytes32 internal constant FALLBACKS_STORAGE_SLOT = 0x6aa9b80a3ef8fd7c61052fd742393c4cad924e6f735976eb39535648c67cd200; /// @dev keccak256(abi.encode(uint256(keccak256("eip7579.vortex.storage.hooks")) - 1)) & ~bytes32(uint256(0xff)) bytes32 internal constant HOOKS_STORAGE_SLOT = 0x804aa2c00aa2afd5774b5603b005ba2fe99b98231bb0faa297c8cbc51d78c800; address internal constant SMART_SESSION = 0x00000000002B0eCfbD0496EE71e01257dA0E37DE; address internal constant SENTINEL = 0x0000000000000000000000000000000000000001; address internal constant ZERO = 0x0000000000000000000000000000000000000000; ModuleType internal constant MODULE_TYPE_MULTI = ModuleType.wrap(0x00); ModuleType internal constant MODULE_TYPE_VALIDATOR = ModuleType.wrap(0x01); ModuleType internal constant MODULE_TYPE_EXECUTOR = ModuleType.wrap(0x02); ModuleType internal constant MODULE_TYPE_FALLBACK = ModuleType.wrap(0x03); ModuleType internal constant MODULE_TYPE_HOOK = ModuleType.wrap(0x04); ModuleType internal constant MODULE_TYPE_POLICY = ModuleType.wrap(0x05); ModuleType internal constant MODULE_TYPE_SIGNER = ModuleType.wrap(0x06); ModuleType internal constant MODULE_TYPE_STATELESS_VALIDATOR = ModuleType.wrap(0x07); ModuleType internal constant MODULE_TYPE_PREVALIDATION_HOOK_ERC1271 = ModuleType.wrap(0x08); ModuleType internal constant MODULE_TYPE_PREVALIDATION_HOOK_ERC4337 = ModuleType.wrap(0x09); function _configureRootValidator(address rootValidator, bytes calldata data) internal virtual { AccountStorage storage state = _getAccountStorage(); if (rootValidator == address(0) || rootValidator == state.rootValidator) revert InvalidRootValidator(); if (!state.validators.contains(rootValidator)) _installModule(MODULE_TYPE_VALIDATOR, rootValidator, data); else if (!_isInitialized(rootValidator)) _invokeOnInstall(rootValidator, data); _setRootValidator(rootValidator); } function _setRootValidator(address module) internal virtual { emit RootValidatorConfigured(_getAccountStorage().rootValidator = module); } function _rootValidator() internal view virtual returns (address rootValidator) { return _getAccountStorage().rootValidator; } function _installModule( ModuleType moduleTypeId, address module, bytes calldata data ) internal virtual withRegistry(module, moduleTypeId) { _validateModuleType(moduleTypeId, module); address hook; bytes calldata hookData; (data, hook, hookData) = data.decodeInstallModuleParams(); AccountStorage storage state = _getAccountStorage(); if (moduleTypeId == MODULE_TYPE_VALIDATOR || moduleTypeId == MODULE_TYPE_STATELESS_VALIDATOR) { require(state.validators.add(module), ModuleAlreadyInstalled(MODULE_TYPE_VALIDATOR, module)); } else if (moduleTypeId == MODULE_TYPE_EXECUTOR) { require(state.executors.add(module), ModuleAlreadyInstalled(MODULE_TYPE_EXECUTOR, module)); } else if (moduleTypeId == MODULE_TYPE_FALLBACK) { bytes32[] calldata selectors; (selectors, data) = data.decodeFallbackParams(); _installFallback(module, selectors); } else if (moduleTypeId == MODULE_TYPE_HOOK) { require(state.hooks.add(module), ModuleAlreadyInstalled(MODULE_TYPE_HOOK, module)); } else if ( moduleTypeId == MODULE_TYPE_PREVALIDATION_HOOK_ERC1271 || moduleTypeId == MODULE_TYPE_PREVALIDATION_HOOK_ERC4337 ) { _installPreValidationHook(moduleTypeId, module); } assembly ("memory-safe") { module := shr(0x60, shl(0x60, module)) mstore(0x00, module) mstore(0x20, HOOKS_STORAGE_SLOT) sstore(keccak256(0x00, 0x40), shr(0x60, shl(0x60, hook))) let ptr := mload(0x40) mstore(ptr, moduleTypeId) mstore(add(ptr, 0x20), module) log1(ptr, 0x40, MODULE_INSTALLED_TOPIC) } if (!_isInitialized(module)) _invokeOnInstall(module, data); if (hook != SENTINEL && !_isInitialized(hook)) _invokeOnInstall(hook, hookData); } function _uninstallModule(ModuleType moduleTypeId, address module, bytes calldata data) internal virtual { _validateModuleType(moduleTypeId, module); address hook; bytes calldata hookData; (data, hookData) = data.decodeUninstallModuleParams(); AccountStorage storage state = _getAccountStorage(); if (moduleTypeId == MODULE_TYPE_VALIDATOR || moduleTypeId == MODULE_TYPE_STATELESS_VALIDATOR) { require(state.rootValidator != module, RootValidatorCannotBeRemoved()); require(state.validators.remove(module), ModuleNotInstalled(MODULE_TYPE_VALIDATOR, module)); } else if (moduleTypeId == MODULE_TYPE_EXECUTOR) { require(state.executors.remove(module), ModuleNotInstalled(MODULE_TYPE_EXECUTOR, module)); } else if (moduleTypeId == MODULE_TYPE_FALLBACK) { bytes32[] calldata selectors; (selectors, data) = data.decodeFallbackParams(); _uninstallFallback(module, selectors); } else if (moduleTypeId == MODULE_TYPE_HOOK) { require(state.hooks.remove(module), ModuleNotInstalled(MODULE_TYPE_HOOK, module)); } else if ( moduleTypeId == MODULE_TYPE_PREVALIDATION_HOOK_ERC1271 || moduleTypeId == MODULE_TYPE_PREVALIDATION_HOOK_ERC4337 ) { _setPreValidationHook(moduleTypeId, module); } assembly ("memory-safe") { module := shr(0x60, shl(0x60, module)) mstore(0x00, module) mstore(0x20, HOOKS_STORAGE_SLOT) let slot := keccak256(0x00, 0x40) hook := shr(0x60, shl(0x60, sload(slot))) sstore(slot, 0x00) let ptr := mload(0x40) mstore(ptr, moduleTypeId) mstore(add(ptr, 0x20), module) log1(ptr, 0x40, MODULE_UNINSTALLED_TOPIC) } if (_isInitialized(module)) _invokeOnUninstall(module, data); if (hook != SENTINEL && _isInitialized(hook)) _invokeOnUninstall(hook, hookData); } function _isModuleInstalled( ModuleType moduleTypeId, address module, bytes calldata additionalContext ) internal view virtual returns (bool installed) { if (moduleTypeId == MODULE_TYPE_VALIDATOR || moduleTypeId == MODULE_TYPE_STATELESS_VALIDATOR) { return _getAccountStorage().validators.contains(module); } else if (moduleTypeId == MODULE_TYPE_EXECUTOR) { return _getAccountStorage().executors.contains(module); } else if (moduleTypeId == MODULE_TYPE_FALLBACK) { return _isFallbackInstalled(module, additionalContext); } else if (moduleTypeId == MODULE_TYPE_HOOK) { return _getAccountStorage().hooks.contains(module); } else if ( moduleTypeId == MODULE_TYPE_PREVALIDATION_HOOK_ERC1271 || moduleTypeId == MODULE_TYPE_PREVALIDATION_HOOK_ERC4337 ) { return _getPreValidationHook(moduleTypeId) == module; } else { return false; } } function _installFallback(address module, bytes32[] calldata selectors) internal virtual { assembly ("memory-safe") { mstore(0x20, FALLBACKS_STORAGE_SLOT) let configuration let callType let selector let slot // prettier-ignore for { let i } lt(i, selectors.length) { i := add(i, 0x01) } { configuration := calldataload(add(selectors.offset, shl(0x05, i))) callType := shr(0xf8, shl(0x20, configuration)) selector := shr(0xe0, configuration) // CALLTYPE_SINGLE: 0x00 | CALLTYPE_STATIC: 0xFE | CALLTYPE_DELEGATE: 0xFF if iszero(or(iszero(callType), or(eq(callType, 0xFE), eq(callType, 0xFF)))) { mstore(0x00, 0xb96fcfe4) // UnsupportedCallType(bytes1) mstore(0x20, shl(0xf8, callType)) revert(0x1c, 0x24) } if or(iszero(selector), or(eq(selector, 0x6d61fe70), eq(selector, 0x8a91b0e3))) { mstore(0x00, 0x9ff8cd94) // ForbiddenSelector(bytes4) mstore(0x20, shl(0xe0, selector)) revert(0x1c, 0x24) } mstore(0x00, shl(0xe0, selector)) slot := keccak256(0x00, 0x40) if sload(slot) { mstore(0x00, 0x172c3c6a) // ModuleAlreadyInstalled(uint256,address) mstore(0x20, 0x03) mstore(0x40, module) revert(0x1c, 0x44) } sstore(slot, or(shl(0xf8, callType), module)) } } } function _uninstallFallback(address module, bytes32[] calldata selectors) internal virtual { assembly ("memory-safe") { mstore(0x20, FALLBACKS_STORAGE_SLOT) let selector let slot // prettier-ignore for { let i } lt(i, selectors.length) { i := add(i, 0x01) } { selector := shr(0xe0, calldataload(add(selectors.offset, shl(0x05, i)))) if or(iszero(selector), or(eq(selector, 0x6d61fe70), eq(selector, 0x8a91b0e3))) { mstore(0x00, 0x9ff8cd94) // ForbiddenSelector(bytes4) mstore(0x20, shl(0xe0, selector)) revert(0x1c, 0x24) } mstore(0x00, shl(0xe0, selector)) slot := keccak256(0x00, 0x40) if iszero(sload(slot)) { mstore(0x00, 0xbe601672) // ModuleNotInstalled(uint256,address) mstore(0x20, 0x03) mstore(0x40, module) revert(0x1c, 0x44) } sstore(slot, 0x00) } } } function _isFallbackInstalled(address module, bytes calldata data) internal view virtual returns (bool result) { assembly ("memory-safe") { if lt(data.length, 0x04) { mstore(0x00, 0xdfe93090) // InvalidDataLength() revert(0x1c, 0x04) } mstore(0x00, shl(0xe0, shr(0xe0, calldataload(data.offset)))) mstore(0x20, FALLBACKS_STORAGE_SLOT) result := eq(module, shr(0x60, shl(0x60, sload(keccak256(0x00, 0x40))))) } } function _getFallbackHandler(bytes4 selector) internal view virtual returns (CallType callType, address module) { assembly ("memory-safe") { mstore(0x00, shl(0xe0, shr(0xe0, selector))) mstore(0x20, FALLBACKS_STORAGE_SLOT) let configuration := sload(keccak256(0x00, 0x40)) if configuration { callType := shl(0xf8, shr(0xf8, configuration)) module := shr(0x60, shl(0x60, configuration)) } } } function _installPreValidationHook(ModuleType moduleTypeId, address module) internal virtual { require(_getPreValidationHook(moduleTypeId) == address(0), ModuleAlreadyInstalled(moduleTypeId, module)); _setPreValidationHook(moduleTypeId, module); } function _setPreValidationHook(ModuleType moduleTypeId, address module) internal virtual { _validatePreValidationHookType(moduleTypeId); _getAccountStorage().preValidationHooks[moduleTypeId] = module; } function _getPreValidationHook(ModuleType moduleTypeId) internal view virtual returns (address preValidationHook) { return _getAccountStorage().preValidationHooks[moduleTypeId]; } function _getValidators() internal view virtual returns (address[] memory validators) { return _getAccountStorage().validators.values(); } function _getExecutors() internal view virtual returns (address[] memory executors) { return _getAccountStorage().executors.values(); } function _getHooks() internal view virtual returns (address[] memory hooks) { return _getAccountStorage().hooks.values(); } function _getHook(address module) internal view virtual returns (address hook) { assembly ("memory-safe") { module := shr(0x60, shl(0x60, module)) mstore(0x00, module) mstore(0x20, HOOKS_STORAGE_SLOT) hook := shr(0x60, shl(0x60, sload(keccak256(0x00, 0x40)))) if iszero(hook) { mstore(0x00, 0x026d9639) // ModuleNotInstalled(address) mstore(0x20, module) revert(0x1c, 0x24) } } } function _invokeOnInstall(address module, bytes calldata data) internal virtual { assembly ("memory-safe") { let ptr := mload(0x40) mstore(ptr, 0x6d61fe7000000000000000000000000000000000000000000000000000000000) // onInstall(bytes) mstore(add(ptr, 0x04), 0x20) mstore(add(ptr, 0x24), data.length) calldatacopy(add(ptr, 0x44), data.offset, data.length) if iszero(call(gas(), module, 0x00, ptr, add(data.length, 0x44), 0x00, 0x00)) { returndatacopy(ptr, 0x00, returndatasize()) revert(ptr, returndatasize()) } } } function _invokeOnUninstall(address module, bytes calldata data) internal virtual { assembly ("memory-safe") { let ptr := mload(0x40) mstore(ptr, 0x8a91b0e300000000000000000000000000000000000000000000000000000000) // onUninstall(bytes) mstore(add(ptr, 0x04), 0x20) mstore(add(ptr, 0x24), data.length) calldatacopy(add(ptr, 0x44), data.offset, data.length) if iszero(call(gas(), module, 0x00, ptr, add(data.length, 0x44), 0x00, 0x00)) { returndatacopy(ptr, 0x00, returndatasize()) revert(ptr, returndatasize()) } } } function _isInitialized(address module) internal view virtual returns (bool result) { assembly ("memory-safe") { let ptr := mload(0x40) mstore(ptr, 0xd60b347f00000000000000000000000000000000000000000000000000000000) // isInitialized(address) mstore(add(ptr, 0x04), shr(0x60, shl(0x60, address()))) if iszero(staticcall(gas(), module, ptr, 0x24, 0x00, 0x20)) { returndatacopy(ptr, 0x00, returndatasize()) revert(ptr, returndatasize()) } result := mload(0x00) } } function _validateModuleType(ModuleType moduleTypeId, address module) internal view virtual { assembly ("memory-safe") { if or( or(iszero(moduleTypeId), gt(moduleTypeId, 0x09)), or(eq(moduleTypeId, 0x05), eq(moduleTypeId, 0x06)) ) { mstore(0x00, 0x41c38b30) // UnsupportedModuleType(uint256) mstore(0x20, moduleTypeId) revert(0x1c, 0x24) } if iszero(shl(0x60, module)) { mstore(0x00, 0xdd914b28) // InvalidModule() revert(0x1c, 0x04) } let ptr := mload(0x40) mstore(ptr, 0xecd0596100000000000000000000000000000000000000000000000000000000) // isModuleType(uint256) mstore(add(ptr, 0x04), moduleTypeId) if iszero(staticcall(gas(), module, ptr, 0x24, 0x00, 0x20)) { returndatacopy(ptr, 0x00, returndatasize()) revert(ptr, returndatasize()) } if iszero(mload(0x00)) { mstore(0x00, 0x2125deae) // InvalidModuleType() revert(0x1c, 0x04) } } } function _validatePreValidationHookType(ModuleType moduleTypeId) internal pure virtual { assembly ("memory-safe") { if iszero(or(eq(moduleTypeId, 0x08), eq(moduleTypeId, 0x09))) { mstore(0x00, 0xa86ebca7) // UnsupportedPreValidationHookType(uint256) mstore(0x20, moduleTypeId) revert(0x1c, 0x24) } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Library for managing enumerable sets in storage. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/EnumerableSetLib.sol) /// /// @dev Note: /// In many applications, the number of elements in an enumerable set is small. /// This enumerable set implementation avoids storing the length and indices /// for up to 3 elements. Once the length exceeds 3 for the first time, the length /// and indices will be initialized. The amortized cost of adding elements is O(1). /// /// The AddressSet implementation packs the length with the 0th entry. /// /// All enumerable sets except Uint8Set use a pop and swap mechanism to remove elements. /// This means that the iteration order of elements can change between element removals. library EnumerableSetLib { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The index must be less than the length. error IndexOutOfBounds(); /// @dev The value cannot be the zero sentinel. error ValueIsZeroSentinel(); /// @dev Cannot accommodate a new unique value with the capacity. error ExceedsCapacity(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CONSTANTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev A sentinel value to denote the zero value in storage. /// No elements can be equal to this value. /// `uint72(bytes9(keccak256(bytes("_ZERO_SENTINEL"))))`. uint256 private constant _ZERO_SENTINEL = 0xfbb67fda52d4bfb8bf; /// @dev The storage layout is given by: /// ``` /// mstore(0x04, _ENUMERABLE_ADDRESS_SET_SLOT_SEED) /// mstore(0x00, set.slot) /// let rootSlot := keccak256(0x00, 0x24) /// mstore(0x20, rootSlot) /// mstore(0x00, shr(96, shl(96, value))) /// let positionSlot := keccak256(0x00, 0x40) /// let valueSlot := add(rootSlot, sload(positionSlot)) /// let valueInStorage := shr(96, sload(valueSlot)) /// let lazyLength := shr(160, shl(160, sload(rootSlot))) /// ``` uint256 private constant _ENUMERABLE_ADDRESS_SET_SLOT_SEED = 0x978aab92; /// @dev The storage layout is given by: /// ``` /// mstore(0x04, _ENUMERABLE_WORD_SET_SLOT_SEED) /// mstore(0x00, set.slot) /// let rootSlot := keccak256(0x00, 0x24) /// mstore(0x20, rootSlot) /// mstore(0x00, value) /// let positionSlot := keccak256(0x00, 0x40) /// let valueSlot := add(rootSlot, sload(positionSlot)) /// let valueInStorage := sload(valueSlot) /// let lazyLength := sload(not(rootSlot)) /// ``` uint256 private constant _ENUMERABLE_WORD_SET_SLOT_SEED = 0x18fb5864; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* STRUCTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev An enumerable address set in storage. struct AddressSet { uint256 _spacer; } /// @dev An enumerable bytes32 set in storage. struct Bytes32Set { uint256 _spacer; } /// @dev An enumerable uint256 set in storage. struct Uint256Set { uint256 _spacer; } /// @dev An enumerable int256 set in storage. struct Int256Set { uint256 _spacer; } /// @dev An enumerable uint8 set in storage. Useful for enums. struct Uint8Set { uint256 data; } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* GETTERS / SETTERS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the number of elements in the set. function length(AddressSet storage set) internal view returns (uint256 result) { bytes32 rootSlot = _rootSlot(set); /// @solidity memory-safe-assembly assembly { let rootPacked := sload(rootSlot) let n := shr(160, shl(160, rootPacked)) result := shr(1, n) for {} iszero(or(iszero(shr(96, rootPacked)), n)) {} { result := 1 if iszero(sload(add(rootSlot, result))) { break } result := 2 if iszero(sload(add(rootSlot, result))) { break } result := 3 break } } } /// @dev Returns the number of elements in the set. function length(Bytes32Set storage set) internal view returns (uint256 result) { bytes32 rootSlot = _rootSlot(set); /// @solidity memory-safe-assembly assembly { let n := sload(not(rootSlot)) result := shr(1, n) for {} iszero(n) {} { result := 0 if iszero(sload(add(rootSlot, result))) { break } result := 1 if iszero(sload(add(rootSlot, result))) { break } result := 2 if iszero(sload(add(rootSlot, result))) { break } result := 3 break } } } /// @dev Returns the number of elements in the set. function length(Uint256Set storage set) internal view returns (uint256 result) { result = length(_toBytes32Set(set)); } /// @dev Returns the number of elements in the set. function length(Int256Set storage set) internal view returns (uint256 result) { result = length(_toBytes32Set(set)); } /// @dev Returns the number of elements in the set. function length(Uint8Set storage set) internal view returns (uint256 result) { /// @solidity memory-safe-assembly assembly { for { let packed := sload(set.slot) } packed { result := add(1, result) } { packed := xor(packed, and(packed, add(1, not(packed)))) } } } /// @dev Returns whether `value` is in the set. function contains(AddressSet storage set, address value) internal view returns (bool result) { bytes32 rootSlot = _rootSlot(set); /// @solidity memory-safe-assembly assembly { value := shr(96, shl(96, value)) if eq(value, _ZERO_SENTINEL) { mstore(0x00, 0xf5a267f1) // `ValueIsZeroSentinel()`. revert(0x1c, 0x04) } if iszero(value) { value := _ZERO_SENTINEL } let rootPacked := sload(rootSlot) for {} 1 {} { if iszero(shr(160, shl(160, rootPacked))) { result := 1 if eq(shr(96, rootPacked), value) { break } if eq(shr(96, sload(add(rootSlot, 1))), value) { break } if eq(shr(96, sload(add(rootSlot, 2))), value) { break } result := 0 break } mstore(0x20, rootSlot) mstore(0x00, value) result := iszero(iszero(sload(keccak256(0x00, 0x40)))) break } } } /// @dev Returns whether `value` is in the set. function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool result) { bytes32 rootSlot = _rootSlot(set); /// @solidity memory-safe-assembly assembly { if eq(value, _ZERO_SENTINEL) { mstore(0x00, 0xf5a267f1) // `ValueIsZeroSentinel()`. revert(0x1c, 0x04) } if iszero(value) { value := _ZERO_SENTINEL } for {} 1 {} { if iszero(sload(not(rootSlot))) { result := 1 if eq(sload(rootSlot), value) { break } if eq(sload(add(rootSlot, 1)), value) { break } if eq(sload(add(rootSlot, 2)), value) { break } result := 0 break } mstore(0x20, rootSlot) mstore(0x00, value) result := iszero(iszero(sload(keccak256(0x00, 0x40)))) break } } } /// @dev Returns whether `value` is in the set. function contains(Uint256Set storage set, uint256 value) internal view returns (bool result) { result = contains(_toBytes32Set(set), bytes32(value)); } /// @dev Returns whether `value` is in the set. function contains(Int256Set storage set, int256 value) internal view returns (bool result) { result = contains(_toBytes32Set(set), bytes32(uint256(value))); } /// @dev Returns whether `value` is in the set. function contains(Uint8Set storage set, uint8 value) internal view returns (bool result) { /// @solidity memory-safe-assembly assembly { result := and(1, shr(and(0xff, value), sload(set.slot))) } } /// @dev Adds `value` to the set. Returns whether `value` was not in the set. function add(AddressSet storage set, address value) internal returns (bool result) { bytes32 rootSlot = _rootSlot(set); /// @solidity memory-safe-assembly assembly { value := shr(96, shl(96, value)) if eq(value, _ZERO_SENTINEL) { mstore(0x00, 0xf5a267f1) // `ValueIsZeroSentinel()`. revert(0x1c, 0x04) } if iszero(value) { value := _ZERO_SENTINEL } let rootPacked := sload(rootSlot) for { let n := shr(160, shl(160, rootPacked)) } 1 {} { mstore(0x20, rootSlot) if iszero(n) { let v0 := shr(96, rootPacked) if iszero(v0) { sstore(rootSlot, shl(96, value)) result := 1 break } if eq(v0, value) { break } let v1 := shr(96, sload(add(rootSlot, 1))) if iszero(v1) { sstore(add(rootSlot, 1), shl(96, value)) result := 1 break } if eq(v1, value) { break } let v2 := shr(96, sload(add(rootSlot, 2))) if iszero(v2) { sstore(add(rootSlot, 2), shl(96, value)) result := 1 break } if eq(v2, value) { break } mstore(0x00, v0) sstore(keccak256(0x00, 0x40), 1) mstore(0x00, v1) sstore(keccak256(0x00, 0x40), 2) mstore(0x00, v2) sstore(keccak256(0x00, 0x40), 3) rootPacked := or(rootPacked, 7) n := 7 } mstore(0x00, value) let p := keccak256(0x00, 0x40) if iszero(sload(p)) { n := shr(1, n) result := 1 sstore(p, add(1, n)) if iszero(n) { sstore(rootSlot, or(3, shl(96, value))) break } sstore(add(rootSlot, n), shl(96, value)) sstore(rootSlot, add(2, rootPacked)) break } break } } } /// @dev Adds `value` to the set. Returns whether `value` was not in the set. function add(Bytes32Set storage set, bytes32 value) internal returns (bool result) { bytes32 rootSlot = _rootSlot(set); /// @solidity memory-safe-assembly assembly { if eq(value, _ZERO_SENTINEL) { mstore(0x00, 0xf5a267f1) // `ValueIsZeroSentinel()`. revert(0x1c, 0x04) } if iszero(value) { value := _ZERO_SENTINEL } for { let n := sload(not(rootSlot)) } 1 {} { mstore(0x20, rootSlot) if iszero(n) { let v0 := sload(rootSlot) if iszero(v0) { sstore(rootSlot, value) result := 1 break } if eq(v0, value) { break } let v1 := sload(add(rootSlot, 1)) if iszero(v1) { sstore(add(rootSlot, 1), value) result := 1 break } if eq(v1, value) { break } let v2 := sload(add(rootSlot, 2)) if iszero(v2) { sstore(add(rootSlot, 2), value) result := 1 break } if eq(v2, value) { break } mstore(0x00, v0) sstore(keccak256(0x00, 0x40), 1) mstore(0x00, v1) sstore(keccak256(0x00, 0x40), 2) mstore(0x00, v2) sstore(keccak256(0x00, 0x40), 3) n := 7 } mstore(0x00, value) let p := keccak256(0x00, 0x40) if iszero(sload(p)) { n := shr(1, n) sstore(add(rootSlot, n), value) sstore(p, add(1, n)) sstore(not(rootSlot), or(1, shl(1, add(1, n)))) result := 1 break } break } } } /// @dev Adds `value` to the set. Returns whether `value` was not in the set. function add(Uint256Set storage set, uint256 value) internal returns (bool result) { result = add(_toBytes32Set(set), bytes32(value)); } /// @dev Adds `value` to the set. Returns whether `value` was not in the set. function add(Int256Set storage set, int256 value) internal returns (bool result) { result = add(_toBytes32Set(set), bytes32(uint256(value))); } /// @dev Adds `value` to the set. Returns whether `value` was not in the set. function add(Uint8Set storage set, uint8 value) internal returns (bool result) { /// @solidity memory-safe-assembly assembly { result := sload(set.slot) let mask := shl(and(0xff, value), 1) sstore(set.slot, or(result, mask)) result := iszero(and(result, mask)) } } /// @dev Adds `value` to the set. Returns whether `value` was not in the set. /// Reverts if the set grows bigger than the custom on-the-fly capacity `cap`. function add(AddressSet storage set, address value, uint256 cap) internal returns (bool result) { if (result = add(set, value)) if (length(set) > cap) revert ExceedsCapacity(); } /// @dev Adds `value` to the set. Returns whether `value` was not in the set. /// Reverts if the set grows bigger than the custom on-the-fly capacity `cap`. function add(Bytes32Set storage set, bytes32 value, uint256 cap) internal returns (bool result) { if (result = add(set, value)) if (length(set) > cap) revert ExceedsCapacity(); } /// @dev Adds `value` to the set. Returns whether `value` was not in the set. /// Reverts if the set grows bigger than the custom on-the-fly capacity `cap`. function add(Uint256Set storage set, uint256 value, uint256 cap) internal returns (bool result) { if (result = add(set, value)) if (length(set) > cap) revert ExceedsCapacity(); } /// @dev Adds `value` to the set. Returns whether `value` was not in the set. /// Reverts if the set grows bigger than the custom on-the-fly capacity `cap`. function add(Int256Set storage set, int256 value, uint256 cap) internal returns (bool result) { if (result = add(set, value)) if (length(set) > cap) revert ExceedsCapacity(); } /// @dev Adds `value` to the set. Returns whether `value` was not in the set. /// Reverts if the set grows bigger than the custom on-the-fly capacity `cap`. function add(Uint8Set storage set, uint8 value, uint256 cap) internal returns (bool result) { if (result = add(set, value)) if (length(set) > cap) revert ExceedsCapacity(); } /// @dev Removes `value` from the set. Returns whether `value` was in the set. function remove(AddressSet storage set, address value) internal returns (bool result) { bytes32 rootSlot = _rootSlot(set); /// @solidity memory-safe-assembly assembly { value := shr(96, shl(96, value)) if eq(value, _ZERO_SENTINEL) { mstore(0x00, 0xf5a267f1) // `ValueIsZeroSentinel()`. revert(0x1c, 0x04) } if iszero(value) { value := _ZERO_SENTINEL } let rootPacked := sload(rootSlot) for { let n := shr(160, shl(160, rootPacked)) } 1 {} { if iszero(n) { result := 1 if eq(shr(96, rootPacked), value) { sstore(rootSlot, sload(add(rootSlot, 1))) sstore(add(rootSlot, 1), sload(add(rootSlot, 2))) sstore(add(rootSlot, 2), 0) break } if eq(shr(96, sload(add(rootSlot, 1))), value) { sstore(add(rootSlot, 1), sload(add(rootSlot, 2))) sstore(add(rootSlot, 2), 0) break } if eq(shr(96, sload(add(rootSlot, 2))), value) { sstore(add(rootSlot, 2), 0) break } result := 0 break } mstore(0x20, rootSlot) mstore(0x00, value) let p := keccak256(0x00, 0x40) let position := sload(p) if iszero(position) { break } n := sub(shr(1, n), 1) if iszero(eq(sub(position, 1), n)) { let lastValue := shr(96, sload(add(rootSlot, n))) sstore(add(rootSlot, sub(position, 1)), shl(96, lastValue)) mstore(0x00, lastValue) sstore(keccak256(0x00, 0x40), position) } sstore(rootSlot, or(shl(96, shr(96, sload(rootSlot))), or(shl(1, n), 1))) sstore(p, 0) result := 1 break } } } /// @dev Removes `value` from the set. Returns whether `value` was in the set. function remove(Bytes32Set storage set, bytes32 value) internal returns (bool result) { bytes32 rootSlot = _rootSlot(set); /// @solidity memory-safe-assembly assembly { if eq(value, _ZERO_SENTINEL) { mstore(0x00, 0xf5a267f1) // `ValueIsZeroSentinel()`. revert(0x1c, 0x04) } if iszero(value) { value := _ZERO_SENTINEL } for { let n := sload(not(rootSlot)) } 1 {} { if iszero(n) { result := 1 if eq(sload(rootSlot), value) { sstore(rootSlot, sload(add(rootSlot, 1))) sstore(add(rootSlot, 1), sload(add(rootSlot, 2))) sstore(add(rootSlot, 2), 0) break } if eq(sload(add(rootSlot, 1)), value) { sstore(add(rootSlot, 1), sload(add(rootSlot, 2))) sstore(add(rootSlot, 2), 0) break } if eq(sload(add(rootSlot, 2)), value) { sstore(add(rootSlot, 2), 0) break } result := 0 break } mstore(0x20, rootSlot) mstore(0x00, value) let p := keccak256(0x00, 0x40) let position := sload(p) if iszero(position) { break } n := sub(shr(1, n), 1) if iszero(eq(sub(position, 1), n)) { let lastValue := sload(add(rootSlot, n)) sstore(add(rootSlot, sub(position, 1)), lastValue) mstore(0x00, lastValue) sstore(keccak256(0x00, 0x40), position) } sstore(not(rootSlot), or(shl(1, n), 1)) sstore(p, 0) result := 1 break } } } /// @dev Removes `value` from the set. Returns whether `value` was in the set. function remove(Uint256Set storage set, uint256 value) internal returns (bool result) { result = remove(_toBytes32Set(set), bytes32(value)); } /// @dev Removes `value` from the set. Returns whether `value` was in the set. function remove(Int256Set storage set, int256 value) internal returns (bool result) { result = remove(_toBytes32Set(set), bytes32(uint256(value))); } /// @dev Removes `value` from the set. Returns whether `value` was in the set. function remove(Uint8Set storage set, uint8 value) internal returns (bool result) { /// @solidity memory-safe-assembly assembly { result := sload(set.slot) let mask := shl(and(0xff, value), 1) sstore(set.slot, and(result, not(mask))) result := iszero(iszero(and(result, mask))) } } /// @dev Shorthand for `isAdd ? set.add(value, cap) : set.remove(value)`. function update(AddressSet storage set, address value, bool isAdd, uint256 cap) internal returns (bool) { return isAdd ? add(set, value, cap) : remove(set, value); } /// @dev Shorthand for `isAdd ? set.add(value, cap) : set.remove(value)`. function update(Bytes32Set storage set, bytes32 value, bool isAdd, uint256 cap) internal returns (bool) { return isAdd ? add(set, value, cap) : remove(set, value); } /// @dev Shorthand for `isAdd ? set.add(value, cap) : set.remove(value)`. function update(Uint256Set storage set, uint256 value, bool isAdd, uint256 cap) internal returns (bool) { return isAdd ? add(set, value, cap) : remove(set, value); } /// @dev Shorthand for `isAdd ? set.add(value, cap) : set.remove(value)`. function update(Int256Set storage set, int256 value, bool isAdd, uint256 cap) internal returns (bool) { return isAdd ? add(set, value, cap) : remove(set, value); } /// @dev Shorthand for `isAdd ? set.add(value, cap) : set.remove(value)`. function update(Uint8Set storage set, uint8 value, bool isAdd, uint256 cap) internal returns (bool) { return isAdd ? add(set, value, cap) : remove(set, value); } /// @dev Returns all of the values in the set. /// Note: This can consume more gas than the block gas limit for large sets. function values(AddressSet storage set) internal view returns (address[] memory result) { bytes32 rootSlot = _rootSlot(set); /// @solidity memory-safe-assembly assembly { let zs := _ZERO_SENTINEL let rootPacked := sload(rootSlot) let n := shr(160, shl(160, rootPacked)) result := mload(0x40) let o := add(0x20, result) let v := shr(96, rootPacked) mstore(o, mul(v, iszero(eq(v, zs)))) for {} 1 {} { if iszero(n) { if v { n := 1 v := shr(96, sload(add(rootSlot, n))) if v { n := 2 mstore(add(o, 0x20), mul(v, iszero(eq(v, zs)))) v := shr(96, sload(add(rootSlot, n))) if v { n := 3 mstore(add(o, 0x40), mul(v, iszero(eq(v, zs)))) } } } break } n := shr(1, n) for { let i := 1 } lt(i, n) { i := add(i, 1) } { v := shr(96, sload(add(rootSlot, i))) mstore(add(o, shl(5, i)), mul(v, iszero(eq(v, zs)))) } break } mstore(result, n) mstore(0x40, add(o, shl(5, n))) } } /// @dev Returns all of the values in the set. /// Note: This can consume more gas than the block gas limit for large sets. function values(Bytes32Set storage set) internal view returns (bytes32[] memory result) { bytes32 rootSlot = _rootSlot(set); /// @solidity memory-safe-assembly assembly { let zs := _ZERO_SENTINEL let n := sload(not(rootSlot)) result := mload(0x40) let o := add(0x20, result) for {} 1 {} { if iszero(n) { let v := sload(rootSlot) if v { n := 1 mstore(o, mul(v, iszero(eq(v, zs)))) v := sload(add(rootSlot, n)) if v { n := 2 mstore(add(o, 0x20), mul(v, iszero(eq(v, zs)))) v := sload(add(rootSlot, n)) if v { n := 3 mstore(add(o, 0x40), mul(v, iszero(eq(v, zs)))) } } } break } n := shr(1, n) for { let i := 0 } lt(i, n) { i := add(i, 1) } { let v := sload(add(rootSlot, i)) mstore(add(o, shl(5, i)), mul(v, iszero(eq(v, zs)))) } break } mstore(result, n) mstore(0x40, add(o, shl(5, n))) } } /// @dev Returns all of the values in the set. /// Note: This can consume more gas than the block gas limit for large sets. function values(Uint256Set storage set) internal view returns (uint256[] memory result) { result = _toUints(values(_toBytes32Set(set))); } /// @dev Returns all of the values in the set. /// Note: This can consume more gas than the block gas limit for large sets. function values(Int256Set storage set) internal view returns (int256[] memory result) { result = _toInts(values(_toBytes32Set(set))); } /// @dev Returns all of the values in the set. function values(Uint8Set storage set) internal view returns (uint8[] memory result) { /// @solidity memory-safe-assembly assembly { result := mload(0x40) let ptr := add(result, 0x20) let o := 0 for { let packed := sload(set.slot) } packed {} { if iszero(and(packed, 0xffff)) { o := add(o, 16) packed := shr(16, packed) continue } mstore(ptr, o) ptr := add(ptr, shl(5, and(packed, 1))) o := add(o, 1) packed := shr(1, packed) } mstore(result, shr(5, sub(ptr, add(result, 0x20)))) mstore(0x40, ptr) } } /// @dev Returns the element at index `i` in the set. Reverts if `i` is out-of-bounds. function at(AddressSet storage set, uint256 i) internal view returns (address result) { bytes32 rootSlot = _rootSlot(set); /// @solidity memory-safe-assembly assembly { result := shr(96, sload(add(rootSlot, i))) result := mul(result, iszero(eq(result, _ZERO_SENTINEL))) } if (i >= length(set)) revert IndexOutOfBounds(); } /// @dev Returns the element at index `i` in the set. Reverts if `i` is out-of-bounds. function at(Bytes32Set storage set, uint256 i) internal view returns (bytes32 result) { result = _rootSlot(set); /// @solidity memory-safe-assembly assembly { result := sload(add(result, i)) result := mul(result, iszero(eq(result, _ZERO_SENTINEL))) } if (i >= length(set)) revert IndexOutOfBounds(); } /// @dev Returns the element at index `i` in the set. Reverts if `i` is out-of-bounds. function at(Uint256Set storage set, uint256 i) internal view returns (uint256 result) { result = uint256(at(_toBytes32Set(set), i)); } /// @dev Returns the element at index `i` in the set. Reverts if `i` is out-of-bounds. function at(Int256Set storage set, uint256 i) internal view returns (int256 result) { result = int256(uint256(at(_toBytes32Set(set), i))); } /// @dev Returns the element at index `i` in the set. Reverts if `i` is out-of-bounds. function at(Uint8Set storage set, uint256 i) internal view returns (uint8 result) { /// @solidity memory-safe-assembly assembly { let packed := sload(set.slot) for {} 1 { mstore(0x00, 0x4e23d035) // `IndexOutOfBounds()`. revert(0x1c, 0x04) } { if iszero(lt(i, 256)) { continue } for { let j := 0 } iszero(eq(i, j)) {} { packed := xor(packed, and(packed, add(1, not(packed)))) j := add(j, 1) } if iszero(packed) { continue } break } // Find first set subroutine, optimized for smaller bytecode size. let x := and(packed, add(1, not(packed))) let r := shl(7, iszero(iszero(shr(128, x)))) r := or(r, shl(6, iszero(iszero(shr(64, shr(r, x)))))) r := or(r, shl(5, lt(0xffffffff, shr(r, x)))) // For the lower 5 bits of the result, use a De Bruijn lookup. // forgefmt: disable-next-item result := or(r, byte(and(div(0xd76453e0, shr(r, x)), 0x1f), 0x001f0d1e100c1d070f090b19131c1706010e11080a1a141802121b1503160405)) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* PRIVATE HELPERS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the root slot. function _rootSlot(AddressSet storage s) private pure returns (bytes32 r) { /// @solidity memory-safe-assembly assembly { mstore(0x04, _ENUMERABLE_ADDRESS_SET_SLOT_SEED) mstore(0x00, s.slot) r := keccak256(0x00, 0x24) } } /// @dev Returns the root slot. function _rootSlot(Bytes32Set storage s) private pure returns (bytes32 r) { /// @solidity memory-safe-assembly assembly { mstore(0x04, _ENUMERABLE_WORD_SET_SLOT_SEED) mstore(0x00, s.slot) r := keccak256(0x00, 0x24) } } /// @dev Casts to a Bytes32Set. function _toBytes32Set(Uint256Set storage s) private pure returns (Bytes32Set storage c) { /// @solidity memory-safe-assembly assembly { c.slot := s.slot } } /// @dev Casts to a Bytes32Set. function _toBytes32Set(Int256Set storage s) private pure returns (Bytes32Set storage c) { /// @solidity memory-safe-assembly assembly { c.slot := s.slot } } /// @dev Casts to a uint256 array. function _toUints(bytes32[] memory a) private pure returns (uint256[] memory c) { /// @solidity memory-safe-assembly assembly { c := a } } /// @dev Casts to a int256 array. function _toInts(bytes32[] memory a) private pure returns (int256[] memory c) { /// @solidity memory-safe-assembly assembly { c := a } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; /// @title Calldata /// @notice Library for manipulating objects in calldata library Calldata { function hash(bytes calldata data) internal pure returns (bytes32 digest) { assembly ("memory-safe") { let ptr := mload(0x40) calldatacopy(ptr, data.offset, data.length) digest := keccak256(ptr, data.length) } } function emptyBytes() internal pure returns (bytes calldata result) { assembly ("memory-safe") { result.offset := 0x00 result.length := 0x00 } } function emptyString() internal pure returns (string calldata result) { assembly ("memory-safe") { result.offset := 0x00 result.length := 0x00 } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; import {ExecutionMode, CallType, ModuleType} from "src/types/DataTypes.sol"; /// @title CalldataDecoder /// @notice Library for abi decoding in calldata. library CalldataDecoder { function decodeSelector(bytes calldata params) internal pure returns (bytes4 selector) { assembly ("memory-safe") { if lt(params.length, 0x04) { mstore(0x00, 0x7352d91c) // InvalidSelector() revert(0x1c, 0x04) } selector := calldataload(params.offset) } } function decodeExecutionCalldata( bytes calldata params ) internal pure returns (ExecutionMode mode, bytes calldata executionCalldata) { assembly ("memory-safe") { if lt(params.length, 0x20) { mstore(0x00, 0xdfe93090) // InvalidDataLength() revert(0x1c, 0x04) } mode := calldataload(params.offset) let ptr := add(params.offset, calldataload(add(params.offset, 0x20))) executionCalldata.offset := add(ptr, 0x20) executionCalldata.length := calldataload(ptr) } } function decodeInstallModuleParams( bytes calldata params ) internal pure returns (bytes calldata moduleData, address hook, bytes calldata hookData) { assembly ("memory-safe") { let ptr := params.offset moduleData.offset := add(ptr, 0x04) moduleData.length := shr(0xe0, calldataload(ptr)) ptr := add(moduleData.offset, moduleData.length) hookData.offset := add(ptr, 0x04) hookData.length := shr(0xe0, calldataload(ptr)) if iszero(lt(hookData.length, 0x14)) { hook := shr(0x60, calldataload(hookData.offset)) hookData.offset := add(hookData.offset, 0x14) hookData.length := sub(hookData.length, 0x14) } if iszero(hook) { hook := 0x01 } } } function decodeUninstallModuleParams( bytes calldata params ) internal pure returns (bytes calldata moduleData, bytes calldata hookData) { assembly ("memory-safe") { let ptr := params.offset moduleData.offset := add(ptr, 0x04) moduleData.length := shr(0xe0, calldataload(ptr)) ptr := add(moduleData.offset, moduleData.length) hookData.offset := add(ptr, 0x04) hookData.length := shr(0xe0, calldataload(ptr)) } } function decodeFallbackParams( bytes calldata params ) internal pure returns (bytes32[] calldata selectors, bytes calldata data) { assembly ("memory-safe") { let ptr := add(params.offset, calldataload(params.offset)) selectors.offset := add(ptr, 0x20) selectors.length := calldataload(ptr) ptr := add(params.offset, calldataload(add(params.offset, 0x20))) data.offset := add(ptr, 0x20) data.length := calldataload(ptr) } } function decodeInstallMultiTypeParams( bytes calldata params ) internal pure returns (ModuleType[] calldata moduleTypeIds, bytes[] calldata data) { assembly ("memory-safe") { let ptr := add(params.offset, calldataload(params.offset)) moduleTypeIds.offset := add(ptr, 0x20) moduleTypeIds.length := calldataload(ptr) ptr := add(params.offset, calldataload(add(params.offset, 0x20))) data.offset := add(ptr, 0x20) data.length := calldataload(ptr) if xor(moduleTypeIds.length, data.length) { mstore(0x00, 0x0fe4a1df) // InvalidParametersLength() revert(0x1c, 0x04) } } } function decodeEnableModuleParams( bytes calldata params ) internal pure returns ( ModuleType moduleTypeId, address module, bytes calldata initData, bytes calldata signature, bytes calldata userOpSignature ) { assembly ("memory-safe") { let ptr := params.offset moduleTypeId := shr(0xf8, calldataload(ptr)) ptr := add(ptr, 0x01) module := shr(0x60, calldataload(ptr)) ptr := add(ptr, 0x14) initData.offset := add(ptr, 0x04) initData.length := shr(0xe0, calldataload(ptr)) ptr := add(initData.offset, initData.length) signature.offset := add(ptr, 0x04) signature.length := shr(0xe0, calldataload(ptr)) ptr := sub(add(signature.offset, signature.length), params.offset) userOpSignature.offset := add(params.offset, ptr) userOpSignature.length := sub(params.length, ptr) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; import {ExecutionMode, CallType, ExecType, ModeSelector, ModePayload} from "./ExecutionMode.sol"; import {ModuleType, PackedModuleTypes} from "./ModuleType.sol"; import {ActionId, ActionPolicyId, ConfigId, Erc1271PolicyId, PermissionId, PolicyType, SmartSessionMode, UserOpPolicyId} from "./Session.sol"; import {ResolverUID, SchemaUID} from "./UID.sol"; import {ValidationData} from "./ValidationData.sol"; import {ValidationMode} from "./ValidationMode.sol";
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; /// @title AccessControl /// @notice Provides modifiers for restricting access control to the contract and its entry points abstract contract AccessControl { address internal constant ENTRYPOINT = 0x0000000071727De22E5E9d8BAf0edAc6f37da032; /// @notice Restricts access to the EntryPoint modifier onlyEntryPoint() virtual { _checkEntryPoint(); _; } /// @notice Restricts access to EntryPoint or the account itself modifier onlyEntryPointOrSelf() virtual { _checkEntryPointOrSelf(); _; } function _isEntryPointOrSelf() internal view virtual returns (bool result) { assembly ("memory-safe") { result := or(eq(caller(), ENTRYPOINT), eq(caller(), address())) } } function _checkEntryPoint() internal view virtual { assembly ("memory-safe") { if xor(caller(), ENTRYPOINT) { mstore(0x00, 0x9f03a026) // UnauthorizedCallContext() revert(0x1c, 0x04) } } } function _checkEntryPointOrSelf() internal view virtual { assembly ("memory-safe") { if and(xor(caller(), ENTRYPOINT), xor(caller(), address())) { mstore(0x00, 0x9f03a026) // UnauthorizedCallContext() revert(0x1c, 0x04) } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; import {EnumerableSetLib} from "solady/utils/EnumerableSetLib.sol"; import {ModuleType} from "src/types/DataTypes.sol"; /// @title ERC7201 /// @notice Manages isolated storage spaces for smart account in compliance with ERC-7201 standard contract ERC7201 { struct AccountStorage { address rootValidator; EnumerableSetLib.AddressSet validators; EnumerableSetLib.AddressSet executors; EnumerableSetLib.AddressSet hooks; mapping(ModuleType moduleTypeId => address hook) preValidationHooks; } /// @custom:storage-location erc7201:eip7579.vortex.storage.modules /// @dev keccak256(abi.encode(uint256(keccak256("eip7579.vortex.storage.modules")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant STORAGE_NAMESPACE = 0xffb1db744ac0caf2c7f81a63c0858e72cff909d0c940f6d0d5009607061ef100; function _getAccountStorage() internal pure virtual returns (AccountStorage storage $) { assembly ("memory-safe") { $.slot := STORAGE_NAMESPACE } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; import {ModuleType} from "src/types/ModuleType.sol"; /// @title RegistryAdapter /// @notice Provides an interface for interacting with an ERC-7484 compliant registry abstract contract RegistryAdapter { /// @notice Emitted when a new ERC-7484 registry is successfully configured event RegistryConfigured(address indexed registry); /// @dev keccak256("RegistryConfigured(address)") bytes32 private constant REGISTRY_CONFIGURED_TOPIC = 0x7d1c97842846d37d5ecd1884bd61723b85333bfbc4e3daa46882adaf1876afd2; /// @dev keccak256(abi.encode(uint256(keccak256("eip7579.vortex.storage.registry")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant REGISTRY_STORAGE_SLOT = 0x1a72bca8c19a5ea6f4c84f32c9ea9486de8a7c32689a31ace7fab938dfd59100; /// @notice Restricts execution to modules that satisfy the attestation requirements from the configured ERC-7484 registry modifier withRegistry(address module, ModuleType moduleTypeId) { _checkRegistry(module, moduleTypeId); _; } function _getRegistry() internal view virtual returns (address registry) { assembly ("memory-safe") { registry := sload(REGISTRY_STORAGE_SLOT) } } function _configureRegistry(address registry, address[] calldata attesters, uint8 threshold) internal virtual { assembly ("memory-safe") { registry := shr(0x60, shl(0x60, registry)) sstore(REGISTRY_STORAGE_SLOT, registry) log2(codesize(), 0x00, REGISTRY_CONFIGURED_TOPIC, registry) if iszero(iszero(registry)) { let ptr := mload(0x40) mstore(ptr, 0xf05c04e100000000000000000000000000000000000000000000000000000000) // trustAttesters(uint8,address[]) mstore(add(ptr, 0x04), threshold) mstore(add(ptr, 0x24), 0x40) mstore(add(ptr, 0x44), attesters.length) calldatacopy(add(ptr, 0x64), attesters.offset, shl(0x05, attesters.length)) if iszero(call(gas(), registry, 0x00, ptr, add(shl(0x05, attesters.length), 0x64), codesize(), 0x00)) { returndatacopy(ptr, 0x00, returndatasize()) revert(ptr, returndatasize()) } } } } function _checkRegistry(address module, ModuleType moduleTypeId) internal view virtual { assembly ("memory-safe") { let registry := sload(REGISTRY_STORAGE_SLOT) if iszero(iszero(registry)) { let ptr := mload(0x40) mstore(ptr, 0x96fb721700000000000000000000000000000000000000000000000000000000) // check(address,uint256) mstore(add(ptr, 0x04), shr(0x60, shl(0x60, module))) mstore(add(ptr, 0x24), moduleTypeId) if iszero(staticcall(gas(), registry, ptr, 0x44, codesize(), 0x00)) { returndatacopy(ptr, 0x00, returndatasize()) revert(ptr, returndatasize()) } } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; type ExecutionMode is bytes32; type CallType is bytes1; type ExecType is bytes1; type ModeSelector is bytes4; type ModePayload is bytes22; using ExecutionModeLib for ExecutionMode global; using {eqCallType as ==, neqCallType as !=} for CallType global; using {eqExecType as ==, neqExecType as !=} for ExecType global; using {eqModeSelector as ==, neqModeSelector as !=} for ModeSelector global; using {eqModePayload as ==, neqModePayload as !=} for ModePayload global; function eqCallType(CallType x, CallType y) pure returns (bool z) { assembly ("memory-safe") { z := eq(x, y) } } function neqCallType(CallType x, CallType y) pure returns (bool z) { assembly ("memory-safe") { z := xor(x, y) } } function eqExecType(ExecType x, ExecType y) pure returns (bool z) { assembly ("memory-safe") { z := eq(x, y) } } function neqExecType(ExecType x, ExecType y) pure returns (bool z) { assembly ("memory-safe") { z := xor(x, y) } } function eqModeSelector(ModeSelector x, ModeSelector y) pure returns (bool z) { assembly ("memory-safe") { z := eq(x, y) } } function neqModeSelector(ModeSelector x, ModeSelector y) pure returns (bool z) { assembly ("memory-safe") { z := xor(x, y) } } function eqModePayload(ModePayload x, ModePayload y) pure returns (bool z) { assembly ("memory-safe") { z := eq(x, y) } } function neqModePayload(ModePayload x, ModePayload y) pure returns (bool z) { assembly ("memory-safe") { z := xor(x, y) } } /// @title ExecutionModeLib /// @notice Provides functions to encode and decode execution mode library ExecutionModeLib { error UnsupportedCallType(CallType callType); error UnsupportedExecType(ExecType execType); CallType internal constant CALLTYPE_SINGLE = CallType.wrap(0x00); CallType internal constant CALLTYPE_BATCH = CallType.wrap(0x01); CallType internal constant CALLTYPE_STATIC = CallType.wrap(0xFE); CallType internal constant CALLTYPE_DELEGATE = CallType.wrap(0xFF); ExecType internal constant EXECTYPE_DEFAULT = ExecType.wrap(0x00); ExecType internal constant EXECTYPE_TRY = ExecType.wrap(0x01); ModeSelector internal constant MODE_SELECTOR_DEFAULT = ModeSelector.wrap(bytes4(0x00000000)); ModePayload internal constant MODE_PAYLOAD_DEFAULT = ModePayload.wrap(bytes22(0)); function encode( CallType callType, ExecType execType, ModeSelector selector, ModePayload payload ) internal pure returns (ExecutionMode mode) { assembly ("memory-safe") { mode := or(shl(0x08, byte(0x00, callType)), byte(0x00, execType)) mode := or(shr(0xe0, selector), shl(0x40, mode)) mode := or(shr(0x50, payload), shl(0xb0, mode)) } } function decode( ExecutionMode mode ) internal pure returns (CallType callType, ExecType execType, ModeSelector selector, ModePayload payload) { assembly ("memory-safe") { callType := shl(0xf8, shr(0xf8, mode)) execType := shl(0xf8, shr(0xf8, shl(0x08, mode))) selector := shl(0xe0, shr(0xe0, shl(0x30, mode))) payload := shl(0x50, mode) } } function parseTypes(ExecutionMode mode) internal pure returns (CallType callType, ExecType execType) { assembly ("memory-safe") { callType := shl(0xf8, shr(0xf8, mode)) execType := shl(0xf8, shr(0xf8, shl(0x08, mode))) // CALLTYPE_SINGLE: 0x00 | CALLTYPE_BATCH: 0x01 | CALLTYPE_DELEGATE: 0xFF if iszero(or(iszero(callType), or(eq(callType, shl(0xf8, 0x01)), eq(callType, shl(0xf8, 0xFF))))) { mstore(0x00, 0xb96fcfe4) // UnsupportedCallType(bytes1) mstore(0x20, callType) revert(0x1c, 0x24) } // EXECTYPE_DEFAULT: 0x00 | EXECTYPE_TRY: 0x01 if iszero(or(iszero(execType), eq(execType, shl(0xf8, 0x01)))) { mstore(0x00, 0x1187dc06) // UnsupportedExecType(bytes1) mstore(0x20, execType) revert(0x1c, 0x24) } } } function getCallType(ExecutionMode mode) internal pure returns (CallType callType) { assembly ("memory-safe") { callType := mode } } function getExecType(ExecutionMode mode) internal pure returns (ExecType execType) { assembly ("memory-safe") { execType := shl(0x08, mode) } } function getSelector(ExecutionMode mode) internal pure returns (ModeSelector selector) { assembly ("memory-safe") { selector := shl(0x30, mode) } } function getPayload(ExecutionMode mode) internal pure returns (ModePayload payload) { assembly ("memory-safe") { payload := shl(0x50, mode) } } function encodeSingle() internal pure returns (ExecutionMode mode) { return encodeCustom(CALLTYPE_SINGLE, EXECTYPE_DEFAULT); } function encodeTrySingle() internal pure returns (ExecutionMode mode) { return encodeCustom(CALLTYPE_SINGLE, EXECTYPE_TRY); } function encodeBatch() internal pure returns (ExecutionMode mode) { return encodeCustom(CALLTYPE_BATCH, EXECTYPE_DEFAULT); } function encodeTryBatch() internal pure returns (ExecutionMode mode) { return encodeCustom(CALLTYPE_BATCH, EXECTYPE_TRY); } function encodeDelegate() internal pure returns (ExecutionMode mode) { return encodeCustom(CALLTYPE_DELEGATE, EXECTYPE_DEFAULT); } function encodeTryDelegate() internal pure returns (ExecutionMode mode) { return encodeCustom(CALLTYPE_DELEGATE, EXECTYPE_TRY); } function encodeCustom(CallType callType, ExecType execType) internal pure returns (ExecutionMode mode) { return encode(callType, execType, MODE_SELECTOR_DEFAULT, MODE_PAYLOAD_DEFAULT); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; type ModuleType is uint256; type PackedModuleTypes is uint32; using ModuleTypeLib for ModuleType global; using ModuleTypeLib for PackedModuleTypes global; using { eqModuleType as ==, neqModuleType as != } for ModuleType global; using { eqPackedModuleTypes as ==, neqPackedModuleTypes as != } for PackedModuleTypes global; function eqModuleType(ModuleType x, ModuleType y) pure returns (bool z) { assembly ("memory-safe") { z := eq(x, y) } } function neqModuleType(ModuleType x, ModuleType y) pure returns (bool z) { assembly ("memory-safe") { z := xor(x, y) } } function eqPackedModuleTypes(PackedModuleTypes x, PackedModuleTypes y) pure returns (bool z) { assembly ("memory-safe") { z := eq(x, y) } } function neqPackedModuleTypes(PackedModuleTypes x, PackedModuleTypes y) pure returns (bool z) { assembly ("memory-safe") { z := xor(x, y) } } /// @title ModuleTypeLib /// @notice Provides functions for handling module type and packed module types library ModuleTypeLib { error InvalidModuleType(); function isType(PackedModuleTypes packedTypes, ModuleType moduleType) internal pure returns (bool result) { assembly ("memory-safe") { result := and(packedTypes, shl(moduleType, 0x01)) } } function numberOfTypes(PackedModuleTypes packedTypes) internal pure returns (uint256 count) { assembly ("memory-safe") { for { let moduleType } lt(moduleType, 0x20) { moduleType := add(moduleType, 0x01) } { if and(packedTypes, shl(moduleType, 0x01)) { count := add(count, 0x01) } } } } function decode(PackedModuleTypes packedTypes) internal pure returns (ModuleType[] memory moduleTypes) { assembly ("memory-safe") { moduleTypes := mload(0x40) let offset := add(moduleTypes, 0x20) let length for { let moduleType } lt(moduleType, 0x20) { moduleType := add(moduleType, 0x01) } { if and(packedTypes, shl(moduleType, 0x01)) { mstore(add(offset, shl(0x05, length)), moduleType) length := add(length, 0x01) } } mstore(moduleTypes, length) mstore(0x40, add(moduleTypes, shl(0x05, add(length, 0x01)))) } } function encode(ModuleType[] memory moduleTypes) internal pure returns (PackedModuleTypes packedTypes) { assembly ("memory-safe") { let offset := add(moduleTypes, 0x20) let guard := add(offset, shl(0x05, mload(moduleTypes))) for { } 0x01 { } { let moduleType := mload(offset) if or(gt(moduleType, 0x1f), and(packedTypes, shl(moduleType, 0x01))) { mstore(0x00, 0x2125deae) // InvalidModuleType() revert(0x1c, 0x04) } packedTypes := or(packedTypes, shl(moduleType, 0x01)) offset := add(offset, 0x20) if iszero(lt(offset, guard)) { break } } } } function arrayify(ModuleType moduleTypeId) internal pure returns (ModuleType[] memory moduleTypeIds) { moduleTypeIds = new ModuleType[](1); moduleTypeIds[0] = moduleTypeId; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; type PermissionId is bytes32; type ActionId is bytes32; type ActionPolicyId is bytes32; type UserOpPolicyId is bytes32; type Erc1271PolicyId is bytes32; type ConfigId is bytes32; enum SmartSessionMode { USE, ENABLE, UNSAFE_ENABLE } enum PolicyType { NA, USER_OP, ACTION, ERC1271 } using SessionLib for SmartSessionMode global; using SessionLib for PermissionId global; using SessionLib for ActionPolicyId global; using SessionLib for Erc1271PolicyId global; using SessionLib for UserOpPolicyId global; using {eqPermissionId as ==, neqPermissionId as !=} for PermissionId global; using {eqActionId as ==, neqActionId as !=} for ActionId global; using {eqActionPolicyId as ==, neqActionPolicyId as !=} for ActionPolicyId global; using {eqUserOpPolicyId as ==, neqUserOpPolicyId as !=} for UserOpPolicyId global; using {eqErc1271PolicyId as ==, neqErc1271PolicyId as !=} for Erc1271PolicyId global; using {eqConfigId as ==, neqConfigId as !=} for ConfigId global; function eqPermissionId(PermissionId x, PermissionId y) pure returns (bool z) { assembly ("memory-safe") { z := eq(x, y) } } function neqPermissionId(PermissionId x, PermissionId y) pure returns (bool z) { assembly ("memory-safe") { z := xor(x, y) } } function eqActionId(ActionId x, ActionId y) pure returns (bool z) { assembly ("memory-safe") { z := eq(x, y) } } function neqActionId(ActionId x, ActionId y) pure returns (bool z) { assembly ("memory-safe") { z := xor(x, y) } } function eqActionPolicyId(ActionPolicyId x, ActionPolicyId y) pure returns (bool z) { assembly ("memory-safe") { z := eq(x, y) } } function neqActionPolicyId(ActionPolicyId x, ActionPolicyId y) pure returns (bool z) { assembly ("memory-safe") { z := xor(x, y) } } function eqUserOpPolicyId(UserOpPolicyId x, UserOpPolicyId y) pure returns (bool z) { assembly ("memory-safe") { z := eq(x, y) } } function neqUserOpPolicyId(UserOpPolicyId x, UserOpPolicyId y) pure returns (bool z) { assembly ("memory-safe") { z := xor(x, y) } } function eqErc1271PolicyId(Erc1271PolicyId x, Erc1271PolicyId y) pure returns (bool z) { assembly ("memory-safe") { z := eq(x, y) } } function neqErc1271PolicyId(Erc1271PolicyId x, Erc1271PolicyId y) pure returns (bool z) { assembly ("memory-safe") { z := xor(x, y) } } function eqConfigId(ConfigId x, ConfigId y) pure returns (bool z) { assembly ("memory-safe") { z := eq(x, y) } } function neqConfigId(ConfigId x, ConfigId y) pure returns (bool z) { assembly ("memory-safe") { z := xor(x, y) } } /// @title SessionLib /// @notice Provides utility functions for SmartSession module library SessionLib { bytes4 internal constant VALUE_SELECTOR = 0xFFFFFFFF; function isUseMode(SmartSessionMode mode) internal pure returns (bool) { return mode == SmartSessionMode.USE; } function isEnableMode(SmartSessionMode mode) internal pure returns (bool) { return mode == SmartSessionMode.ENABLE || mode == SmartSessionMode.UNSAFE_ENABLE; } function useRegistry(SmartSessionMode mode) internal pure returns (bool) { return mode == SmartSessionMode.ENABLE; } function unpackMode( bytes calldata packed ) internal pure returns (SmartSessionMode mode, PermissionId permissionId, bytes calldata data) { mode = SmartSessionMode(uint8(bytes1(packed[:1]))); if (isEnableMode(mode)) { data = packed[1:]; } else { permissionId = PermissionId.wrap(bytes32(packed[1:33])); data = packed[33:]; } } function encodeUse(PermissionId permissionId, bytes memory signature) internal pure returns (bytes memory userOpSig) { return abi.encodePacked(SmartSessionMode.USE, permissionId, signature); } function toUserOpPolicyId(PermissionId permissionId) internal pure returns (UserOpPolicyId userOpPolicyId) { return UserOpPolicyId.wrap(PermissionId.unwrap(permissionId)); } function toActionId(address target, bytes calldata callData) internal pure returns (ActionId actionId) { return toActionId(target, callData.length < 4 ? VALUE_SELECTOR : bytes4(callData[:4])); } function toActionId(address target, bytes4 selector) internal pure returns (ActionId actionId) { return ActionId.wrap(keccak256(abi.encodePacked(target, selector))); } function toActionPolicyId( PermissionId permissionId, ActionId actionId ) internal pure returns (ActionPolicyId policyId) { return ActionPolicyId.wrap(keccak256(abi.encodePacked(permissionId, actionId))); } function toErc1271PolicyId(PermissionId permissionId) internal pure returns (Erc1271PolicyId erc1271PolicyId) { return Erc1271PolicyId.wrap(keccak256(abi.encodePacked("ERC1271: ", permissionId))); } function toConfigId(UserOpPolicyId userOpPolicyId, address account) internal pure returns (ConfigId configId) { return ConfigId.wrap(keccak256(abi.encodePacked(account, userOpPolicyId))); } function toConfigId(ActionPolicyId actionPolicyId, address account) internal pure returns (ConfigId configId) { return ConfigId.wrap(keccak256(abi.encodePacked(account, actionPolicyId))); } function toConfigId( PermissionId permissionId, ActionId actionId, address account ) internal pure returns (ConfigId configId) { return toConfigId(toActionPolicyId(permissionId, actionId), account); } function toConfigId(Erc1271PolicyId erc1271PolicyId, address account) internal pure returns (ConfigId configId) { return ConfigId.wrap(keccak256(abi.encodePacked(account, erc1271PolicyId))); } function toConfigId(UserOpPolicyId userOpPolicyId) internal view returns (ConfigId configId) { return toConfigId(userOpPolicyId, msg.sender); } function toConfigId(PermissionId permissionId, ActionId actionId) internal view returns (ConfigId configId) { return toConfigId(toActionPolicyId(permissionId, actionId), msg.sender); } function toConfigId(Erc1271PolicyId erc1271PolicyId) internal view returns (ConfigId configId) { return toConfigId(erc1271PolicyId, msg.sender); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; type ResolverUID is bytes32; type SchemaUID is bytes32; using {eqResolverUID as ==, neqResolverUID as !=} for ResolverUID global; using {eqSchemaUID as ==, neqSchemaUID as !=} for SchemaUID global; function eqResolverUID(ResolverUID x, ResolverUID y) pure returns (bool z) { assembly ("memory-safe") { z := eq(x, y) } } function neqResolverUID(ResolverUID x, ResolverUID y) pure returns (bool z) { assembly ("memory-safe") { z := xor(x, y) } } function eqSchemaUID(SchemaUID x, SchemaUID y) pure returns (bool z) { assembly ("memory-safe") { z := eq(x, y) } } function neqSchemaUID(SchemaUID x, SchemaUID y) pure returns (bool z) { assembly ("memory-safe") { z := xor(x, y) } } /// @title UIDLib /// @notice Provides functions to encode UID types library UIDLib { function getResolverUID(address sender, address resolver) internal pure returns (ResolverUID) { return ResolverUID.wrap(keccak256(abi.encodePacked(sender, resolver))); } function getSchemaUID(address sender, address validator, string memory schema) internal pure returns (SchemaUID) { return SchemaUID.wrap(keccak256(abi.encodePacked(sender, schema, address(validator)))); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; type ValidationData is uint256; using ValidationDataLib for ValidationData global; using {eqValidationData as ==, neqValidationData as !=} for ValidationData global; function eqValidationData(ValidationData x, ValidationData y) pure returns (bool z) { assembly ("memory-safe") { z := eq(x, y) } } function neqValidationData(ValidationData x, ValidationData y) pure returns (bool z) { assembly ("memory-safe") { z := xor(x, y) } } /// @title ValidationDataLib /// @notice Provides functions for encoding and decoding validations library ValidationDataLib { uint48 internal constant MAX_UINT48 = (1 << 48) - 1; function encode( bool flag, uint48 validUntil, uint48 validAfter ) internal pure returns (ValidationData validationData) { assembly ("memory-safe") { validationData := or(add(shl(208, validAfter), shl(160, validUntil)), and(iszero(iszero(flag)), 0xff)) } } function decode( ValidationData validationData ) internal pure returns (bool failed, uint48 validUntil, uint48 validAfter) { assembly ("memory-safe") { failed := and(validationData, 0x01) validUntil := and(shr(160, validationData), MAX_UINT48) validAfter := and(shr(208, validationData), MAX_UINT48) } } function isFailed(ValidationData validationData) internal pure returns (bool flag) { assembly ("memory-safe") { flag := and(validationData, 0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff) } } function intersect(ValidationData a, ValidationData b) internal pure returns (ValidationData validationData) { assembly ("memory-safe") { let sum := shl(0x60, add(a, b)) switch or( iszero(and(xor(a, b), 0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff)), or(eq(sum, shl(0x60, a)), eq(sum, shl(0x60, b))) ) case 0x01 { validationData := and(or(a, b), 0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff) // validAfter let a_vd := and(0xffffffffffff0000000000000000000000000000000000000000000000000000, a) let b_vd := and(0xffffffffffff0000000000000000000000000000000000000000000000000000, b) validationData := or(validationData, xor(a_vd, mul(xor(a_vd, b_vd), gt(b_vd, a_vd)))) // validUntil a_vd := and(0x000000000000ffffffffffff0000000000000000000000000000000000000000, a) if iszero(a_vd) { a_vd := 0x000000000000ffffffffffff0000000000000000000000000000000000000000 } b_vd := and(0x000000000000ffffffffffff0000000000000000000000000000000000000000, b) if iszero(b_vd) { b_vd := 0x000000000000ffffffffffff0000000000000000000000000000000000000000 } let until := xor(a_vd, mul(xor(a_vd, b_vd), lt(b_vd, a_vd))) if iszero(until) { until := 0x000000000000ffffffffffff0000000000000000000000000000000000000000 } validationData := or(validationData, until) } default { validationData := 0x01 } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; type ValidationMode is bytes1; using ValidationLib for ValidationMode global; using {eqValidationMode as ==, neqValidationMode as !=} for ValidationMode global; function eqValidationMode(ValidationMode x, ValidationMode y) pure returns (bool z) { assembly ("memory-safe") { z := eq(x, y) } } function neqValidationMode(ValidationMode x, ValidationMode y) pure returns (bool z) { assembly ("memory-safe") { z := xor(x, y) } } /// @title ValidationLib library ValidationLib { // [1 bytes validation mode][3 bytes unused][20 bytes validator][8 bytes nonce] function encodeNonceKey(ValidationMode mode, address validator) internal pure returns (uint192 key) { assembly ("memory-safe") { key := or(shr(0x40, mode), validator) } } }
{ "remappings": [ "ds-test/=lib/forge-std/lib/ds-test/src/", "forge-std/=lib/forge-std/src/", "@openzeppelin/=lib/openzeppelin-contracts/contracts/", "account-abstraction/=lib/account-abstraction/contracts/", "erc4337-validation/=lib/erc4337-validation/src/", "solady/=lib/solady/src/", "solarray/=lib/solarray/src/", "string-utils/=lib/solidity-stringutils/src/", "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", "halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "solidity-stringutils/=lib/solidity-stringutils/" ], "optimizer": { "enabled": true, "runs": 999 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "none", "appendCBOR": false }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "cancun", "viaIR": true, "libraries": {} }
Contract ABI
API[{"inputs":[],"name":"InvalidRootValidator","type":"error"},{"inputs":[{"internalType":"ModuleType","name":"moduleTypeId","type":"uint256"},{"internalType":"address","name":"module","type":"address"}],"name":"ModuleAlreadyInstalled","type":"error"},{"inputs":[{"internalType":"ModuleType","name":"moduleTypeId","type":"uint256"},{"internalType":"address","name":"module","type":"address"}],"name":"ModuleNotInstalled","type":"error"},{"inputs":[],"name":"RootValidatorCannotBeRemoved","type":"error"},{"inputs":[{"internalType":"ModuleType","name":"moduleTypeId","type":"uint256"}],"name":"UnsupportedPreValidationHookType","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"registry","type":"address"}],"name":"RegistryConfigured","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"rootValidator","type":"address"}],"name":"RootValidatorConfigured","type":"event"},{"inputs":[{"components":[{"internalType":"address","name":"module","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct BootstrapConfig","name":"rootValidator","type":"tuple"},{"components":[{"internalType":"address","name":"module","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct BootstrapConfig[]","name":"validators","type":"tuple[]"},{"components":[{"internalType":"address","name":"module","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct BootstrapConfig[]","name":"executors","type":"tuple[]"},{"components":[{"internalType":"address","name":"module","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct BootstrapConfig[]","name":"fallbacks","type":"tuple[]"},{"components":[{"internalType":"address","name":"module","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct BootstrapConfig[]","name":"hooks","type":"tuple[]"},{"components":[{"internalType":"address","name":"module","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct BootstrapConfig","name":"preValidationHook1271","type":"tuple"},{"components":[{"internalType":"address","name":"module","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct BootstrapConfig","name":"preValidationHook4337","type":"tuple"},{"internalType":"address","name":"registry","type":"address"},{"internalType":"address[]","name":"attesters","type":"address[]"},{"internalType":"uint8","name":"threshold","type":"uint8"}],"name":"getInitializeCalldata","outputs":[{"internalType":"bytes","name":"callData","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"module","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct BootstrapConfig","name":"rootValidator","type":"tuple"},{"components":[{"internalType":"address","name":"module","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct BootstrapConfig[]","name":"validators","type":"tuple[]"},{"components":[{"internalType":"address","name":"module","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct BootstrapConfig[]","name":"executors","type":"tuple[]"},{"components":[{"internalType":"address","name":"module","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct BootstrapConfig[]","name":"fallbacks","type":"tuple[]"},{"components":[{"internalType":"address","name":"module","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct BootstrapConfig[]","name":"hooks","type":"tuple[]"},{"internalType":"address","name":"registry","type":"address"},{"internalType":"address[]","name":"attesters","type":"address[]"},{"internalType":"uint8","name":"threshold","type":"uint8"}],"name":"getInitializeScopedCalldata","outputs":[{"internalType":"bytes","name":"callData","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"module","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct BootstrapConfig","name":"rootValidator","type":"tuple"},{"internalType":"address","name":"registry","type":"address"},{"internalType":"address[]","name":"attesters","type":"address[]"},{"internalType":"uint8","name":"threshold","type":"uint8"}],"name":"getInitializeWithRootValidatorCalldata","outputs":[{"internalType":"bytes","name":"callData","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"module","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct BootstrapConfig","name":"rootValidator","type":"tuple"},{"components":[{"internalType":"address","name":"module","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct BootstrapConfig[]","name":"validators","type":"tuple[]"},{"components":[{"internalType":"address","name":"module","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct BootstrapConfig[]","name":"executors","type":"tuple[]"},{"components":[{"internalType":"address","name":"module","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct BootstrapConfig[]","name":"fallbacks","type":"tuple[]"},{"components":[{"internalType":"address","name":"module","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct BootstrapConfig[]","name":"hooks","type":"tuple[]"},{"components":[{"internalType":"address","name":"module","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct BootstrapConfig","name":"preValidationHook1271","type":"tuple"},{"components":[{"internalType":"address","name":"module","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct BootstrapConfig","name":"preValidationHook4337","type":"tuple"},{"internalType":"address","name":"registry","type":"address"},{"internalType":"address[]","name":"attesters","type":"address[]"},{"internalType":"uint8","name":"threshold","type":"uint8"}],"name":"initialize","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"module","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct BootstrapConfig","name":"rootValidator","type":"tuple"},{"components":[{"internalType":"address","name":"module","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct BootstrapConfig[]","name":"validators","type":"tuple[]"},{"components":[{"internalType":"address","name":"module","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct BootstrapConfig[]","name":"executors","type":"tuple[]"},{"components":[{"internalType":"address","name":"module","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct BootstrapConfig[]","name":"fallbacks","type":"tuple[]"},{"components":[{"internalType":"address","name":"module","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct BootstrapConfig[]","name":"hooks","type":"tuple[]"},{"internalType":"address","name":"registry","type":"address"},{"internalType":"address[]","name":"attesters","type":"address[]"},{"internalType":"uint8","name":"threshold","type":"uint8"}],"name":"initializeScoped","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"module","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct BootstrapConfig","name":"rootValidator","type":"tuple"},{"internalType":"address","name":"registry","type":"address"},{"internalType":"address[]","name":"attesters","type":"address[]"},{"internalType":"uint8","name":"threshold","type":"uint8"}],"name":"initializeWithRootValidator","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"}]
Deployed Bytecode
0x60806040526004361015610011575f80fd5b5f3560e01c806306fdde03146120a55780630b28b4d714611fac5780632a0d646114611e48578063477aac2514611e0c5780634f2690a214610e0657806354fd4d5014610da7578063763d206a14610cd45763fb37613614610071575f80fd5b6100c061007d36612169565b916001600160a01b03849e969e9d959d9c989c9b979b16610cc2575b505050506100ba6100af829b9a9b9998996125a5565b9160208101906125b9565b916126c8565b5f5b818110610ae8575050505f5b818110610790575050505f915b80831061047b575050505f915b8083106100f157005b6101046100ff8483856125ec565b6125a5565b9261011d6101138284866125ec565b60208101906125b9565b50935f516020612c525f395f51905f525480610443575b508060601b156104365760405163ecd0596160e01b815260048082015260205f602483855afa1561042e57505f5115610421575f90853560e01c90818701916008830191600484013560e01c936014851015610408575b5084156103ff575b5f63978aab926004527fffb1db744ac0caf2c7f81a63c0858e72cff909d0c940f6d0d5009607061ef1035f5260245f20906001600160a01b038316809268fbb67fda52d4bfb8bf82146103f25781156103e1575b80546bffffffffffffffffffffffff811692826020528315610322575b805f5260405f20938454156102e95750505050505b156102d357509060019697986001600160a01b0388931691825f525f516020612c725f395f51905f526020526001600160a01b038716928360405f20555f516020612c325f395f51905f526040805160048152836020820152a161027c81612a2a565b156102be575b5050501415806102ae575b61029d575b5050500191906100e8565b6102a692612a6a565b5f8080610292565b506102b883612a2a565b1561028d565b60046102cb930190612a6a565b5f8080610282565b630b961e3560e11b5f526004805260245260445ffd5b90919293945060011c90600194828601905581156103125760601b908301556002019055610219565b91505060601b6003179055610219565b92508060601c9081156103d1578382146103c85760018301805460601c9081156103b657508481146103ac576002840190815460601c918215610399575085821461038e576007935f52600160405f20555f52600260405f20555f52600360405f205517600792610204565b505050505050610219565b9650505050505060601b90556001610219565b5050505050610219565b95505050505060601b90556001610219565b50505050610219565b5050915060601b90556001610219565b68fbb67fda52d4bfb8bf91506101e7565b63f5a267f15f526004601cfd5b60019450610193565b94509291601c903560601c94019160131901925f61018b565b632125deae5f526004601cfd5b3d5f823e3d90fd5b63dd914b285f526004601cfd5b5f604051916396fb721760e01b83526001600160a01b03841660048401526004602484015260448338925afa610134573d5f823e3d90fd5b61048c6100ff8483859896986125ec565b9461049b6101138284866125ec565b5f516020612c525f395f51905f525480610758575b50508660601b156104365760405163ecd0596160e01b81526003600482015260205f6024838b5afa1561042e57505f5115610421575f906004810190803560e01c90818101926008840192600485013560e01c94601486101561073f575b508515610736575b503581019960048b013591602481013501916004602484019301359b7f6aa9b80a3ef8fd7c61052fd742393c4cad924e6f735976eb39535648c67cd2006020525f5b82811061061757505050906001969798999a6001600160a01b0388931690815f525f516020612c725f395f51905f526020526001600160a01b038716928360405f20555f516020612c325f395f51905f526040805160038152856020820152a16105c183612a2a565b15610606575b5050501415806105f6575b6105e5575b5095969550500191906100db565b6105ee92612a6a565b5f80806105d7565b5061060083612a2a565b156105d2565b61060f92612a6a565b5f80806105c7565b602060048260051b840101013560ff8160d81c168160e01c9060ff811460fe8214179015171561070057638a91b0e38114636d61fe708214179015176106ce577fffffffff0000000000000000000000000000000000000000000000000000000081165f5260405f209081546106b85760201b7fff000000000000000000000000000000000000000000000000000000000000001685179055600101610558565b8563172c3c6a5f5260036020526040526044601cfd5b639ff8cd945f527fffffffff00000000000000000000000000000000000000000000000000000000166020526024601cfd5b7fff000000000000000000000000000000000000000000000000000000000000008263b96fcfe45f5260201b166020526024601cfd5b60019550610516565b95509392601c903560601c95019260131901935f61050e565b5f604051916396fb721760e01b83526001600160a01b038b1660048401526003602484015260448338925afa6104b0573d5f823e3d90fd5b6107a46100ff8284869a999a9897986125ec565b6107b26101138385876125ec565b505f516020612c525f395f51905f525480610ab0575b508160601b156104365760405163ecd0596160e01b81526002600482015260205f602483865afa1561042e57505f5115610421575f91813560e01c808301926008840192600485013560e01c946014861015610a97575b508515610a8e575b5f63978aab926004527fffb1db744ac0caf2c7f81a63c0858e72cff909d0c940f6d0d5009607061ef1025f5260245f20906001600160a01b038316809268fbb67fda52d4bfb8bf82146103f2578115610a7d575b80546bffffffffffffffffffffffff8116928260205283156109be575b805f5260405f20938454156109855750505050505b1561096e57509160019695949392916001600160a01b0388931691825f525f516020612c725f395f51905f526020526001600160a01b038716928360405f20555f516020612c325f395f51905f526040805160028152836020820152a161091381612a2a565b15610959575b505050141580610949575b610938575b505050019594959392936100ce565b61094192612a6a565b5f8080610929565b5061095383612a2a565b15610924565b6004610966930190612a6a565b5f8080610919565b630b961e3560e11b5f52600260045260245260445ffd5b90919293945060011c90600194828601905581156109ae5760601b9083015560020190556108ad565b91505060601b60031790556108ad565b92508060601c908115610a6d57838214610a645760018301805460601c908115610a525750848114610a48576002840190815460601c918215610a355750858214610a2a576007935f52600160405f20555f52600260405f20555f52600360405f205517600792610898565b5050505050506108ad565b9650505050505060601b905560016108ad565b50505050506108ad565b95505050505060601b905560016108ad565b505050506108ad565b5050915060601b905560016108ad565b68fbb67fda52d4bfb8bf915061087b565b60019550610827565b95509392601c903560601c95019260131901935f61081f565b5f604051916396fb721760e01b83526001600160a01b03851660048401526002602484015260448338925afa6107c8573d5f823e3d90fd5b610afc6100ff8284869c9b9c9a999a6125ec565b610b0a6101138385876125ec565b505f516020612c525f395f51905f525480610c8a575b508160601b156104365760405163ecd0596160e01b81526001600482015260205f602483865afa1561042e57505f5115610421575f91813560e01c808301926008840192600485013560e01c946014861015610c71575b508515610c68575b610b8881612ab9565b15610c47579160019695949392916001600160a01b0388931691825f525f516020612c725f395f51905f526020526001600160a01b038716928360405f20555f516020612c325f395f51905f5260408051878152836020820152a1610bec81612a2a565b15610c32575b505050141580610c22575b610c11575b505050019796979594956100c2565b610c1a92612a6a565b5f8080610c02565b50610c2c83612a2a565b15610bfd565b6004610c3f930190612a6a565b5f8080610bf2565b6001600160a01b0390630b961e3560e11b5f5260016004521660245260445ffd5b60019550610b7f565b95509392601c903560601c95019260131901935f610b77565b5f604051916396fb721760e01b83526001600160a01b03851660048401526001602484015260448338925afa610b20573d5f823e3d90fd5b610ccb93612622565b5f808080610099565b34610da357610d9f610d7d610d8b610d40610d6d610d5860ff610cf6366123b7565b94939592916001600160a01b03604051998a987f477aac250000000000000000000000000000000000000000000000000000000060208b0152608060248b015260a48a0190612462565b93166044880152868303602319016064880152612537565b9116608483015203601f19810183528261242c565b6040519283913060208401612578565b03601f19810183528261242c565b604051918291602083526020830190612100565b0390f35b5f80fd5b34610da3575f366003190112610da357610d9f604051610dc860408261242c565b600581527f312e302e300000000000000000000000000000000000000000000000000000006020820152604051918291602083526020830190612100565b610e48610e123661226b565b91939e949d936001600160a01b03849e989e9d979d9c9a9c9b999b16611dfa575b505050506100ba6100af829d9c9b9a9d6125a5565b5f5b818110611c43575050505f5b818110611904575050505f5b81811061166b575050505f935b8085106113315750506001600160a01b03610e89826125a5565b166110e6575b506001600160a01b03610ea1826125a5565b16610ea857005b610eb46100af826125a5565b505f516020612c525f395f51905f5254806110ae575b508160601b156104365760405163ecd0596160e01b81526009600482015260205f602483865afa1561042e57505f5115610421575f91813560e01c808301926008840192600485013560e01c946014861015611095575b50851561108c575b60095f527fffb1db744ac0caf2c7f81a63c0858e72cff909d0c940f6d0d5009607061ef1046020527fb31752be194790c397c00aa3f118b86a0e310100c9594f24b6d36def7cc6b4ed546001600160a01b031661106b57906001600160a01b036001939260095f527fffb1db744ac0caf2c7f81a63c0858e72cff909d0c940f6d0d5009607061ef10460205260405f2082821673ffffffffffffffffffffffffffffffffffffffff198254161790551691825f525f516020612c725f395f51905f526020526001600160a01b038716928360405f20555f516020612c325f395f51905f526040805160098152836020820152a161102581612a2a565b15611056575b505050141580611046575b61103d575b005b61103b92612a6a565b5061105083612a2a565b15611036565b6004611063930190612a6a565b85808061102b565b6001600160a01b0390630b961e3560e11b5f5260096004521660245260445ffd5b60019550610f29565b95509392601c903560601c950192601319019386610f21565b5f604051916396fb721760e01b83526001600160a01b03851660048401526009602484015260448338925afa610eca573d5f823e3d90fd5b6110f26100af826125a5565b505f516020612c525f395f51905f5254806112f9575b508160601b156104365760405163ecd0596160e01b81526008600482015260205f602483865afa1561042e57505f5115610421575f91813560e01c808301926008840192600485013560e01c9460148610156112e0575b5085156112d7575b60085f527fffb1db744ac0caf2c7f81a63c0858e72cff909d0c940f6d0d5009607061ef1046020527f9e9daa3e9af44d1ed5923e2b8780a10b078dba2763354d25426e6eaabfcd569c546001600160a01b03166112b657906001600160a01b036001939260085f527fffb1db744ac0caf2c7f81a63c0858e72cff909d0c940f6d0d5009607061ef10460205260405f2082821673ffffffffffffffffffffffffffffffffffffffff198254161790551691825f525f516020612c725f395f51905f526020526001600160a01b038716928360405f20555f516020612c325f395f51905f526040805160088152836020820152a161126381612a2a565b156112a1575b505050141580611291575b611280575b5050610e8f565b61128992612a6a565b818080611279565b5061129b83612a2a565b15611274565b60046112ae930190612a6a565b868080611269565b6001600160a01b0390630b961e3560e11b5f5260086004521660245260445ffd5b60019550611167565b95509392601c903560601c95019260131901938761115f565b5f604051916396fb721760e01b83526001600160a01b03851660048401526008602484015260448338925afa611108573d5f823e3d90fd5b61133f6100ff8683856125ec565b9461134e6101138284866125ec565b50955f516020612c525f395f51905f525480611633575b508060601b156104365760405163ecd0596160e01b815260048082015260205f602483855afa1561042e57505f5115610421575f90873560e01c90818901916008830191600484013560e01c93601485101561161a575b508415611611575b5f63978aab926004527fffb1db744ac0caf2c7f81a63c0858e72cff909d0c940f6d0d5009607061ef1035f5260245f20906001600160a01b038316809268fbb67fda52d4bfb8bf82146103f2578115611600575b80546bffffffffffffffffffffffff811692826020528315611541575b805f5260405f20938454156115085750505050505b156102d35750906001969798999a6001600160a01b0388931691825f525f516020612c725f395f51905f526020526001600160a01b038716928360405f20555f516020612c325f395f51905f526040805160048152836020820152a16114af81612a2a565b156114f3575b5050501415806114e3575b6114d2575b5050500193929190610e6f565b6114db92612a6a565b8680806114c5565b506114ed83612a2a565b156114c0565b6004611500930190612a6a565b8b80806114b5565b90919293945060011c90600194828601905581156115315760601b90830155600201905561144a565b91505060601b600317905561144a565b92508060601c9081156115f0578382146115e75760018301805460601c9081156115d557508481146115cb576002840190815460601c9182156115b857508582146115ad576007935f52600160405f20555f52600260405f20555f52600360405f205517600792611435565b50505050505061144a565b9650505050505060601b9055600161144a565b505050505061144a565b95505050505060601b9055600161144a565b5050505061144a565b5050915060601b9055600161144a565b68fbb67fda52d4bfb8bf9150611418565b600194506113c4565b94509291601c903560601c94019160131901928b6113bc565b5f604051916396fb721760e01b83526001600160a01b03841660048401526004602484015260448338925afa611365573d5f823e3d90fd5b61167e6100ff8284869a9798999a6125ec565b61168c6101138385876125ec565b5f516020612c525f395f51905f5254806118cc575b50508160601b156104365760405163ecd0596160e01b81526003600482015260205f602483865afa1561042e57505f5115610421575f916004820191803560e01c91828201936008850193600486013560e01c9560148710156118b3575b5086156118aa575b503582019060048201359260248101350192600460248501940135927f6aa9b80a3ef8fd7c61052fd742393c4cad924e6f735976eb39535648c67cd2006020525f5b828110611809575050509160019695949392916001600160a01b0388931690815f525f516020612c725f395f51905f526020526001600160a01b038716928360405f20555f516020612c325f395f51905f526040805160038152856020820152a16117b383612a2a565b156117f8575b5050501415806117e8575b6117d7575b505050019594939295610e62565b6117e092612a6a565b8880806117c9565b506117f283612a2a565b156117c4565b61180192612a6a565b8d80806117b9565b602060048260051b840101013560ff8160d81c168160e01c9060ff811460fe8214179015171561070057638a91b0e38114636d61fe708214179015176106ce577fffffffff0000000000000000000000000000000000000000000000000000000081165f5260405f209081546106b85760201b7fff000000000000000000000000000000000000000000000000000000000000001685179055600101611749565b60019650611707565b96509493601c903560601c96019360131901948e6116ff565b5f604051916396fb721760e01b83526001600160a01b03861660048401526003602484015260448338925afa6116a1573d5f823e3d90fd5b6119176100ff8284869c999a9b9c6125ec565b6119256101138385876125ec565b505f516020612c525f395f51905f525480611c0b575b508160601b156104365760405163ecd0596160e01b81526002600482015260205f602483865afa1561042e57505f5115610421575f91813560e01c808301926008840192600485013560e01c946014861015611bf2575b508515611be9575b5f63978aab926004527fffb1db744ac0caf2c7f81a63c0858e72cff909d0c940f6d0d5009607061ef1025f5260245f20906001600160a01b038316809268fbb67fda52d4bfb8bf82146103f2578115611bd8575b80546bffffffffffffffffffffffff811692826020528315611b19575b805f5260405f2093845415611ae05750505050505b1561096e57509160019695949392916001600160a01b0388931691825f525f516020612c725f395f51905f526020526001600160a01b038716928360405f20555f516020612c325f395f51905f526040805160028152836020820152a1611a8681612a2a565b15611acb575b505050141580611abb575b611aaa575b505050019796959497610e56565b611ab392612a6a565b8a8080611a9c565b50611ac583612a2a565b15611a97565b6004611ad8930190612a6a565b8f8080611a8c565b90919293945060011c9060019482860190558115611b095760601b908301556002019055611a20565b91505060601b6003179055611a20565b92508060601c908115611bc857838214611bbf5760018301805460601c908115611bad5750848114611ba3576002840190815460601c918215611b905750858214611b85576007935f52600160405f20555f52600260405f20555f52600360405f205517600792611a0b565b505050505050611a20565b9650505050505060601b90556001611a20565b5050505050611a20565b95505050505060601b90556001611a20565b50505050611a20565b5050915060601b90556001611a20565b68fbb67fda52d4bfb8bf91506119ee565b6001955061199a565b95509392601c903560601c95019260131901938f611992565b5f604051916396fb721760e01b83526001600160a01b03851660048401526002602484015260448338925afa61193b573d5f823e3d90fd5b611c566100ff8284869e9b9c9d9e6125ec565b611c646101138385876125ec565b505f516020612c525f395f51905f525480611dc2575b508160601b156104365760405163ecd0596160e01b81526001600482015260205f602483865afa1561042e57505f5115610421575f91813560e01c808301926008840192600485013560e01c946014861015611da9575b508515611da0575b611ce281612ab9565b15610c47579160019695949392916001600160a01b0388931691825f525f516020612c725f395f51905f526020526001600160a01b038716928360405f20555f516020612c325f395f51905f5260408051878152836020820152a1611d4681612a2a565b15611d8b575b505050141580611d7b575b611d6a575b505050019998979699610e4a565b611d7392612a6a565b8c8080611d5c565b50611d8583612a2a565b15611d57565b6004611d98930190612a6a565b5f8080611d4c565b60019550611cd9565b95509392601c903560601c95019260131901935f611cd1565b5f604051916396fb721760e01b83526001600160a01b03851660048401526001602484015260448338925afa611c7a573d5f823e3d90fd5b611e0393612622565b8c808080610e33565b61103b611e18366123b7565b916001600160a01b038416611e36575b85856100ba6100af826125a5565b611e3f93612622565b82808080611e28565b34610da357611e563661226b565b6040517f4f2690a200000000000000000000000000000000000000000000000000000000602082015261014060248201529e8f9e919d939c949b929a95999698979694938f91611eab90610164840190612462565b91602319818403019060440152611ec1926124d2565b908d602319818403019060640152611ed8926124d2565b906023198c83030160848d0152611eee926124d2565b906023198a83030160a48b0152611f04926124d2565b8781036023190160c4890152611f1991612462565b8681036023190160e4880152611f2e91612462565b916001600160a01b031661010486015260231985830301610124860152611f5492612537565b9060ff1661014483015203601f1981018252611f70908261242c565b604051908190611f84903060208401612578565b03601f1981018252611f96908261242c565b60405180916020825260208201610d9f91612100565b34610da357611fba36612169565b999b9a60409992999891979495969398519c8d9c60208e017ffb3761360000000000000000000000000000000000000000000000000000000090528d6024810161010090526101240161200c91612462565b908d602319818403019060440152612023926124d2565b906023198c83030160648d0152612039926124d2565b906023198a83030160848b015261204f926124d2565b906023198883030160a4890152612065926124d2565b916001600160a01b031660c48601526023198583030160e486015261208992612537565b9060ff1661010483015203601f1981018252611f70908261242c565b34610da3575f366003190112610da357610d9f6040516120c660408261242c565b600981527f426f6f747374726170000000000000000000000000000000000000000000000060208201526040519182916020835260208301905b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b9181601f84011215610da35782359167ffffffffffffffff8311610da3576020808501948460051b010111610da357565b35906001600160a01b0382168203610da357565b610100600319820112610da35760043567ffffffffffffffff8111610da35760408183036003190112610da3576004019160243567ffffffffffffffff8111610da357826121b991600401612124565b9290929160443567ffffffffffffffff8111610da357826121dc91600401612124565b9290929160643567ffffffffffffffff8111610da357826121ff91600401612124565b9290929160843567ffffffffffffffff8111610da3578261222291600401612124565b9290929160a4356001600160a01b0381168103610da3579160c4359067ffffffffffffffff8211610da35761225991600401612124565b909160e43560ff81168103610da35790565b610140600319820112610da35760043567ffffffffffffffff8111610da35760408183036003190112610da3576004019160243567ffffffffffffffff8111610da357826122bb91600401612124565b9290929160443567ffffffffffffffff8111610da357826122de91600401612124565b9290929160643567ffffffffffffffff8111610da3578261230191600401612124565b9290929160843567ffffffffffffffff8111610da3578261232491600401612124565b9290929160a43567ffffffffffffffff8111610da35760408184036003190112610da3576004019160c43567ffffffffffffffff8111610da35760408183036003190112610da3576004019160e4356001600160a01b0381168103610da35791610104359067ffffffffffffffff8211610da3576123a491600401612124565b90916101243560ff81168103610da35790565b6080600319820112610da35760043567ffffffffffffffff8111610da35760408183036003190112610da357600401916024356001600160a01b0381168103610da357916044359067ffffffffffffffff8211610da35761241a91600401612124565b909160643560ff81168103610da35790565b90601f8019910116810190811067ffffffffffffffff82111761244e57604052565b634e487b7160e01b5f52604160045260245ffd5b6001600160a01b0361247382612155565b1682526020810135601e1982360301811215610da35701906020823592019167ffffffffffffffff8111610da3578036038313610da3578060609360406020850152816040850152848401375f828201840152601f01601f1916010190565b90602083828152019060208160051b85010193835f915b8383106124f95750505050505090565b909192939495601f198282030186528635603e1984360301811215610da357602061252960019386839401612462565b9801960194930191906124e9565b916020908281520191905f5b8181106125505750505090565b9091926020806001926001600160a01b0361256a88612155565b168152019401929101612543565b6014926020926bffffffffffffffffffffffff199060601b1682528051928391018483015e01015f815290565b356001600160a01b0381168103610da35790565b903590601e1981360301821215610da3570180359067ffffffffffffffff8211610da357602001918136038313610da357565b919081101561260e5760051b81013590603e1981360301821215610da3570190565b634e487b7160e01b5f52603260045260245ffd5b6001600160a01b0316805f516020612c525f395f51905f5255807f7d1c97842846d37d5ecd1884bd61723b85333bfbc4e3daa46882adaf1876afd25f80a28061266c575b50505050565b5f92604051947ff05c04e100000000000000000000000000000000000000000000000000000000865260048601526040602486015280604486015260051b8092606486013783836064389401925af11561042e57808080612666565b906001600160a01b0382169283158080156129f7575b6129cf5763978aab926004527fffb1db744ac0caf2c7f81a63c0858e72cff909d0c940f6d0d5009607061ef1015f5260245f20859168fbb67fda52d4bfb8bf87146103f2576129be575b80546bffffffffffffffffffffffff81161561298457506020525f5260405f205415155b61295b57505f516020612c525f395f51905f52548061292c575b508160601b156104365760405163ecd0596160e01b81526001600482015260205f602483865afa1561042e57505f5115610421575f91813560e01c808301926008840192600485013560e01c946014861015612913575b50851561290a575b6127ce90612ab9565b156128f25790600191865f525f516020612c725f395f51905f526020526001600160a01b038616918260405f20555f516020612c325f395f51905f52604080518681528a6020820152a161282188612a2a565b156128de575b50501415806128ce575b6128bd575b5050505b8073ffffffffffffffffffffffffffffffffffffffff197fffb1db744ac0caf2c7f81a63c0858e72cff909d0c940f6d0d5009607061ef1005416177fffb1db744ac0caf2c7f81a63c0858e72cff909d0c940f6d0d5009607061ef100557fdba94517c2e4d2bd67ab2d9e679f0a166a27f8026e070545b1b1f067424597785f80a2565b6128c692612a6a565b5f8080612836565b506128d883612a2a565b15612831565b60046128eb920188612a6a565b5f80612827565b85630b961e3560e11b5f52600160045260245260445ffd5b600195506127c5565b95509392601c903560601c95019260131901935f6127bd565b5f604051916396fb721760e01b83528560048401526001602484015260448338925afa612766573d5f823e3d90fd5b9061296583612a2a565b15612973575b50505061283a565b61297c92612a6a565b5f808061296b565b91908160019360601c146129b757818382015460601c146129b7576002015460601c146129b257505f61274c565b61274c565b505061274c565b68fbb67fda52d4bfb8bf9150612728565b7fefc0ad37000000000000000000000000000000000000000000000000000000005f5260045ffd5b506001600160a01b037fffb1db744ac0caf2c7f81a63c0858e72cff909d0c940f6d0d5009607061ef100541685146126de565b60205f602460405180947fd60b347f0000000000000000000000000000000000000000000000000000000082523060048301525afa1561042e57505f5190565b5f91908291826044866040519788947f6d61fe70000000000000000000000000000000000000000000000000000000008652602060048701528160248701528386013701925af11561042e5750565b905f9163978aab926004527fffb1db744ac0caf2c7f81a63c0858e72cff909d0c940f6d0d5009607061ef1015f526001600160a01b0360245f2091169068fbb67fda52d4bfb8bf82146103f2578115612c20575b80546bffffffffffffffffffffffff811692826020528315612b73575b805f5260405f2093845415612b40575050505050565b90919293955060011c9060019582870190558115612b665760601b908301556002019055565b91505060601b6003179055565b92508060601c908115612c11578382146126665760018301805460601c908115612c005750848114612bf9576002840190815460601c918215612be75750858214612bdf576007935f52600160405f20555f52600260405f20555f52600360405f205517600792612b2a565b505050505050565b969750505050505060601b9055600190565b5050505050565b9596505050505060601b9055600190565b505091925060601b9055600190565b68fbb67fda52d4bfb8bf9150612b0d56fed21d0b289f126c4b473ea641963e766833c2f13866e4ff480abd787c100ef1231a72bca8c19a5ea6f4c84f32c9ea9486de8a7c32689a31ace7fab938dfd59100804aa2c00aa2afd5774b5603b005ba2fe99b98231bb0faa297c8cbc51d78c800
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.