Skip to main content

CampaignAccessChecker

The CampaignAccessChecker is an abstract utility contract that provides campaign-specific access control. It extends admin access control with campaign owner permissions.

Overview

abstract contract CampaignAccessChecker {
ICampaignInfo internal INFO;

error AccessCheckerUnauthorized();

function __CampaignAccessChecker_init(address campaignInfo) internal;
modifier onlyProtocolAdmin();
modifier onlyPlatformAdmin(bytes32 platformHash);
modifier onlyCampaignOwner();
}

Purpose

  • Campaign Owner Access: Restricts functions to campaign owners
  • Protocol Admin Access: Restricts functions to protocol administrators
  • Platform Admin Access: Restricts functions to platform-specific admins
  • Campaign-Specific: Uses ICampaignInfo for campaign context
  • Reusable: Can be inherited by treasury and other campaign contracts

State Variables

VariableTypeDescription
INFOICampaignInfoReference to campaign info contract

Functions

Initialization

Init Campaign Access Checker

function __CampaignAccessChecker_init(address campaignInfo) internal;

Parameters:

  • campaignInfo: CampaignInfo contract address

Effects:

  • Stores reference to CampaignInfo
  • Enables access control checks

Called by:

  • BaseTreasury and derived contracts
  • Any contract needing campaign access control

Modifiers

Only Campaign Owner

modifier onlyCampaignOwner();

Effect:

  • Restricts function to campaign owner only
  • Reverts with AccessCheckerUnauthorized if caller is not owner

Usage:

function updateGoal(uint256 newGoal) external onlyCampaignOwner {
// Only campaign owner can call
}

Only Protocol Admin

modifier onlyProtocolAdmin();

Effect:

  • Restricts function to protocol admin only
  • Queries CampaignInfo for protocol admin address

Only Platform Admin

modifier onlyPlatformAdmin(bytes32 platformHash);

Parameters:

  • platformHash: Platform identifier

Effect:

  • Restricts function to specific platform's admin
  • Queries CampaignInfo for platform admin address

Errors

AccessCheckerUnauthorized

error AccessCheckerUnauthorized();

Thrown when: Caller is not authorized Conditions:

  • Not campaign owner when onlyCampaignOwner used
  • Not protocol admin when onlyProtocolAdmin used
  • Not platform admin when onlyPlatformAdmin used

Usage Examples

Inheriting the Contract

contract CampaignTreasury is CampaignAccessChecker {
function initialize(address campaignInfo) external {
__CampaignAccessChecker_init(campaignInfo);
}

function ownerFunction() external onlyCampaignOwner {
// Only campaign owner can call
}

function adminFunction() external onlyProtocolAdmin {
// Only protocol admin can call
}
}

Campaign Owner Functions

// Get campaign owner
const owner = await campaign.owner();
console.log('Campaign Owner:', owner);

// Call owner-only function
try {
await treasury.ownerFunction();
} catch (error) {
if (error.message.includes('AccessCheckerUnauthorized')) {
console.log('Not authorized - only owner can call');
}
}

Access Control Hierarchy

// Campaign owner has most permissions
await treasury.updateReward(rewardName, newReward); // ✓

// Protocol admin can pause/cancel
await campaign._pauseCampaign(reason); // ✓

// Platform admin manages platform settings
await treasury.updatePlatformSettings(); // ✓

Integration

With BaseTreasury

abstract contract BaseTreasury is CampaignAccessChecker {
function __BaseContract_init(address campaignInfo) internal {
__CampaignAccessChecker_init(campaignInfo);
}

// Campaign owner can withdraw
function withdraw() external onlyCampaignOwner {
// Withdrawal logic
}
}

With CampaignInfo

// CampaignInfo provides admin addresses
const protocolAdmin = await campaign.getProtocolAdminAddress();
const campaignOwner = await campaign.owner();

// Check if caller is authorized
const isOwner = msg.sender === campaignOwner;
const isProtocolAdmin = msg.sender === protocolAdmin;

Security Considerations

Campaign-Scoped Access

  • Access control is scoped to specific campaign
  • Campaign owner cannot access other campaigns
  • Platform admin scoped to their platform

Ownership Transfer

  • Campaign ownership can be transferred
  • New owner inherits all permissions
  • Previous owner loses access

Admin Separation

  • Protocol admin ≠ Platform admin ≠ Campaign owner
  • Clear separation of responsibilities
  • No overlap in permissions

Best Practices

Check Ownership Before Operations

// Frontend should check ownership
const isOwner = await campaign.owner() === currentUser;
if (!isOwner) {
disableOwnerFunctions();
}

Error Handling

try {
await treasury.ownerFunction();
} catch (error) {
if (error.message.includes('AccessCheckerUnauthorized')) {
showError('Only campaign owner can perform this action');
}
}

Next Steps