Skip to content

Commit

Permalink
Merge branch 'develop' into feat/sma-392-session-keys-v2
Browse files Browse the repository at this point in the history
  • Loading branch information
ankurdubey521 authored Mar 2, 2024
2 parents f365630 + 21c9ff6 commit 82abd25
Show file tree
Hide file tree
Showing 45 changed files with 3,932 additions and 574 deletions.
4 changes: 3 additions & 1 deletion .solhintignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@ node_modules
artifacts
contracts/smart-account/test
contracts/smart-account/libs
contracts/smart-account/modules/AccountRecoveryModule.sol
contracts/smart-account/modules/AccountRecoveryModule.sol
contracts/smart-account/modules/SessionValidationModules/ABISessionValidationModule.sol
contracts/smart-account/test/mocks/MockProtocol.sol
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added audits/_Aggregated Audits Kawach - Final.pdf
Binary file not shown.
Binary file added audits/_Aggregated Audits Zellic - Final.pdf
Binary file not shown.
3 changes: 1 addition & 2 deletions contracts/smart-account/base/FallbackManager.sol
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity ^0.8.23;

import {SelfAuthorized} from "../common/SelfAuthorized.sol";
import {IFallbackManager} from "../interfaces/base/IFallbackManager.sol";

/**
* @title Fallback Manager - A contract that manages fallback calls made to the Smart Account
* @dev Fallback calls are handled by a `handler` contract that is stored at FALLBACK_HANDLER_STORAGE_SLOT
* fallback calls are not delegated to the `handler` so they can not directly change Smart Account storage
*/
abstract contract FallbackManager is SelfAuthorized, IFallbackManager {
abstract contract FallbackManager is IFallbackManager {
// keccak-256 hash of "fallback_manager.handler.address" subtracted by 1
bytes32 internal constant FALLBACK_HANDLER_STORAGE_SLOT =
0x6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d4;
Expand Down
3 changes: 1 addition & 2 deletions contracts/smart-account/base/ModuleManager.sol
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity ^0.8.23;

import {SelfAuthorized} from "../common/SelfAuthorized.sol";
import {Executor, Enum} from "./Executor.sol";
import {IModuleManager} from "../interfaces/base/IModuleManager.sol";

/**
* @title Module Manager - A contract that manages modules that can execute transactions
* on behalf of the Smart Account via this contract.
*/
abstract contract ModuleManager is SelfAuthorized, Executor, IModuleManager {
abstract contract ModuleManager is Executor, IModuleManager {
address internal constant SENTINEL_MODULES = address(0x1);
mapping(address => address) internal _modules;
uint256[24] private __gap;
Expand Down
1 change: 1 addition & 0 deletions contracts/smart-account/common/SignatureDecoder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ abstract contract SignatureDecoder {
// The signature format is a compact form of:
// {bytes32 r}{bytes32 s}{uint8 v}
// Compact means, uint8 is not padded to 32 bytes.
require(signature.length == 65, "Invalid signature length");

assembly {
r := mload(add(signature, 0x20))
Expand Down
39 changes: 39 additions & 0 deletions contracts/smart-account/interfaces/IAddressResolver.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,43 @@ interface IAddressResolver {
string factoryVersion;
uint256 deploymentIndex;
}

/**
* @dev Returns the addresses of all the smart accounts deployed by the EOA for any deployment index from 0 to _maxIndex.
* @param _eoa Address of the EOA.
* @param _maxIndex Maximum index to check.
* @notice This function is only for V1 Biconomy smart accounts.
*/
function resolveAddressesV1(
address _eoa,
uint8 _maxIndex
) external view returns (SmartAccountResult[] memory);

/**
* @dev Returns the addresses of all the smart accounts deployed by the EOA for any deployment index from 0 to _maxIndex.
* @param _eoa Address of the EOA.
* @param _maxIndex Maximum index to check.
* @notice This function is only for V1 and V2 Biconomy smart accounts.
* @notice For V2 smart accounts, the _moduleAddress and _moduleSetupData parameters are not used. It assumes ECDSA module.
*/
function resolveAddresses(
address _eoa,
uint8 _maxIndex
) external view returns (SmartAccountResult[] memory);

/**
* @dev Returns the addresses of all the smart accounts deployed by the EOA for any deployment index from 0 to _maxIndex.
* @param _eoa Address of the EOA.
* @param _maxIndex Maximum index to check.
* @param _moduleAddress Address of the auth module used to deploy the smart accounts.
* @param _moduleSetupData module setup data used to deploy the smart accounts.
* @notice This function is only for V1 and V2 Biconomy smart accounts.
* @notice For V2 smart accounts, the _moduleAddress and _moduleSetupData parameters are used. It can be any auth module (which uses ecda owner) used with the factory
*/
function resolveAddressesFlexibleForV2(
address _eoa,
uint8 _maxIndex,
address _moduleAddress, // V2 factory could use any auth module
bytes memory _moduleSetupData
) external view returns (SmartAccountResult[] memory);
}
11 changes: 0 additions & 11 deletions contracts/smart-account/interfaces/ISmartAccount.sol
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,6 @@ interface ISmartAccount is IBaseSmartAccount, IModuleManager {

error EntryPointCannotBeZero();

/**
* @notice Throws at mixedAuth when msg.sender is not an owner neither _self
* @param caller address that tried to call mixedAuth-protected method
*/
error MixedAuthFail(address caller);

/**
* @notice Throws if trying to change an owner of a SmartAccount to the zero address
*/
error OwnerCannotBeZero();

/**
* @notice Throws if zero address has been provided as Base Implementation address
*/
Expand Down
10 changes: 0 additions & 10 deletions contracts/smart-account/interfaces/base/IModuleManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,6 @@ interface IModuleManager {
Enum.Operation operation
);

/**
* @notice Throws when trying to initialize module manager that already been initialized
*/
error ModulesAlreadyInitialized();

/**
* @notice Throws when a delegatecall in course of module manager initialization has failed
*/
error ModulesSetupExecutionFailed();

/**
* @notice Throws when address(0) or SENTINEL_MODULES constant has been provided as a module address
* @param module Module address provided
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ interface IAccountRecoveryModule {
uint8 guardiansCount;
uint8 recoveryThreshold;
uint24 securityDelay;
uint8 recoveriesLeft;
}

/**
Expand All @@ -33,6 +34,20 @@ interface IAccountRecoveryModule {
uint48 requestTimestamp;
}

/**
* @dev Emitted when a recovery request is executed
* @param smartAccount address of the Smart Account
* @param recoverer module address that executed the recovery request
* @param recoveryCallValue value that was sent with the recovery request
* @param recoveryCallData calldata that was executed to recover the account
*/
event RecoveryExecuted(
address indexed smartAccount,
address recoverer,
uint256 recoveryCallValue,
bytes recoveryCallData
);

/**
* @dev Emitted when a recovery request is submitted
* @param smartAccount address of the Smart Account
Expand Down Expand Up @@ -94,9 +109,25 @@ interface IAccountRecoveryModule {
*/
event SecurityDelayChanged(
address indexed smartAccount,
uint48 securityDelay
uint24 securityDelay
);

/**
* @dev Emitted when recoveries left have been changed
* @param smartAccount address of the Smart Account
* @param recoveriesLeft new recoveries allowed
*/
event RecoveriesLeft(
address indexed smartAccount,
uint8 indexed recoveriesLeft
);

/**
* @dev Emitted when all the guardians and setting have been reset for the Smart Account
* @param smartAccount address of the Smart Account
*/
event ModuleReset(address indexed smartAccount);

/**
* @dev Thrown if trying to init module for the Smart Account
* but it has already been initialized
Expand Down Expand Up @@ -149,6 +180,11 @@ interface IAccountRecoveryModule {
*/
error ZeroThreshold();

/**
* @dev Thrown if trying to set zero allowed recoveries
*/
error ZeroAllowedRecoveries();

/**
* @dev Thrown if not enough or too many params provided
*/
Expand Down Expand Up @@ -182,6 +218,19 @@ interface IAccountRecoveryModule {
bytes32 requestCallDataHash
);

/**
* @dev Thrown when recovery execution failed
* @param smartAccount address of the Smart Account
* @param returnData error data
*/
error RecoveryExecutionFailed(address smartAccount, bytes returnData);

/**
* @dev Thrown if trying to reset module with an incomplete list of guardians
* @param guardiansLeft number of guardians that are still set for the Smart Account
*/
error ResetFailed(address smartAccount, uint256 guardiansLeft);

/**
* @dev Initializes the module for a Smart Account.
* Can only be used at a time of first enabling the module for a Smart Account.
Expand All @@ -197,7 +246,8 @@ interface IAccountRecoveryModule {
bytes32[] calldata guardians,
TimeFrame[] memory timeFrames,
uint8 recoveryThreshold,
uint24 securityDelay
uint24 securityDelay,
uint8 recoveriesAllowed
) external returns (address);

/**
Expand Down Expand Up @@ -287,6 +337,42 @@ interface IAccountRecoveryModule {
*/
function renounceRecoveryRequest() external;

/**
* @dev Resets the module for a Smart Account that calls the method
* Should be called by the Smart Account
* @param guardians the list of guardians that are enabled for the Smart Account
*/
function resetModuleForCaller(bytes32[] memory guardians) external;

/**
* @dev Changes how many allowed recoveries left for a Smart Account (msg.sender)
* Should be called by the Smart Account
* @param allowedRecoveries new security delay
*/
function setAllowedRecoveries(uint8 allowedRecoveries) external;

/**
* @dev Executes recovery request for a Smart Account (msg.sender)
* Should be called by the Smart Account
* SA.execute => AccRecovery.executeRecovery
* Decrements recoveries left, and if 0 left, no userOps will be validated by this module
* It forces user to perform an explicit action:
* - If user wants same guardians to be able to recover the account again,
* they have to call setAllowedRecoveries() => NOT RECOMMENDED
* - If user wants to change guardians, they have to
* -- remove/replace guardians + adjust threshold + setAllowedRecoveries()
* or
* -- clear all guardians + re-init the module => RECOMMENDED
* @param to destination address
* @param value value to send
* @param data callData to execute
*/
function executeRecovery(
address to,
uint256 value,
bytes calldata data
) external;

/**
* @dev Returns guardian validity timeframes for the Smart Account
* @param guardian guardian to get params for
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;

import {PassKeyId} from "../../modules/PasskeyValidationModules/Secp256r1.sol";

/**
* @title Passkey ownership Authorization module for Biconomy Smart Accounts.
* @dev Compatible with Biconomy Modular Interface v 0.2
Expand All @@ -27,9 +29,40 @@ interface IPasskeyRegistryModule {
string calldata _keyId
) external returns (address);

/**
* @dev Validates an EIP-1271 signature
* @dev Appends Smart Account address to the hash to avoid replay attacks
* @param signedDataHash hash of the data
* @param moduleSignature Signature to be validated.
* @param smartAccount expected signer Smart Account address.
* @return EIP1271_MAGIC_VALUE if signature is valid, 0xffffffff otherwise.
*/
function isValidSignatureForAddress(
bytes32 signedDataHash,
bytes memory moduleSignature,
address smartAccount
) external view returns (bytes4);

/**
* @dev Same as isValidSignatureForAddress but does not append Smart Account address to the hash
* @dev Expects the data Hash to already include smart account address information
* @param signedDataHash hash of the data which includes smart account address
* @param moduleSignature Signature to be validated.
* @param smartAccount expected signer Smart Account address.
* @return EIP1271_MAGIC_VALUE if signature is valid, 0xffffffff otherwise.
*/
function isValidSignatureForAddressUnsafe(
bytes32 signedDataHash,
bytes memory moduleSignature,
address smartAccount
) external view returns (bytes4);

/**
* @dev Returns the owner of the Smart Account.
* @param smartAccount Smart Account address.
* @return PassKeyId The owner key of the Smart Account.
*/
function getOwner(
address smartAccount
) external view returns (PassKeyId memory);
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ abstract contract ISessionValidationModule {
* @param funcCallData the data for the call.
* is parsed inside the Session Validation Module (SVM)
* @param sessionKeyData SessionKey data, that describes sessionKey permissions
* @param callSpecificData additional data for the call, that is parsed inside the SVM
* @return the Session Key address (public key) that was used to sign the call
*/
function validateSessionParams(
address destinationContract,
Expand Down
7 changes: 2 additions & 5 deletions contracts/smart-account/libs/LibAddress.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,9 @@ library LibAddress {
* @dev This contract will return false if called within the constructor of
* a contract's deployment, as the code is not yet stored on-chain.
*/
function isContract(address account) internal view returns (bool) {
uint256 csize;

function isContract(address account) internal view returns (bool res) {
assembly {
csize := extcodesize(account)
res := gt(extcodesize(account), 0)
}
return csize != 0;
}
}
Loading

0 comments on commit 82abd25

Please sign in to comment.