Skip to content
CommonLayer
Documentation menu
On this page

ADR-0045: The proposer never approves a reward, and a contribution is rewarded once

Status: Accepted (WP-70b; security review finding HIGH-1). Implemented in crates/commonlayer-funding/src/domain/reward.rs, src/service/rewards.rs and migrations/0020_funding_hardening.sql.

Context

Up to the single-approval limit (default $100) one approval funded a reward, and the proposer could give it. Nothing limited how many rewards one approved contribution could carry. The security review demonstrated that one maintainer could propose and approve repeated rewards for an account they control until the flexible pool was empty.

Decision

  • The proposer never counts as an approver, for every reward, whatever the number of required approvals (service check funding.self_approval and database trigger). The recipient never approves either.
  • A contribution carries at most one open or funded reward (partial unique index community_rewards_one_per_contribution; 409 funding.reward_exists).
  • Approvers are people, never service accounts (ADR-0035).
  • funding.reward_single_approval_max_minor remains the threshold above which two approvals (one by a project or platform admin) are needed; it is a runtime setting (ADR-0038).

Consequences

  • One person can no longer fund a reward alone. Two colluding project members can still reward a third account up to the single-approval limit, once per approved contribution (threat model O6). Lowering the limit, or a per-recipient cap, is a governance decision that has not been made.
  • RewardView carries the proposer, so the portal explains the rule before the API refuses (WP-70e).
  • Test: hardening::a_proposer_never_approves_and_a_contribution_is_rewarded_once.