Files

39 lines
30 KiB
JSON

{
"contractName": "Permissions",
"sourceName": "contracts/Permissions.sol",
"compilerVersion": "v0.8.6+commit.11564f7e",
"constructorArguments": "",
"input": {
"language": "Solidity",
"sources": {
"contracts/Permissions.sol": {
"content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity ^0.8.6;\n\nimport \"@gnosis.pm/safe-contracts/contracts/common/Enum.sol\";\n\nenum ParameterType {\n Static,\n Dynamic,\n Dynamic32\n}\n\nenum Comparison {\n EqualTo,\n GreaterThan,\n LessThan,\n OneOf\n}\n\nenum ExecutionOptions {\n None,\n Send,\n DelegateCall,\n Both\n}\n\nenum Clearance {\n None,\n Target,\n Function\n}\n\nstruct TargetAddress {\n Clearance clearance;\n ExecutionOptions options;\n}\n\nstruct Role {\n mapping(address => bool) members;\n mapping(address => TargetAddress) targets;\n mapping(bytes32 => uint256) functions;\n mapping(bytes32 => bytes32) compValues;\n mapping(bytes32 => bytes32[]) compValuesOneOf;\n}\n\nlibrary Permissions {\n uint256 internal constant SCOPE_MAX_PARAMS = 48;\n\n event AllowTarget(\n uint16 role,\n address targetAddress,\n ExecutionOptions options\n );\n event RevokeTarget(uint16 role, address targetAddress);\n event ScopeTarget(uint16 role, address targetAddress);\n event ScopeAllowFunction(\n uint16 role,\n address targetAddress,\n bytes4 selector,\n ExecutionOptions options,\n uint256 resultingScopeConfig\n );\n event ScopeRevokeFunction(\n uint16 role,\n address targetAddress,\n bytes4 selector,\n uint256 resultingScopeConfig\n );\n event ScopeFunction(\n uint16 role,\n address targetAddress,\n bytes4 functionSig,\n bool[] isParamScoped,\n ParameterType[] paramType,\n Comparison[] paramComp,\n bytes[] compValue,\n ExecutionOptions options,\n uint256 resultingScopeConfig\n );\n event ScopeFunctionExecutionOptions(\n uint16 role,\n address targetAddress,\n bytes4 functionSig,\n ExecutionOptions options,\n uint256 resultingScopeConfig\n );\n event ScopeParameter(\n uint16 role,\n address targetAddress,\n bytes4 functionSig,\n uint256 index,\n ParameterType paramType,\n Comparison paramComp,\n bytes compValue,\n uint256 resultingScopeConfig\n );\n event ScopeParameterAsOneOf(\n uint16 role,\n address targetAddress,\n bytes4 functionSig,\n uint256 index,\n ParameterType paramType,\n bytes[] compValues,\n uint256 resultingScopeConfig\n );\n event UnscopeParameter(\n uint16 role,\n address targetAddress,\n bytes4 functionSig,\n uint256 index,\n uint256 resultingScopeConfig\n );\n\n /// Sender is not a member of the role\n error NoMembership();\n\n /// Arrays must be the same length\n error ArraysDifferentLength();\n\n /// Function signature too short\n error FunctionSignatureTooShort();\n\n /// Role not allowed to delegate call to target address\n error DelegateCallNotAllowed();\n\n /// Role not allowed to call target address\n error TargetAddressNotAllowed();\n\n /// Role not allowed to call this function on target address\n error FunctionNotAllowed();\n\n /// Role not allowed to send to target address\n error SendNotAllowed();\n\n /// Role not allowed to use bytes for parameter\n error ParameterNotAllowed();\n\n /// Role not allowed to use bytes for parameter\n error ParameterNotOneOfAllowed();\n\n /// Role not allowed to use bytes less than value for parameter\n error ParameterLessThanAllowed();\n\n /// Role not allowed to use bytes greater than value for parameter\n error ParameterGreaterThanAllowed();\n\n /// only multisend txs with an offset of 32 bytes are allowed\n error UnacceptableMultiSendOffset();\n\n /// OneOf Comparison must be set via dedicated function\n error UnsuitableOneOfComparison();\n\n /// Not possible to define gt/lt for Dynamic types\n error UnsuitableRelativeComparison();\n\n /// CompValue for static types should have a size of exactly 32 bytes\n error UnsuitableStaticCompValueSize();\n\n /// CompValue for Dynamic32 types should be a multiple of exactly 32 bytes\n error UnsuitableDynamic32CompValueSize();\n\n /// Exceeds the max number of params supported\n error ScopeMaxParametersExceeded();\n\n /// OneOf Comparison requires at least two compValues\n error NotEnoughCompValuesForOneOf();\n\n /// The provided calldata for execution is too short, or an OutOfBounds scoped parameter was configured\n error CalldataOutOfBounds();\n\n /*\n *\n * CHECKERS\n *\n */\n\n function check(\n Role storage role,\n address multisend,\n address to,\n uint256 value,\n bytes calldata data,\n Enum.Operation operation\n ) public view {\n if (!role.members[msg.sender]) {\n revert NoMembership();\n }\n if (multisend == to) {\n checkMultisendTransaction(role, data);\n } else {\n checkTransaction(role, to, value, data, operation);\n }\n }\n\n /// @dev Splits a multisend data blob into transactions and forwards them to be checked.\n /// @param data the packed transaction data (created by utils function buildMultiSendSafeTx).\n /// @param role Role to check for.\n function checkMultisendTransaction(Role storage role, bytes memory data)\n internal\n view\n {\n Enum.Operation operation;\n address to;\n uint256 value;\n bytes memory out;\n uint256 dataLength;\n\n uint256 offset;\n assembly {\n offset := mload(add(data, 36))\n }\n if (offset != 32) {\n revert UnacceptableMultiSendOffset();\n }\n\n // transaction data (1st tx operation) reads at byte 100,\n // 4 bytes (multisend_id) + 32 bytes (offset_multisend_data) + 32 bytes multisend_data_length\n // increment i by the transaction data length\n // + 85 bytes of the to, value, and operation bytes until we reach the end of the data\n for (uint256 i = 100; i < data.length; i += (85 + dataLength)) {\n assembly {\n // First byte of the data is the operation.\n // We shift by 248 bits (256 - 8 [operation byte]) right since mload will always load 32 bytes (a word).\n // This will also zero out unused data.\n operation := shr(0xf8, mload(add(data, i)))\n // We offset the load address by 1 byte (operation byte)\n // We shift it right by 96 bits (256 - 160 [20 address bytes]) to right-align the data and zero out unused data.\n to := shr(0x60, mload(add(data, add(i, 0x01))))\n // We offset the load address by 21 byte (operation byte + 20 address bytes)\n value := mload(add(data, add(i, 0x15)))\n // We offset the load address by 53 byte (operation byte + 20 address bytes + 32 value bytes)\n dataLength := mload(add(data, add(i, 0x35)))\n // We offset the load address by 85 byte (operation byte + 20 address bytes + 32 value bytes + 32 data length bytes)\n out := add(data, add(i, 0x35))\n }\n checkTransaction(role, to, value, out, operation);\n }\n }\n\n function checkTransaction(\n Role storage role,\n address targetAddress,\n uint256 value,\n bytes memory data,\n Enum.Operation operation\n ) internal view {\n if (data.length != 0 && data.length < 4) {\n revert FunctionSignatureTooShort();\n }\n\n TargetAddress storage target = role.targets[targetAddress];\n if (target.clearance == Clearance.None) {\n revert TargetAddressNotAllowed();\n }\n\n if (target.clearance == Clearance.Target) {\n checkExecutionOptions(value, operation, target.options);\n return;\n }\n\n if (target.clearance == Clearance.Function) {\n uint256 scopeConfig = role.functions[\n keyForFunctions(targetAddress, bytes4(data))\n ];\n\n if (scopeConfig == 0) {\n revert FunctionNotAllowed();\n }\n\n (ExecutionOptions options, bool isWildcarded, ) = unpackFunction(\n scopeConfig\n );\n\n checkExecutionOptions(value, operation, options);\n\n if (isWildcarded == false) {\n checkParameters(role, scopeConfig, targetAddress, data);\n }\n return;\n }\n\n assert(false);\n }\n\n function checkExecutionOptions(\n uint256 value,\n Enum.Operation operation,\n ExecutionOptions options\n ) internal pure {\n // isSend && !canSend\n if (\n value > 0 &&\n options != ExecutionOptions.Send &&\n options != ExecutionOptions.Both\n ) {\n revert SendNotAllowed();\n }\n\n // isDelegateCall && !canDelegateCall\n if (\n operation == Enum.Operation.DelegateCall &&\n options != ExecutionOptions.DelegateCall &&\n options != ExecutionOptions.Both\n ) {\n revert DelegateCallNotAllowed();\n }\n }\n\n /// @dev Will revert if a transaction has a parameter that is not allowed\n /// @param role reference to role storage\n /// @param targetAddress Address to check.\n /// @param data the transaction data to check\n function checkParameters(\n Role storage role,\n uint256 scopeConfig,\n address targetAddress,\n bytes memory data\n ) internal view {\n bytes4 functionSig = bytes4(data);\n (, , uint256 length) = unpackFunction(scopeConfig);\n\n for (uint256 i = 0; i < length; i++) {\n (\n bool isScoped,\n ParameterType paramType,\n Comparison paramComp\n ) = unpackParameter(scopeConfig, i);\n\n if (!isScoped) {\n continue;\n }\n\n bytes32 value;\n if (paramType != ParameterType.Static) {\n value = pluckDynamicValue(data, paramType, i);\n } else {\n value = pluckStaticValue(data, i);\n }\n\n bytes32 key = keyForCompValues(targetAddress, functionSig, i);\n if (paramComp != Comparison.OneOf) {\n compare(paramComp, role.compValues[key], value);\n } else {\n compareOneOf(role.compValuesOneOf[key], value);\n }\n }\n }\n\n function compare(\n Comparison paramComp,\n bytes32 compValue,\n bytes32 value\n ) internal pure {\n if (paramComp == Comparison.EqualTo && value != compValue) {\n revert ParameterNotAllowed();\n } else if (paramComp == Comparison.GreaterThan && value <= compValue) {\n revert ParameterLessThanAllowed();\n } else if (paramComp == Comparison.LessThan && value >= compValue) {\n revert ParameterGreaterThanAllowed();\n }\n }\n\n function compareOneOf(bytes32[] storage compValue, bytes32 value)\n internal\n view\n {\n for (uint256 i = 0; i < compValue.length; i++) {\n if (value == compValue[i]) return;\n }\n revert ParameterNotOneOfAllowed();\n }\n\n /*\n *\n * SETTERS\n *\n */\n\n function allowTarget(\n Role storage role,\n uint16 roleId,\n address targetAddress,\n ExecutionOptions options\n ) external {\n role.targets[targetAddress] = TargetAddress(Clearance.Target, options);\n emit AllowTarget(roleId, targetAddress, options);\n }\n\n function revokeTarget(\n Role storage role,\n uint16 roleId,\n address targetAddress\n ) external {\n role.targets[targetAddress] = TargetAddress(\n Clearance.None,\n ExecutionOptions.None\n );\n emit RevokeTarget(roleId, targetAddress);\n }\n\n function scopeTarget(\n Role storage role,\n uint16 roleId,\n address targetAddress\n ) external {\n role.targets[targetAddress] = TargetAddress(\n Clearance.Function,\n ExecutionOptions.None\n );\n emit ScopeTarget(roleId, targetAddress);\n }\n\n function scopeAllowFunction(\n Role storage role,\n uint16 roleId,\n address targetAddress,\n bytes4 functionSig,\n ExecutionOptions options\n ) external {\n /*\n * packLeft(\n * 0 -> start from a fresh scopeConfig\n * options -> externally provided options\n * true -> mark the function as wildcarded\n * 0 -> length\n * )\n */\n uint256 scopeConfig = packLeft(0, options, true, 0);\n role.functions[\n keyForFunctions(targetAddress, functionSig)\n ] = scopeConfig;\n emit ScopeAllowFunction(\n roleId,\n targetAddress,\n functionSig,\n options,\n scopeConfig\n );\n }\n\n function scopeRevokeFunction(\n Role storage role,\n uint16 roleId,\n address targetAddress,\n bytes4 functionSig\n ) external {\n role.functions[keyForFunctions(targetAddress, functionSig)] = 0;\n emit ScopeRevokeFunction(roleId, targetAddress, functionSig, 0);\n }\n\n function scopeFunction(\n Role storage role,\n uint16 roleId,\n address targetAddress,\n bytes4 functionSig,\n bool[] memory isScoped,\n ParameterType[] memory paramType,\n Comparison[] memory paramComp,\n bytes[] calldata compValue,\n ExecutionOptions options\n ) external {\n uint256 length = isScoped.length;\n\n if (\n length != paramType.length ||\n length != paramComp.length ||\n length != compValue.length\n ) {\n revert ArraysDifferentLength();\n }\n\n if (length > SCOPE_MAX_PARAMS) {\n revert ScopeMaxParametersExceeded();\n }\n\n for (uint256 i = 0; i < length; i++) {\n if (isScoped[i]) {\n enforceComp(paramType[i], paramComp[i]);\n enforceCompValue(paramType[i], compValue[i]);\n }\n }\n\n /*\n * packLeft(\n * 0 -> start from a fresh scopeConfig\n * options -> externally provided options\n * false -> mark the function as not wildcarded\n * 0 -> length\n * )\n */\n uint256 scopeConfig = packLeft(0, options, false, length);\n for (uint256 i = 0; i < length; i++) {\n scopeConfig = packRight(\n scopeConfig,\n i,\n isScoped[i],\n paramType[i],\n paramComp[i]\n );\n }\n\n //set scopeConfig\n role.functions[\n keyForFunctions(targetAddress, functionSig)\n ] = scopeConfig;\n\n //set compValues\n for (uint256 i = 0; i < length; i++) {\n role.compValues[\n keyForCompValues(targetAddress, functionSig, i)\n ] = compressCompValue(paramType[i], compValue[i]);\n }\n emit ScopeFunction(\n roleId,\n targetAddress,\n functionSig,\n isScoped,\n paramType,\n paramComp,\n compValue,\n options,\n scopeConfig\n );\n }\n\n function scopeFunctionExecutionOptions(\n Role storage role,\n uint16 roleId,\n address targetAddress,\n bytes4 functionSig,\n ExecutionOptions options\n ) external {\n bytes32 key = keyForFunctions(targetAddress, functionSig);\n\n //set scopeConfig\n uint256 scopeConfig = packOptions(role.functions[key], options);\n\n role.functions[\n keyForFunctions(targetAddress, functionSig)\n ] = scopeConfig;\n\n emit ScopeFunctionExecutionOptions(\n roleId,\n targetAddress,\n functionSig,\n options,\n scopeConfig\n );\n }\n\n function scopeParameter(\n Role storage role,\n uint16 roleId,\n address targetAddress,\n bytes4 functionSig,\n uint256 index,\n ParameterType paramType,\n Comparison paramComp,\n bytes calldata compValue\n ) external {\n if (index >= SCOPE_MAX_PARAMS) {\n revert ScopeMaxParametersExceeded();\n }\n\n enforceComp(paramType, paramComp);\n enforceCompValue(paramType, compValue);\n\n // set scopeConfig\n bytes32 key = keyForFunctions(targetAddress, functionSig);\n uint256 scopeConfig = packParameter(\n role.functions[key],\n index,\n true, // isScoped\n paramType,\n paramComp\n );\n role.functions[key] = scopeConfig;\n\n // set compValue\n role.compValues[\n keyForCompValues(targetAddress, functionSig, index)\n ] = compressCompValue(paramType, compValue);\n\n emit ScopeParameter(\n roleId,\n targetAddress,\n functionSig,\n index,\n paramType,\n paramComp,\n compValue,\n scopeConfig\n );\n }\n\n function scopeParameterAsOneOf(\n Role storage role,\n uint16 roleId,\n address targetAddress,\n bytes4 functionSig,\n uint256 index,\n ParameterType paramType,\n bytes[] calldata compValues\n ) external {\n if (index >= SCOPE_MAX_PARAMS) {\n revert ScopeMaxParametersExceeded();\n }\n\n if (compValues.length < 2) {\n revert NotEnoughCompValuesForOneOf();\n }\n\n for (uint256 i = 0; i < compValues.length; i++) {\n enforceCompValue(paramType, compValues[i]);\n }\n\n // set scopeConfig\n bytes32 key = keyForFunctions(targetAddress, functionSig);\n uint256 scopeConfig = packParameter(\n role.functions[key],\n index,\n true, // isScoped\n paramType,\n Comparison.OneOf\n );\n role.functions[key] = scopeConfig;\n\n // set compValue\n key = keyForCompValues(targetAddress, functionSig, index);\n role.compValuesOneOf[key] = new bytes32[](compValues.length);\n for (uint256 i = 0; i < compValues.length; i++) {\n role.compValuesOneOf[key][i] = compressCompValue(\n paramType,\n compValues[i]\n );\n }\n\n emit ScopeParameterAsOneOf(\n roleId,\n targetAddress,\n functionSig,\n index,\n paramType,\n compValues,\n scopeConfig\n );\n }\n\n function unscopeParameter(\n Role storage role,\n uint16 roleId,\n address targetAddress,\n bytes4 functionSig,\n uint256 index\n ) external {\n if (index >= SCOPE_MAX_PARAMS) {\n revert ScopeMaxParametersExceeded();\n }\n\n // set scopeConfig\n bytes32 key = keyForFunctions(targetAddress, functionSig);\n uint256 scopeConfig = packParameter(\n role.functions[key],\n index,\n false, // isScoped\n ParameterType(0),\n Comparison(0)\n );\n role.functions[key] = scopeConfig;\n\n emit UnscopeParameter(\n roleId,\n targetAddress,\n functionSig,\n index,\n scopeConfig\n );\n }\n\n function enforceComp(ParameterType paramType, Comparison paramComp)\n internal\n pure\n {\n if (paramComp == Comparison.OneOf) {\n revert UnsuitableOneOfComparison();\n }\n\n if (\n (paramType != ParameterType.Static) &&\n (paramComp != Comparison.EqualTo)\n ) {\n revert UnsuitableRelativeComparison();\n }\n }\n\n function enforceCompValue(ParameterType paramType, bytes calldata compValue)\n internal\n pure\n {\n if (paramType == ParameterType.Static && compValue.length != 32) {\n revert UnsuitableStaticCompValueSize();\n }\n\n if (\n paramType == ParameterType.Dynamic32 && compValue.length % 32 != 0\n ) {\n revert UnsuitableDynamic32CompValueSize();\n }\n }\n\n /*\n *\n * HELPERS\n *\n */\n function pluckDynamicValue(\n bytes memory data,\n ParameterType paramType,\n uint256 index\n ) internal pure returns (bytes32) {\n assert(paramType != ParameterType.Static);\n // pre-check: is there a word available for the current parameter at argumentsBlock?\n if (data.length < 4 + index * 32 + 32) {\n revert CalldataOutOfBounds();\n }\n\n /*\n * Encoded calldata:\n * 4 bytes -> function selector\n * 32 bytes -> sequence, one chunk per parameter\n *\n * There is one (byte32) chunk per parameter. Depending on type it contains:\n * Static -> value encoded inline (not plucked by this function)\n * Dynamic -> a byte offset to encoded data payload\n * Dynamic32 -> a byte offset to encoded data payload\n * Note: Fixed Sized Arrays (e.g., bool[2]), are encoded inline\n * Note: Nested types also do not follow the above described rules, and are unsupported\n * Note: The offset to payload does not include 4 bytes for functionSig\n *\n *\n * At encoded payload, the first 32 bytes are the length encoding of the parameter payload. Depending on ParameterType:\n * Dynamic -> length in bytes\n * Dynamic32 -> length in bytes32\n * Note: Dynamic types are: bytes, string\n * Note: Dynamic32 types are non-nested arrays: address[] bytes32[] uint[] etc\n */\n\n // the start of the parameter block\n // 32 bytes - length encoding of the data bytes array\n // 4 bytes - function sig\n uint256 argumentsBlock;\n assembly {\n argumentsBlock := add(data, 36)\n }\n\n // the two offsets are relative to argumentsBlock\n uint256 offset = index * 32;\n uint256 offsetPayload;\n assembly {\n offsetPayload := mload(add(argumentsBlock, offset))\n }\n\n uint256 lengthPayload;\n assembly {\n lengthPayload := mload(add(argumentsBlock, offsetPayload))\n }\n\n // account for:\n // 4 bytes - functionSig\n // 32 bytes - length encoding for the parameter payload\n uint256 start = 4 + offsetPayload + 32;\n uint256 end = start +\n (\n paramType == ParameterType.Dynamic32\n ? lengthPayload * 32\n : lengthPayload\n );\n\n // are we slicing out of bounds?\n if (data.length < end) {\n revert CalldataOutOfBounds();\n }\n\n return keccak256(slice(data, start, end));\n }\n\n function pluckStaticValue(bytes memory data, uint256 index)\n internal\n pure\n returns (bytes32)\n {\n // pre-check: is there a word available for the current parameter at argumentsBlock?\n if (data.length < 4 + index * 32 + 32) {\n revert CalldataOutOfBounds();\n }\n\n uint256 offset = 4 + index * 32;\n bytes32 value;\n assembly {\n // add 32 - jump over the length encoding of the data bytes array\n value := mload(add(32, add(data, offset)))\n }\n return value;\n }\n\n function slice(\n bytes memory data,\n uint256 start,\n uint256 end\n ) internal pure returns (bytes memory result) {\n result = new bytes(end - start);\n for (uint256 j = start; j < end; j++) {\n result[j - start] = data[j];\n }\n }\n\n /*\n * pack/unpack are bit helpers for scopeConfig\n */\n function packParameter(\n uint256 scopeConfig,\n uint256 index,\n bool isScoped,\n ParameterType paramType,\n Comparison paramComp\n ) internal pure returns (uint256) {\n (ExecutionOptions options, , uint256 prevLength) = unpackFunction(\n scopeConfig\n );\n\n uint256 nextLength = index + 1 > prevLength ? index + 1 : prevLength;\n\n return\n packLeft(\n packRight(scopeConfig, index, isScoped, paramType, paramComp),\n options,\n false, // isWildcarded=false\n nextLength\n );\n }\n\n function packOptions(uint256 scopeConfig, ExecutionOptions options)\n internal\n pure\n returns (uint256)\n {\n uint256 optionsMask = 3 << 254;\n\n scopeConfig &= ~optionsMask;\n scopeConfig |= uint256(options) << 254;\n\n return scopeConfig;\n }\n\n function packLeft(\n uint256 scopeConfig,\n ExecutionOptions options,\n bool isWildcarded,\n uint256 length\n ) internal pure returns (uint256) {\n // LEFT SIDE\n // 2 bits -> options\n // 1 bits -> isWildcarded\n // 5 bits -> unused\n // 8 bits -> length\n // RIGHT SIDE\n // 48 bits -> isScoped\n // 96 bits -> paramType (2 bits per entry 48*2)\n // 96 bits -> paramComp (2 bits per entry 48*2)\n\n // Wipe the LEFT SIDE clean. Start from there\n scopeConfig = (scopeConfig << 16) >> 16;\n\n // set options -> 256 - 2 = 254\n scopeConfig |= uint256(options) << 254;\n\n // set isWildcarded -> 256 - 2 - 1 = 253\n if (isWildcarded) {\n scopeConfig |= 1 << 253;\n }\n\n // set Length -> 48 + 96 + 96 = 240\n scopeConfig |= length << 240;\n\n return scopeConfig;\n }\n\n function packRight(\n uint256 scopeConfig,\n uint256 index,\n bool isScoped,\n ParameterType paramType,\n Comparison paramComp\n ) internal pure returns (uint256) {\n // LEFT SIDE\n // 2 bits -> options\n // 1 bits -> isWildcarded\n // 5 bits -> unused\n // 8 bits -> length\n // RIGHT SIDE\n // 48 bits -> isScoped\n // 96 bits -> paramType (2 bits per entry 48*2)\n // 96 bits -> paramComp (2 bits per entry 48*2)\n uint256 isScopedMask = 1 << (index + 96 + 96);\n uint256 paramTypeMask = 3 << (index * 2 + 96);\n uint256 paramCompMask = 3 << (index * 2);\n\n if (isScoped) {\n scopeConfig |= isScopedMask;\n } else {\n scopeConfig &= ~isScopedMask;\n }\n\n scopeConfig &= ~paramTypeMask;\n scopeConfig |= uint256(paramType) << (index * 2 + 96);\n\n scopeConfig &= ~paramCompMask;\n scopeConfig |= uint256(paramComp) << (index * 2);\n\n return scopeConfig;\n }\n\n function unpackFunction(uint256 scopeConfig)\n internal\n pure\n returns (\n ExecutionOptions options,\n bool isWildcarded,\n uint256 length\n )\n {\n uint256 isWildcardedMask = 1 << 253;\n\n options = ExecutionOptions(scopeConfig >> 254);\n isWildcarded = scopeConfig & isWildcardedMask != 0;\n length = (scopeConfig << 8) >> 248;\n }\n\n function unpackParameter(uint256 scopeConfig, uint256 index)\n internal\n pure\n returns (\n bool isScoped,\n ParameterType paramType,\n Comparison paramComp\n )\n {\n uint256 isScopedMask = 1 << (index + 96 + 96);\n uint256 paramTypeMask = 3 << (index * 2 + 96);\n uint256 paramCompMask = 3 << (index * 2);\n\n isScoped = (scopeConfig & isScopedMask) != 0;\n paramType = ParameterType(\n (scopeConfig & paramTypeMask) >> (index * 2 + 96)\n );\n paramComp = Comparison((scopeConfig & paramCompMask) >> (index * 2));\n }\n\n function keyForFunctions(address targetAddress, bytes4 functionSig)\n public\n pure\n returns (bytes32)\n {\n return bytes32(abi.encodePacked(targetAddress, functionSig));\n }\n\n function keyForCompValues(\n address targetAddress,\n bytes4 functionSig,\n uint256 index\n ) public pure returns (bytes32) {\n return\n bytes32(abi.encodePacked(targetAddress, functionSig, uint8(index)));\n }\n\n function compressCompValue(\n ParameterType paramType,\n bytes calldata compValue\n ) internal pure returns (bytes32) {\n return\n paramType == ParameterType.Static\n ? bytes32(compValue)\n : keccak256(compValue);\n }\n}\n"
},
"@gnosis.pm/safe-contracts/contracts/common/Enum.sol": {
"content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.7.0 <0.9.0;\n\n/// @title Enum - Collection of enums\n/// @author Richard Meissner - <[email protected]>\ncontract Enum {\n enum Operation {Call, DelegateCall}\n}\n"
}
},
"settings": {
"optimizer": {
"enabled": false,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"metadata": {
"useLiteralContent": true
},
"libraries": {}
}
}
}