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
Each is its own tool with its own use case, the first thing to get right is what each one 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_IDby reaching inside anexecute()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's plain deployment (no deterministic addresses or clones); the value is a single, audited, discoverable deployment path, one known factory address per network from which every condition instance can be traced via its events.
Using one
The flow is always the same:
- Deploy the condition (via the factory) with its initial configuration.
- Grant the permission with it attached:
dao.grantWithCondition(where, who, permissionId, condition), often withwho=ANY_ADDR. What that means depends on the condition:SafeOwnerConditionreadswho, soANY_ADDR+ it = "only Safe owners"; the selector conditions ignorewho, soANY_ADDR+ them = "anyone, but only these functions/actions" (they gate what, not who). - 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
- SelectorCondition, ExecuteSelectorCondition, SafeOwnerCondition — the three, each in depth.
- Permission conditions and RuledCondition — what a condition is, and how to build ones these fixed patterns don't cover.
- The permission system —
grantWithConditionandANY_ADDR.