Permissive

By Permissive Labs

Documentation

Supported accounts

Future accounts supported

Deployments

FeeManager impl: 0x84f066969d27c5A41F497f797B331C1c6973a91e
PermissionRegistry impl: 0xb8228206b5ABE05a41639669f33D2a87B9894803
PermissionExecutor impl: 0x36118380bA22ebEd531FBC1Cbec107a8b812F59a
PermissionVerifier impl: 0x54580F79b56DFf099bB6d7CAfB38D5E05F007bFD
FeeManager: 0x4cdb220B27b86161a2e82e2A29A45A37CF24765F
PermissionRegistry: 0xEa4c56AeEf09fdC5a2011faa29226877B9919CEC
PermissionExecutor: 0x878f23FD2489E5B0e0D28EA475852c09183FfC1A
PermissionVerifier: 0x141A637e4516A7B03b6B7530d6498aC9A6986028
===================================================================
ZerodevValidator impl: 0x504b2220f329d274c639e7f73243088c93f4f834
ZerodevValidator: 0xd464Fc6C1Fc5855B2F86A9a154Ee2C23b8C5b299
-------------------------------------------------------------------
BiconomyModule impl: 0x4Ba320EA20d862A773107fcf471F6702931D2366
BiconomyModule: 0x40292C57F0D74E3078211D53C5B1EB512B4d9bC7
-------------------------------------------------------------------
SafeModule impl: 0xe915390C3E2F72687a954364b5BA6362Ef12E33f
SafeModule: 0x84C01a3Ad6362622d88233254ED06F54B445437b
-------------------------------------------------------------------
6900 OperationValidator impl: 0x066811D72BA155F154C245278E1432b1BE40A55B
6900 OperationValidator: 0x0D6d6FD586524007F09A7B3cB4a2873ED940a308
-------------------------------------------------------------------
Saf4337Module impl: 0xc83F407Bc8456025CE674EEE1894A709dFb92f97
Safe4337Module: 0x389C72e17d0C885D8f80462f32A8A8a44680Bad3
-------------------------------------------------------------------

Contents

FeeManager

Git Source

Inherits: Ownable

Author: Flydexo - @Flydex0

Permissive core contracts that determines the percent of gas fee that is collected by Permissive and collects the fees

State Variables

fee

100 basis point, 100 = 1%, 2000 = 20%

uint24 public fee = 2000;

initialized

needs initialization because owner is set as the CREATE2 deployer in the constructor

bool initialized;

Functions

initialize

initialize - Initialization function to set the real owner, see CREATE2

function initialize(address owner) external;

Parameters

NameTypeDescription
owneraddressThe future owner of the FeeManager

setFee

setFee - Sets the Permissive fee, only callable by the owner

function setFee(uint24 _fee) external;

Parameters

NameTypeDescription
_feeuint24The new fee (100 basis point)

pay

Function called to pay the FeeManager

used a function to avoid gas details in the core contracts

function pay() external payable;

Events

FeePaid

FeePaid - Emitted when the Permissive fee is collected

event FeePaid(address indexed from, uint256 amount);

PermissionExecutor

Git Source

Inherits: IPermissionExecutor

see {IPermissionExecutor}

State Variables

feeManager

FeeManager private immutable feeManager;

Functions

constructor

constructor(FeeManager _feeManager);

execute

function execute(
    address dest,
    uint256 value,
    bytes calldata func,
    Permission calldata permission,
    bytes32[] calldata,
    uint256 gasFee
) external;

PermissionRegistry

Git Source

Inherits: IPermissionRegistry

see {IPermissionRegistry}

State Variables

operatorPermissions

mapping(address sender => mapping(address operator => bytes32 permHash)) public operatorPermissions;

remainingPermUsage

mapping(address sender => mapping(bytes32 permHash => uint256 remainingUsage)) public remainingPermUsage;

Functions

constructor

constructor();

setRemainingPermUsage

function setRemainingPermUsage(bytes32 permHash, uint256 remainingUsage) external;

setOperatorPermissions

function setOperatorPermissions(address operator, bytes32 root) external;

PermissionVerifier

Git Source

Inherits: IPermissionVerifier

see {IPermissionVerifier}

State Variables

permissionRegistry

PermissionRegistry immutable permissionRegistry;

Functions

constructor

constructor(PermissionRegistry registry);

verify

function verify(UserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds)
    external
    returns (uint256 validationData);

computeGasFee

function computeGasFee(UserOperation memory userOp) public pure returns (uint256 fee);

_validateFee

function _validateFee(UserOperation calldata userOp, uint256 providedFee) internal pure;

_validationData

function _validationData(UserOperation calldata userOp, bytes32 userOpHash, Permission memory permission)
    internal
    view
    returns (uint256 validationData);

_validateData

function _validateData(
    UserOperation calldata userOp,
    bytes32 userOpHash,
    uint256 missingAccountFunds,
    Permission memory permission
) internal;

_validatePermission

function _validatePermission(
    address to,
    uint256 value,
    bytes memory callData,
    UserOperation calldata userOp,
    Permission memory permission,
    bytes32 permHash
) internal;

_validateMerklePermission

function _validateMerklePermission(Permission memory permission, bytes32[] memory proof, bytes32 permHash)
    internal
    view;

Constants

Git Source

SIG_VALIDATION_FAILED

uint256 constant SIG_VALIDATION_FAILED = 1;

Contents

Contents

OperationValidator

Git Source

State Variables

permissionVerifier

PermissionVerifier immutable permissionVerifier;

Functions

constructor

constructor(PermissionVerifier _verifier);

validateUserOp

function validateUserOp(UserOperation calldata userOp, bytes32 userOpHash) external returns (uint256 validationData);

Contents

BiconomyAuthorizationModule

Git Source

Inherits: BaseAuthorizationModule

State Variables

permissionVerifier

PermissionVerifier immutable permissionVerifier;

permissionExecutor

PermissionExecutor immutable permissionExecutor;

Functions

constructor

constructor(PermissionVerifier _verifier, PermissionExecutor _executor);

validateUserOp

function validateUserOp(UserOperation memory userOp, bytes32 userOpHash) external returns (uint256 validationData);

execute

function execute(
    address dest,
    uint256 value,
    bytes memory func,
    Permission calldata permission,
    bytes32[] calldata proof,
    uint256 gasFee
) external;

isValidSignature

function isValidSignature(bytes32 _dataHash, bytes memory _signature) public view override returns (bytes4);

Contents

ISafe

Git Source

Functions

execTransactionFromModuleReturnData

function execTransactionFromModuleReturnData(address to, uint256 value, bytes memory data, Operation operation)
    external
    returns (bool success, bytes memory returnData);

Enums

Operation

enum Operation {
    Call,
    DelegateCall
}

Safe4337Module

Git Source

Inherits: SafeStorage

State Variables

myAddress

address immutable myAddress;

entryPoint

IEntryPoint immutable entryPoint;

permissionVerifier

PermissionVerifier immutable permissionVerifier;

permissionExecutor

PermissionExecutor immutable permissionExecutor;

SENTINEL_MODULES

address internal constant SENTINEL_MODULES = address(0x1);

Functions

constructor

constructor(IEntryPoint _entryPoint, PermissionVerifier verifier, PermissionExecutor executor);

validateUserOp

function validateUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds)
    external
    returns (uint256 validationData);

execute

function execute(
    address dest,
    uint256 value,
    bytes memory func,
    Permission calldata permission,
    bytes32[] calldata proof,
    uint256 gasFee
) external;

enableMyself

function enableMyself() public;

_payPrefund

function _payPrefund(uint256 missingAccountFunds) internal;

receive

receive() external payable;

_onlySafe

function _onlySafe() internal view;

Events

OperatorMutated

event OperatorMutated(address indexed operator, bytes32 indexed oldPermissions, bytes32 indexed newPermissions);

PermissionVerified

event PermissionVerified(bytes32 indexed userOpHash, UserOperation userOp);

PermissionUsed

event PermissionUsed(
    bytes32 indexed permHash, address dest, uint256 value, bytes func, Permission permission, uint256 gasFee
);

NewSafe

event NewSafe(address safe);

SafeModule

Git Source

State Variables

safe

ISafe public safe;

entryPoint

IEntryPoint immutable entryPoint;

permissionVerifier

PermissionVerifier immutable permissionVerifier;

permissionExecutor

PermissionExecutor immutable permissionExecutor;

Functions

constructor

constructor(IEntryPoint _entryPoint, PermissionVerifier _verifier, PermissionExecutor _executor);

setSafe

function setSafe(address _safe) external;

validateUserOp

function validateUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds)
    external
    returns (uint256 validationData);

execute

function execute(
    address dest,
    uint256 value,
    bytes memory func,
    Permission calldata permission,
    bytes32[] calldata proof,
    uint256 gasFee
) external;

executeAsModule

function executeAsModule(address dest, uint256 value, bytes memory data) external;

_requireFromEntryPointOrOwner

function _requireFromEntryPointOrOwner() internal view;

_payPrefund

function _payPrefund(uint256 missingAccountFunds) internal;

receive

receive() external payable;

_onlySafe

function _onlySafe() internal view;

Events

OperatorMutated

event OperatorMutated(address indexed operator, bytes32 indexed oldPermissions, bytes32 indexed newPermissions);

PermissionVerified

event PermissionVerified(bytes32 indexed userOpHash, UserOperation userOp);

PermissionUsed

event PermissionUsed(
    bytes32 indexed permHash, address dest, uint256 value, bytes func, Permission permission, uint256 gasFee
);

NewSafe

event NewSafe(address safe);

Contents

ZerodevValidator

Git Source

Inherits: IKernelValidator

State Variables

permissionVerifier

PermissionVerifier immutable permissionVerifier;

Functions

constructor

constructor(PermissionVerifier verifier);

enable

function enable(bytes calldata) external override;

disable

function disable(bytes calldata) external pure override;

validateUserOp

function validateUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds)
    external
    override
    returns (uint256 validationData);

validateSignature

function validateSignature(bytes32 hash, bytes calldata signature) external view override returns (uint256);

Contents

IDataValidator

Git Source

Author: Flydexo - @Flydex0

This can be used for example to track the amount of granted ERC20 spent / swapped, etc...

The DataValidator contract must respect ERC-4337 storage rules. That means the only storage accessible must have the userOp.sender as key.

see https://eips.ethereum.org/EIPS/eip-4337#simulation

Functions

isValidData

isValidData is called in the validateUserOp function of the PermissionVerifier contract

userOp is formatted as integration agnostic, that means that if the SA (eg. Zerodev) requires a special field in the signature to determine which plugin to use, it is removed. Then the PermissionVerifier is called.

function isValidData(UserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds)
    external
    returns (bool success);

Parameters

NameTypeDescription
userOpUserOperationThe userOp
userOpHashbytes32The userOp hash
missingAccountFundsuint256The funds the sender needs to pay to the EntryPoint

Returns

NameTypeDescription
successboolCan revert to add additional logs and returns true if the userOp is considered valid

IPermissionExecutor

Git Source

Author: Flydexo - @Flydex0

The core contract in change or executing the userOperation after paying the FeeManager and transforming the AllowanceCalldata to ABI

Functions

execute

Execute a permissioned userOperation

function execute(
    address dest,
    uint256 value,
    bytes calldata func,
    Permission calldata permission,
    bytes32[] calldata proof,
    uint256 gasFee
) external;

Parameters

NameTypeDescription
destaddressThe called contract
valueuint256The msg.value
funcbytesThe AllowanceCalldata used to call the contract
permissionPermissionThe permission object
proofbytes32[]
gasFeeuint256The fee for the userOperation (used to compute the Permissive fee)

Events

PermissionUsed

PermissionUsed - When a permissioned userOperation passed with success

event PermissionUsed(
    bytes32 indexed permHash, address dest, uint256 value, bytes func, Permission permission, uint256 gasFee
);

IPermissionRegistry

Git Source

Author: Flydexo - @Flydex0

PermissionRegistry stores the permissions of an operator on an account and the remaining usages of a permission on an account.

Functions

operatorPermissions

operatorPermissions - Getter for the granted permissions of an operator on an account

function operatorPermissions(address sender, address operator) external view returns (bytes32 permHash);

Parameters

NameTypeDescription
senderaddressThe account address
operatoraddressThe operator address

remainingPermUsage

remainingPermUsage - Getter for the remaining usage of a permission on an account (usage + 1)

function remainingPermUsage(address sender, bytes32 permHash) external view returns (uint256 remainingUsage);

Parameters

NameTypeDescription
senderaddressThe account address
permHashbytes32The permission hash

setOperatorPermissions

setOperatorPermissions - Setter for the granted permissions of an operator on an account. Can only be called by the account modifying it's own operator permissions.

function setOperatorPermissions(address operator, bytes32 root) external;

Parameters

NameTypeDescription
operatoraddressThe operator address
rootbytes32The permissions merkle root

setRemainingPermUsage

setRemainingPermUsage - Setter for the remaining usage of a permission on an account. Can only be called by the account modifying it's own usage

function setRemainingPermUsage(bytes32 permHash, uint256 remainingUsage) external;

Parameters

NameTypeDescription
permHashbytes32The permission hash
remainingUsageuint256The permission remaining usage (usage + 1)

Events

OperatorMutated

OperatorMutated - Emitted when the granted permisssions for an operator on an account change

event OperatorMutated(address indexed operator, bytes32 indexed oldPermissions, bytes32 indexed newPermissions);

IPermissionVerifier

Git Source

Author: Flydexo - @Flydex0

Contract only callable with delegatecall by the account itself or it's module or plugin

Functions

verify

verify - Function that make all the Permissive related checks on the userOperation.

For validationData specs see see https://eips.ethereum.org/EIPS/eip-4337#definitions

function verify(UserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds)
    external
    returns (uint256 validationData);

Parameters

NameTypeDescription
userOpUserOperationThe userOperation
userOpHashbytes32The userOperation hash
missingAccountFundsuint256The funds the sender needs to pay to the EntryPoint

Returns

NameTypeDescription
validationDatauint256The validation data that signals are valid / invalid signature and the timespan of the permission

computeGasFee

computeGasFee - Function called to compute the gasFee of the userOperation depending on all the gas parameters of the operation.

Use this function to determine the fee in the execute function

function computeGasFee(UserOperation memory userOp) external pure returns (uint256 fee);

Parameters

NameTypeDescription
userOpUserOperationThe userOperation

Events

PermissionVerified

PermissionVerified - Emitted when a permission is successfully verified

event PermissionVerified(bytes32 indexed userOpHash, UserOperation userOp);

Contents

AllowanceCalldata

Git Source

Author: Flydexo - @Flydex0

Library in charge of verifying that the calldata is valid corresponding the the allowed calldata conditions.

Functions

isAllowedCalldata

isAllowedCalldata - checks the calldata is valid corresponding the the allowed calldata conditions.

To check the msg.value field, the first arg of data must be equal to msg.value and the first arg of allowed calldata must set rules for the value

function isAllowedCalldata(bytes memory allowed, bytes memory data, uint256 value) internal view returns (bool isOk);

Parameters

NameTypeDescription
allowedbytesThe RLP encoded Allowed calldata
databytesThe RLP encodedx calldata
valueuint256The msg.value

Returns

NameTypeDescription
isOkboolIn case of success returns true, otherwise fails or reverts

RLPtoABI

RLPToABI - Transform the RLP encoded calldata into ABI

the RLP calldata must already be ABI compatible when all arguments are concatenated

If you have n arguments to verify (including value)

You need to have n arguments in the RLP calldata

And when concatenated, the arguments must be ABI compatible

So if you have 1 argument to check (ignore value for the example)

it must be RLP.encode([abi.encode(argument)])

function RLPtoABI(bytes memory data) internal pure returns (bytes memory abiEncoded);

Parameters

NameTypeDescription
databytesthe RLP encoded calldata

Returns

NameTypeDescription
abiEncodedbytesThe result ABI encoded, is valid calldata

_validateArguments

_validateArguments - Core function of the AllowanceCalldata library, checks if arguments respect the allowedArguments conditions

isOr is used to do the minimum checks

in case of AND = a single false result breaks

in case of OR = a single true result breaks

function _validateArguments(
    RLPReader.RLPItem[] memory allowedArguments,
    RLPReader.RLPItem[] memory arguments,
    bool isOr
) internal view returns (bool canPass);

Parameters

NameTypeDescription
allowedArgumentsRLPReader.RLPItem[]The allowed arguments
argumentsRLPReader.RLPItem[]The arguments
isOrboolIs the current loop in a or condition

_unsafe_inc

optimized incrementation

function _unsafe_inc(uint256 i) private pure returns (uint256);

_fillArray

_fillArray - Creates a new array filled with the same item

function _fillArray(RLPReader.RLPItem[] memory arguments, uint256 index, uint256 length)
    internal
    pure
    returns (RLPReader.RLPItem[] memory newArguments);

Parameters

NameTypeDescription
argumentsRLPReader.RLPItem[]Array of arguments to take the item from
indexuint256The index of the item to fill with
lengthuint256The length of the new filled array

Constants

Git Source

ANY

uint256 constant ANY = 0;

NE

uint256 constant NE = 1;

EQ

uint256 constant EQ = 2;

GT

uint256 constant GT = 3;

LT

uint256 constant LT = 4;

AND

uint256 constant AND = 5;

OR

uint256 constant OR = 6;

Permission

Git Source

Author: Flydexo - @Flydex0

A permission is made for a specific function of a specific contract

1 operator = 1 permission set

1 permission set = infinite permissions

struct Permission {
    address operator;
    address to;
    bytes4 selector;
    bytes allowed_arguments;
    address paymaster;
    uint48 validUntil;
    uint48 validAfter;
    uint256 maxUsage;
    address dataValidator;
}

PermissionLib

Git Source

Author: Flydexo - @Flydex0

Library used to hash the Permission struct

Functions

hash

function hash(Permission memory permission) internal pure returns (bytes32 permHash);