Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 0 additions & 45 deletions deploy/deploy-all.ts

This file was deleted.

1 change: 0 additions & 1 deletion deployments/arbitrum/.chainId

This file was deleted.

140 changes: 0 additions & 140 deletions deployments/arbitrum/KernelFactory.json

This file was deleted.

201 changes: 0 additions & 201 deletions deployments/arbitrum/ZeroDevSessionKeyPlugin.json

This file was deleted.

135 changes: 0 additions & 135 deletions deployments/arbitrum/solcInputs/d5c4a417af7f759d03a3c7da438dc2be.json

This file was deleted.

1 change: 0 additions & 1 deletion deployments/arbitrumGoerli/.chainId

This file was deleted.

124 changes: 0 additions & 124 deletions deployments/arbitrumGoerli/KernelFactory.json

This file was deleted.

201 changes: 0 additions & 201 deletions deployments/arbitrumGoerli/ZeroDevSessionKeyPlugin.json

This file was deleted.

This file was deleted.

1 change: 0 additions & 1 deletion deployments/avalanche/.chainId

This file was deleted.

140 changes: 0 additions & 140 deletions deployments/avalanche/KernelFactory.json

This file was deleted.

201 changes: 0 additions & 201 deletions deployments/avalanche/ZeroDevSessionKeyPlugin.json

This file was deleted.

135 changes: 0 additions & 135 deletions deployments/avalanche/solcInputs/d5c4a417af7f759d03a3c7da438dc2be.json

This file was deleted.

1 change: 0 additions & 1 deletion deployments/baseGoerli/.chainId

This file was deleted.

140 changes: 0 additions & 140 deletions deployments/baseGoerli/KernelFactory.json

This file was deleted.

201 changes: 0 additions & 201 deletions deployments/baseGoerli/ZeroDevSessionKeyPlugin.json

This file was deleted.

This file was deleted.

1 change: 0 additions & 1 deletion deployments/bsc/.chainId

This file was deleted.

140 changes: 0 additions & 140 deletions deployments/bsc/KernelFactory.json

This file was deleted.

201 changes: 0 additions & 201 deletions deployments/bsc/ZeroDevSessionKeyPlugin.json

This file was deleted.

129 changes: 0 additions & 129 deletions deployments/bsc/solcInputs/b4f7aa20796f803709c4f0ee7de51b7f.json

This file was deleted.

1 change: 0 additions & 1 deletion deployments/bscTestnet/.chainId

This file was deleted.

140 changes: 0 additions & 140 deletions deployments/bscTestnet/KernelFactory.json

This file was deleted.

201 changes: 0 additions & 201 deletions deployments/bscTestnet/ZeroDevSessionKeyPlugin.json

This file was deleted.

This file was deleted.

1 change: 0 additions & 1 deletion deployments/ethereum/.chainId

This file was deleted.

140 changes: 0 additions & 140 deletions deployments/ethereum/KernelFactory.json

This file was deleted.

201 changes: 0 additions & 201 deletions deployments/ethereum/ZeroDevSessionKeyPlugin.json

This file was deleted.

135 changes: 0 additions & 135 deletions deployments/ethereum/solcInputs/d5c4a417af7f759d03a3c7da438dc2be.json

This file was deleted.

1 change: 0 additions & 1 deletion deployments/fuji/.chainId

This file was deleted.

140 changes: 0 additions & 140 deletions deployments/fuji/KernelFactory.json

This file was deleted.

201 changes: 0 additions & 201 deletions deployments/fuji/ZeroDevSessionKeyPlugin.json

This file was deleted.

135 changes: 0 additions & 135 deletions deployments/fuji/solcInputs/d5c4a417af7f759d03a3c7da438dc2be.json

This file was deleted.

1 change: 0 additions & 1 deletion deployments/goerli/.chainId

This file was deleted.

140 changes: 0 additions & 140 deletions deployments/goerli/KernelFactory.json

This file was deleted.

201 changes: 0 additions & 201 deletions deployments/goerli/ZeroDevSessionKeyPlugin.json

This file was deleted.

135 changes: 0 additions & 135 deletions deployments/goerli/solcInputs/d5c4a417af7f759d03a3c7da438dc2be.json

This file was deleted.

1 change: 0 additions & 1 deletion deployments/mumbai/.chainId

This file was deleted.

156 changes: 0 additions & 156 deletions deployments/mumbai/KernelFactory.json

This file was deleted.

217 changes: 0 additions & 217 deletions deployments/mumbai/ZeroDevSessionKeyPlugin.json

This file was deleted.

135 changes: 0 additions & 135 deletions deployments/mumbai/solcInputs/d5c4a417af7f759d03a3c7da438dc2be.json

This file was deleted.

1 change: 0 additions & 1 deletion deployments/polygon/.chainId

This file was deleted.

156 changes: 0 additions & 156 deletions deployments/polygon/KernelFactory.json

This file was deleted.

217 changes: 0 additions & 217 deletions deployments/polygon/ZeroDevSessionKeyPlugin.json

This file was deleted.

135 changes: 0 additions & 135 deletions deployments/polygon/solcInputs/d5c4a417af7f759d03a3c7da438dc2be.json

This file was deleted.

2 changes: 1 addition & 1 deletion src/abstract/KernelStorage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ struct WalletKernelStorage {
}

/// @title Kernel Storage Contract
/// @author Your Name
/// @author taek<leekt216@gmail.com>
/// @notice This contract serves as the storage module for the Kernel contract.
/// @dev This contract should only be used by the main Kernel contract.
contract KernelStorage {
Expand Down
87 changes: 87 additions & 0 deletions src/factory/MultiECDSAKernelFactory.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

import "./KernelFactory.sol";
import "src/validator/MultiECDSAValidator.sol";
import "src/interfaces/IAddressBook.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract MultiECDSAKernelFactory is IAddressBook, Ownable {
KernelFactory public immutable singletonFactory;
MultiECDSAValidator public immutable validator;
IEntryPoint public immutable entryPoint;

address[] public owners;

constructor(KernelFactory _singletonFactory, MultiECDSAValidator _validator, IEntryPoint _entryPoint) {
singletonFactory = _singletonFactory;
validator = _validator;
entryPoint = _entryPoint;
}

function setOwners(address[] calldata _owners) external onlyOwner {
owners = _owners;
}

function getOwners() external view override returns(address[] memory) {
return owners;
}

function createAccount(uint256 _index) external returns (EIP1967Proxy proxy) {
bytes memory data = abi.encodePacked(address(this));
proxy = singletonFactory.createAccount(validator, data, _index);
}

function getAccountAddress(uint256 _index) public view returns (address) {
bytes memory data = abi.encodePacked(address(this));
return singletonFactory.getAccountAddress(validator, data, _index);
}

/**
* add a deposit for this factory, used for paying for transaction fees
*/
function deposit() public payable {
entryPoint.depositTo{value : msg.value}(address(this));
}

/**
* withdraw value from the deposit
* @param withdrawAddress target to send to
* @param amount to withdraw
*/
function withdrawTo(address payable withdrawAddress, uint256 amount) public onlyOwner {
entryPoint.withdrawTo(withdrawAddress, amount);
}
/**
* add stake for this factory.
* This method can also carry eth value to add to the current stake.
* @param unstakeDelaySec - the unstake delay for this factory. Can only be increased.
*/
function addStake(uint32 unstakeDelaySec) external payable onlyOwner {
entryPoint.addStake{value : msg.value}(unstakeDelaySec);
}

/**
* return current factory's deposit on the entryPoint.
*/
function getDeposit() public view returns (uint256) {
return entryPoint.balanceOf(address(this));
}

/**
* unlock the stake, in order to withdraw it.
* The factory can't serve requests once unlocked, until it calls addStake again
*/
function unlockStake() external onlyOwner {
entryPoint.unlockStake();
}

/**
* withdraw the entire factory's stake.
* stake must be unlocked first (and then wait for the unstakeDelay to be over)
* @param withdrawAddress the address to send withdrawn value.
*/
function withdrawStake(address payable withdrawAddress) external onlyOwner {
entryPoint.withdrawStake(withdrawAddress);
}
}
6 changes: 6 additions & 0 deletions src/interfaces/IAddressBook.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

interface IAddressBook {
function getOwners() external view returns(address[] memory);
}
16 changes: 11 additions & 5 deletions src/utils/KernelHelper.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,18 @@ function _intersectValidationData(uint256 a, uint256 b) pure returns (uint256 va
if (uint160(a) != uint160(b)) {
return SIG_VALIDATION_FAILED;
}
uint48 validAfterA = uint48(a >> 160);
uint48 validUntilA = uint48(a >> (48 + 160));
uint48 validAfterB = uint48(b >> 160);
uint48 validUntilB = uint48(b >> (48 + 160));
uint48 validAfterA = uint48(a >> (160 + 48));
uint48 validUntilA = uint48(a >> 160);
if(validUntilA == 0) {
validUntilA = type(uint48).max;
}
uint48 validAfterB = uint48(b >> (160 + 48));
uint48 validUntilB = uint48(b >> 160);
if(validUntilB == 0) {
validUntilB = type(uint48).max;
}

if (validAfterA < validAfterB) validAfterA = validAfterB;
if (validUntilA > validUntilB) validUntilA = validUntilB;
validationData = uint256(uint160(a)) | (uint256(validAfterA) << 160) | (uint256(validUntilA) << (48 + 160));
validationData = uint256(uint160(a)) | (uint256(validUntilA) << 160) | (uint256(validAfterA) << (48 + 160));
}
64 changes: 64 additions & 0 deletions src/validator/MultiECDSAValidator.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./IValidator.sol";
import "openzeppelin-contracts/contracts/utils/cryptography/EIP712.sol";
import "src/utils/KernelHelper.sol";
import "src/interfaces/IAddressBook.sol";

contract MultiECDSAValidator is IKernelValidator {
event OwnerAdded(address indexed kernel, address indexed owner);
event OwnerRemoved(address indexed kernel, address indexed owner);

mapping(address owner => mapping(address kernel => bool) hello) public isOwner;

function disable(bytes calldata _data) external override {
address[] memory owners = abi.decode(_data, (address[]));
for (uint256 i = 0; i < owners.length; i++) {
isOwner[owners[i]][msg.sender] = false;
emit OwnerRemoved(msg.sender, owners[i]);
}
}

function enable(bytes calldata _data) external override {
address addressBook = address(bytes20(_data));
address[] memory owners = IAddressBook(addressBook).getOwners();
for (uint256 i = 0; i < owners.length; i++) {
isOwner[owners[i]][msg.sender] = true;
emit OwnerAdded(msg.sender, owners[i]);
}
}

function validateUserOp(UserOperation calldata _userOp, bytes32 _userOpHash, uint256)
external
view
override
returns (uint256 validationData)
{
address signer = ECDSA.recover(_userOpHash, _userOp.signature);
if (isOwner[signer][msg.sender]) {
return 0;
}

bytes32 hash = ECDSA.toEthSignedMessageHash(_userOpHash);
signer = ECDSA.recover(hash, _userOp.signature);
if (!isOwner[signer][msg.sender]) {
return SIG_VALIDATION_FAILED;
}
return 0;
}

function validateSignature(bytes32 hash, bytes calldata signature) public view override returns (uint256) {
address signer = ECDSA.recover(hash, signature);
if(isOwner[signer][msg.sender]) {
return 0;
}
bytes32 ethHash = ECDSA.toEthSignedMessageHash(hash);
signer = ECDSA.recover(ethHash, signature);
if (!isOwner[signer][msg.sender]) {
return SIG_VALIDATION_FAILED;
}
return 0;
}
}
26 changes: 26 additions & 0 deletions test/foundry/KernelHelper.test.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
pragma solidity ^0.8.0;

import "forge-std/Test.sol";
import "src/utils/KernelHelper.sol";
import "account-abstraction/core/Helpers.sol";

contract KernelHelperTest is Test {
function testIntersect(uint48 validAfterA, uint48 validUntilA, uint48 validAfterB, uint48 validUntilB) public {
if(validUntilB == 0) {
validUntilB = 0xffffffffffff;
}
if(validUntilA == 0) {
validUntilA = 0xffffffffffff;
}
uint256 a = _packValidationData(false, validUntilA, validAfterA);
uint256 b = _packValidationData(false, validUntilB, validAfterB);
ValidationData memory c = _intersectTimeRange(a, b);

uint256 expected = _packValidationData(
false,
validUntilA < validUntilB ? validUntilA : validUntilB,
validAfterA > validAfterB ? validAfterA : validAfterB
);
assertEq(_packValidationData(c), expected);
}
}
Loading