Skip to content

Condition Library ​

The Condition Library is a set of ready-made permission conditions for common gating patterns, so a DAO doesn't have to write and audit a bespoke condition contract every time it wants to constrain a permission. You deploy one (via the factory) and attach it with grantWithCondition; from then on the permission is allowed only when the condition says so. All three are audited.

The three conditions ​

Choose a condition by what it inspects:

  • SelectorCondition — allow only a set of function selectors on the direct call being authorized. "This permission, but only to call functions X and Y."
  • ExecuteSelectorCondition — scope the DAO's EXECUTE_PERMISSION_ID by reaching inside an execute() batch and allow-listing each action's (target, selector). "This plugin may make the DAO execute, but only these calls."
  • SafeOwnerCondition — allow only the current owners of a given Safe, a live bridge from a Safe's membership to a DAO permission.

SelectorCondition gates the direct call's own selector; ExecuteSelectorCondition gates the selectors of the actions inside an execute(). Pick by which call the permission you're guarding actually receives.

The ConditionFactory ​

ConditionFactory deploys instances of the three conditions (deploySelectorCondition, deployExecuteSelectorCondition, deploySafeOwnerCondition) and emits an event for each. It uses plain deployment (no deterministic addresses or clones). This provides a single, audited deployment path: one known factory address per network, with events that let you find and trace every condition instance.

Using one ​

The flow is always the same:

  1. Deploy the condition (via the factory) with its initial configuration.
  2. Grant the permission with it attached: dao.grantWithCondition(where, who, permissionId, condition), often with who = ANY_ADDR. What that means depends on the condition: SafeOwnerCondition reads who, so ANY_ADDR + it = "only Safe owners"; the selector conditions ignore who, so ANY_ADDR + them = "anyone, but only these functions/actions" (they gate what, not who).
  3. Manage the allow-list over time (for the selector conditions) via their MANAGE_SELECTORS_PERMISSION_ID, typically held by the DAO.

Keep in mind ​

  • A selector is not its arguments. These conditions allow-list which function/action may run, not with what arguments; for argument-level rules, write a bespoke condition or use RuledCondition.
  • All conditions fail closed. A malformed call, or a Safe that doesn't answer, resolves to "denied", never a surfaced error.

See also ​