Background
reputation.rs::rate_contribution updates a content author's contribution_quality running average based on a rating, but the function signature never captures who the rater is:
pub fn rate_contribution(env: &Env, user: Address, rating: u32) {
assert!(rating <= 5, "Rating must be between 0 and 5");
let mut reputation = get_reputation(env, &user);
...
}
The function's own doc comment admits the gap:
/// # Note
/// The caller is the rater, not the rated user. The `user` parameter is the
/// content author whose reputation is being updated. There is currently no
/// check preventing self-rating — this should be enforced at the call site.
///
/// # TODO
/// - Add a `rater: Address` parameter and enforce `rater != user` to prevent
/// self-rating abuse.
Because there's no rater parameter or require_auth-backed identity check at all in this function, any caller can inflate any user's contribution_quality — including their own — with no on-chain record of who submitted the rating and no self-rating guard. This is a direct reputation-manipulation vector, not just a missing nice-to-have.
Implementation Plan
- Add a
rater: Address parameter to rate_contribution, call rater.require_auth(), and reject the call (return a validation error) when rater == user.
- Audit call sites of
rate_contribution across the contract to pass the correct rater identity.
- Add tests: self-rating is rejected, unauthenticated rating is rejected, and a legitimate third-party rating still updates
contribution_quality correctly.
Acceptance Criteria
rate_contribution requires and authenticates a distinct rater address
- Self-rating (
rater == user) is rejected with a clear error
- Tests cover the rejection paths and the happy path
Background
reputation.rs::rate_contributionupdates a content author'scontribution_qualityrunning average based on a rating, but the function signature never captures who the rater is:The function's own doc comment admits the gap:
Because there's no
raterparameter orrequire_auth-backed identity check at all in this function, any caller can inflate any user'scontribution_quality— including their own — with no on-chain record of who submitted the rating and no self-rating guard. This is a direct reputation-manipulation vector, not just a missing nice-to-have.Implementation Plan
rater: Addressparameter torate_contribution, callrater.require_auth(), and reject the call (return a validation error) whenrater == user.rate_contributionacross the contract to pass the correct rater identity.contribution_qualitycorrectly.Acceptance Criteria
rate_contributionrequires and authenticates a distinctrateraddressrater == user) is rejected with a clear error