Skip to content

Commit

Permalink
Merge pull request #77 from rhinestonewtf/feature/modulekit-to-packages
Browse files Browse the repository at this point in the history
Feature/modulekit to packages
  • Loading branch information
zeroknots authored Feb 21, 2024
2 parents e7f6cc0 + c21951d commit ad17830
Show file tree
Hide file tree
Showing 260 changed files with 1,833 additions and 313 deletions.
6 changes: 6 additions & 0 deletions .github/ISSUE_TEMPLATE/Safe7579_issue_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
name: Safe7579 Issue Template
about: Use this template to report a bug in the Safe7579 module
title: "[Safe7579]: [TITLE OF THE ISSUE]"
labels: safe7579, modulekit
---
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ out/
/broadcast/*/31337/
/broadcast/**/dry-run/

gas_calculations/*.json
packages/modulekit/gas_calculations/*.json

# Docs
docs/
Expand Down
4 changes: 4 additions & 0 deletions accounts/safe7579/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,13 @@
},
"devDependencies": {
"@rhinestone/modulekit": "workspace:*",
"@rhinestone/sessionkeymanager": "workspace:*",
"@safe-global/safe-contracts": "^1.4.1",
"@openzeppelin/contracts": "5.0.1",
"@ERC4337/account-abstraction": "github:kopy-kat/account-abstraction#develop",
"@ERC4337/account-abstraction-v0.6": "github:eth-infinitism/account-abstraction#v0.6.0",
"erc4337-validation": "github:rhinestonewtf/erc4337-validation",
"@prb/math": "^4.0.2",
"forge-std": "github:foundry-rs/forge-std",
"ds-test": "github:dapphub/ds-test",
"erc7579": "github:erc7579/erc7579-implementation",
Expand Down
4 changes: 4 additions & 0 deletions accounts/safe7579/remappings.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
ds-test/=node_modules/ds-test/src/
forge-std/=node_modules/forge-std/src/
account-abstraction/=node_modules/@ERC4337/account-abstraction/contracts/
account-abstraction-v0.6/=node_modules/@ERC4337/account-abstraction-v0.6/contracts/
erc7579/=node_modules/erc7579/src/
sentinellist/=node_modules/sentinellist/src/
solmate/=node_modules/solmate/src/
Expand All @@ -9,3 +10,6 @@ solarray/=node_modules/solarray/src/
@rhinestone/=node_modules/@rhinestone/
@safe-global/=node_modules/@safe-global/
@ERC4337/=node_modules/@ERC4337/
@openzeppelin/=node_modules/@openzeppelin/
@prb/math/=node_modules/@prb/math/
erc4337-validation/=node_modules/erc4337-validation/src/
49 changes: 0 additions & 49 deletions accounts/safe7579/src/Account.sol

This file was deleted.

115 changes: 83 additions & 32 deletions accounts/safe7579/src/SafeERC7579.sol
Original file line number Diff line number Diff line change
@@ -1,34 +1,50 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;

import "erc7579/interfaces/IERC7579Account.sol";
import "erc7579/interfaces/IMSA.sol";
import "erc7579/lib/ModeLib.sol";
import "erc7579/lib/ExecutionLib.sol";
import "erc7579/interfaces/IERC7579Module.sol";
import "./AccessControl.sol";
import "./HookManager.sol";
import "./ExecutionHelper.sol";
import "./ModuleManager.sol";
import "./interfaces/ISafeOp.sol";
import { UserOperationLib } from "@ERC4337/account-abstraction/contracts/core/UserOperationLib.sol";
import { IERC7579Account, Execution } from "erc7579/interfaces/IERC7579Account.sol";
import { IMSA } from "erc7579/interfaces/IMSA.sol";
import {
CallType, ModeCode, ModeLib, CALLTYPE_SINGLE, CALLTYPE_BATCH
} from "erc7579/lib/ModeLib.sol";
import { ExecutionLib } from "erc7579/lib/ExecutionLib.sol";
import {
IValidator,
MODULE_TYPE_VALIDATOR,
MODULE_TYPE_HOOK,
MODULE_TYPE_EXECUTOR,
MODULE_TYPE_FALLBACK
} from "erc7579/interfaces/IERC7579Module.sol";
import { AccessControl } from "./core/AccessControl.sol";
import { HookManager } from "./core/HookManager.sol";
import { ISafeOp, SAFE_OP_TYPEHASH } from "./interfaces/ISafeOp.sol";
import { ISafe } from "./interfaces/ISafe.sol";
import {
PackedUserOperation,
UserOperationLib
} from "@ERC4337/account-abstraction/contracts/core/UserOperationLib.sol";
import { _packValidationData } from "@ERC4337/account-abstraction/contracts/core/Helpers.sol";

contract SafeERC7579 is
ISafeOp,
IERC7579Account,
AccessControl,
ExecutionHelper,
IMSA,
HookManager
{
import "forge-std/console2.sol";

/**
* @title ERC7579 Adapter for Safe accounts.
* By using Safe's Fallback and Execution modules,
* this contract creates full ERC7579 compliance to Safe accounts
* @author zeroknots.eth | rhinestone.wtf
*/
contract SafeERC7579 is ISafeOp, IERC7579Account, AccessControl, IMSA, HookManager {
using UserOperationLib for PackedUserOperation;
using ModeLib for ModeCode;
using ExecutionLib for bytes;

error Unsupported();

bytes32 private constant DOMAIN_SEPARATOR_TYPEHASH =
0x47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a79469218;

/**
* @inheritdoc IERC7579Account
*/
function execute(
ModeCode mode,
bytes calldata executionCalldata
Expand All @@ -53,6 +69,9 @@ contract SafeERC7579 is
}
}

/**
* @inheritdoc IERC7579Account
*/
function executeFromExecutor(
ModeCode mode,
bytes calldata executionCalldata
Expand All @@ -79,13 +98,21 @@ contract SafeERC7579 is
}
}

/**
* @inheritdoc IERC7579Account
*/
function executeUserOp(PackedUserOperation calldata userOp)
external
payable
override
onlyEntryPointOrSelf
{ }
{
revert Unsupported();
}

/**
* @inheritdoc IERC7579Account
*/
function validateUserOp(
PackedUserOperation calldata userOp,
bytes32 userOpHash,
Expand All @@ -110,9 +137,12 @@ contract SafeERC7579 is

// pay prefund
if (missingAccountFunds != 0) {
ISafe(userOp.getSender()).execTransactionFromModule(
entryPoint(), missingAccountFunds, "", 0
);
_execute({
safe: userOp.getSender(),
target: entryPoint(),
value: missingAccountFunds,
callData: ""
});
}
}

Expand Down Expand Up @@ -142,8 +172,14 @@ contract SafeERC7579 is
}
}

/**
* @inheritdoc IERC7579Account
*/
function isValidSignature(bytes32 hash, bytes calldata data) external view returns (bytes4) { }

/**
* @inheritdoc IERC7579Account
*/
function installModule(
uint256 moduleType,
address module,
Expand All @@ -162,6 +198,9 @@ contract SafeERC7579 is
emit ModuleInstalled(moduleType, module);
}

/**
* @inheritdoc IERC7579Account
*/
function uninstallModule(
uint256 moduleType,
address module,
Expand All @@ -180,20 +219,29 @@ contract SafeERC7579 is
emit ModuleUninstalled(moduleType, module);
}

/**
* @inheritdoc IERC7579Account
*/
function supportsAccountMode(ModeCode encodedMode) external pure override returns (bool) {
CallType callType = encodedMode.getCallType();
if (callType == CALLTYPE_BATCH) return true;
else if (callType == CALLTYPE_SINGLE) return true;
else return false;
}

/**
* @inheritdoc IERC7579Account
*/
function supportsModule(uint256 moduleTypeId) external pure override returns (bool) {
if (moduleTypeId == MODULE_TYPE_VALIDATOR) return true;
else if (moduleTypeId == MODULE_TYPE_EXECUTOR) return true;
else if (moduleTypeId == MODULE_TYPE_FALLBACK) return true;
else return false;
}

/**
* @inheritdoc IERC7579Account
*/
function isModuleInstalled(
uint256 moduleType,
address module,
Expand All @@ -211,8 +259,11 @@ contract SafeERC7579 is
else return false;
}

/**
* @inheritdoc IERC7579Account
*/
function accountId() external pure override returns (string memory accountImplementationId) {
return "safe-erc7579.v0.0.1";
return "safe-erc7579.v0.0.0";
}

/**
Expand Down Expand Up @@ -293,20 +344,20 @@ contract SafeERC7579 is
}
}

/**
* Domain Separator for EIP-712.
*/
function domainSeparator() public view returns (bytes32) {
return keccak256(abi.encode(DOMAIN_SEPARATOR_TYPEHASH, block.chainid, this));
}

function initializeAccount(bytes calldata data) external payable {
_initModuleManager();
(address[] memory validators, address[] memory executors) =
abi.decode(data, (address[], address[]));
for (uint256 i = 0; i < validators.length; i++) {
_installValidator(validators[i], data);
}

for (uint256 i = 0; i < executors.length; i++) {
_installExecutor(executors[i], data);
}
(address bootstrap, bytes memory bootstrapCall) = abi.decode(data, (address, bytes));
console2.log("bootstrap: ", bootstrap);

(bool success,) = bootstrap.delegatecall(bootstrapCall);
if (!success) revert AccountInitializationFailed();
}
}
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,42 @@
pragma solidity >=0.8.0 <0.9.0;

import { Execution } from "erc7579/interfaces/IERC7579Account.sol";
import "./interfaces/ISafe.sol";
import "forge-std/console2.sol";
import "../interfaces/ISafe.sol";

/**
* @title Helper contract to execute transactions from a safe
* All functions implemented in this contract check,
* that the transaction was successful
* @author zeroknots.eth
*/
abstract contract ExecutionHelper {
error ExecutionFailed();

contract ExecutionHelper {
function _execute(
address safe,
address target,
uint256 value,
bytes calldata callData
bytes memory callData
)
internal
{
bool success = ISafe(safe).execTransactionFromModule(target, value, callData, 0);
require(success, "Execution failed");
if (!success) revert ExecutionFailed();
}

function _executeReturnData(
address safe,
address target,
uint256 value,
bytes calldata callData
bytes memory callData
)
internal
returns (bytes memory returnData)
{
bool success;
(success, returnData) =
ISafe(safe).execTransactionFromModuleReturnData(target, value, callData, 0);
require(success, "Execution failed");
if (!success) revert ExecutionFailed();
}

function _execute(address safe, Execution[] calldata executions) internal {
Expand Down
Loading

0 comments on commit ad17830

Please sign in to comment.