-
Notifications
You must be signed in to change notification settings - Fork 111
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Separate Modifier and Module into normal and Guardable
- Loading branch information
1 parent
7f4a961
commit 3e9234a
Showing
10 changed files
with
321 additions
and
240 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
// SPDX-License-Identifier: LGPL-3.0-only | ||
pragma solidity >=0.7.0 <0.9.0; | ||
|
||
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; | ||
import "../signature/SignatureChecker.sol"; | ||
|
||
abstract contract MiniAvatar is SignatureChecker, OwnableUpgradeable { | ||
event EnabledModule(address module); | ||
event DisabledModule(address module); | ||
event ExecutionFromModuleSuccess(address indexed module); | ||
event ExecutionFromModuleFailure(address indexed module); | ||
|
||
address internal constant SENTINEL_MODULES = address(0x1); | ||
/// Mapping of modules. | ||
mapping(address => address) internal modules; | ||
|
||
/// `sender` is not an authorized module. | ||
/// @param sender The address of the sender. | ||
error NotAuthorized(address sender); | ||
|
||
/// `module` is invalid. | ||
error InvalidModule(address module); | ||
|
||
/// `pageSize` is invalid. | ||
error InvalidPageSize(); | ||
|
||
/// `module` is already disabled. | ||
error AlreadyDisabledModule(address module); | ||
|
||
/// `module` is already enabled. | ||
error AlreadyEnabledModule(address module); | ||
|
||
/// @dev `setModules()` was already called. | ||
error SetupModulesAlreadyCalled(); | ||
|
||
/* | ||
-------------------------------------------------- | ||
*/ | ||
|
||
modifier moduleOnly() { | ||
if (modules[msg.sender] == address(0)) { | ||
if (modules[moduleTxSignedBy()] == address(0)) { | ||
revert NotAuthorized(msg.sender); | ||
} | ||
moduleTxNonceBump(); | ||
} | ||
|
||
_; | ||
} | ||
|
||
/// @dev Disables a module. | ||
/// @notice This can only be called by the owner. | ||
/// @param prevModule Module that pointed to the module to be removed in the linked list. | ||
/// @param module Module to be removed. | ||
function disableModule( | ||
address prevModule, | ||
address module | ||
) public onlyOwner { | ||
if (module == address(0) || module == SENTINEL_MODULES) | ||
revert InvalidModule(module); | ||
if (modules[prevModule] != module) revert AlreadyDisabledModule(module); | ||
modules[prevModule] = modules[module]; | ||
modules[module] = address(0); | ||
emit DisabledModule(module); | ||
} | ||
|
||
/// @dev Enables a module that can add transactions to the queue | ||
/// @param module Address of the module to be enabled | ||
/// @notice This can only be called by the owner | ||
function enableModule(address module) public onlyOwner { | ||
if (module == address(0) || module == SENTINEL_MODULES) | ||
revert InvalidModule(module); | ||
if (modules[module] != address(0)) revert AlreadyEnabledModule(module); | ||
modules[module] = modules[SENTINEL_MODULES]; | ||
modules[SENTINEL_MODULES] = module; | ||
emit EnabledModule(module); | ||
} | ||
|
||
/// @dev Returns if an module is enabled | ||
/// @return True if the module is enabled | ||
function isModuleEnabled(address _module) public view returns (bool) { | ||
return SENTINEL_MODULES != _module && modules[_module] != address(0); | ||
} | ||
|
||
/// @dev Returns array of modules. | ||
/// If all entries fit into a single page, the next pointer will be 0x1. | ||
/// If another page is present, next will be the last element of the returned array. | ||
/// @param start Start of the page. Has to be a module or start pointer (0x1 address) | ||
/// @param pageSize Maximum number of modules that should be returned. Has to be > 0 | ||
/// @return array Array of modules. | ||
/// @return next Start of the next page. | ||
function getModulesPaginated( | ||
address start, | ||
uint256 pageSize | ||
) external view returns (address[] memory array, address next) { | ||
if (start != SENTINEL_MODULES && !isModuleEnabled(start)) { | ||
revert InvalidModule(start); | ||
} | ||
if (pageSize == 0) { | ||
revert InvalidPageSize(); | ||
} | ||
|
||
// Init array with max page size | ||
array = new address[](pageSize); | ||
|
||
// Populate return array | ||
uint256 moduleCount = 0; | ||
next = modules[start]; | ||
while ( | ||
next != address(0) && | ||
next != SENTINEL_MODULES && | ||
moduleCount < pageSize | ||
) { | ||
array[moduleCount] = next; | ||
next = modules[next]; | ||
moduleCount++; | ||
} | ||
|
||
// Because of the argument validation we can assume that | ||
// the `currentModule` will always be either a module address | ||
// or sentinel address (aka the end). If we haven't reached the end | ||
// inside the loop, we need to set the next pointer to the last element | ||
// because it skipped over to the next module which is neither included | ||
// in the current page nor won't be included in the next one | ||
// if you pass it as a start. | ||
if (next != SENTINEL_MODULES) { | ||
next = array[moduleCount - 1]; | ||
} | ||
// Set correct size of returned array | ||
// solhint-disable-next-line no-inline-assembly | ||
assembly { | ||
mstore(array, moduleCount) | ||
} | ||
} | ||
|
||
/// @dev Initializes the modules linked list. | ||
/// @notice Should be called as part of the `setUp` / initializing function and can only be called once. | ||
function setupModules() internal { | ||
if (modules[SENTINEL_MODULES] != address(0)) | ||
revert SetupModulesAlreadyCalled(); | ||
modules[SENTINEL_MODULES] = SENTINEL_MODULES; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
// SPDX-License-Identifier: LGPL-3.0-only | ||
pragma solidity >=0.7.0 <0.9.0; | ||
|
||
import "../interfaces/IAvatar.sol"; | ||
import "./MiniAvatar.sol"; | ||
import "./ModuleGuardable.sol"; | ||
|
||
/// @title Modifier Interface - A contract that sits between a Module and an Avatar and enforce some additional logic. | ||
abstract contract ModifierGuardable is ModuleGuardable, MiniAvatar, IAvatar { | ||
/* | ||
-------------------------------------------------- | ||
You must override at least one of following two virtual functions, | ||
execTransactionFromModule() and execTransactionFromModuleReturnData(). | ||
*/ | ||
|
||
/// @dev Passes a transaction to the modifier. | ||
/// @notice Can only be called by enabled modules. | ||
/// @param to Destination address of module transaction. | ||
/// @param value Ether value of module transaction. | ||
/// @param data Data payload of module transaction. | ||
/// @param operation Operation type of module transaction. | ||
function execTransactionFromModule( | ||
address to, | ||
uint256 value, | ||
bytes calldata data, | ||
Enum.Operation operation | ||
) public virtual override onlyOwner returns (bool success) {} | ||
|
||
/// @dev Passes a transaction to the modifier, expects return data. | ||
/// @notice Can only be called by enabled modules. | ||
/// @param to Destination address of module transaction. | ||
/// @param value Ether value of module transaction. | ||
/// @param data Data payload of module transaction. | ||
/// @param operation Operation type of module transaction. | ||
function execTransactionFromModuleReturnData( | ||
address to, | ||
uint256 value, | ||
bytes calldata data, | ||
Enum.Operation operation | ||
) | ||
public | ||
virtual | ||
override | ||
onlyOwner | ||
returns (bool success, bytes memory returnData) | ||
{} | ||
} |
Oops, something went wrong.