> ## Documentation Index
> Fetch the complete documentation index at: https://docs.oaknetwork.org/llms.txt
> Use this file to discover all available pages before exploring further.

# CampaignAccessChecker

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

## Overview

```solidity theme={null}
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

| Variable | Type            | Description                         |
| -------- | --------------- | ----------------------------------- |
| `INFO`   | `ICampaignInfo` | Reference to campaign info contract |

## Functions

### Initialization

#### Init Campaign Access Checker

```solidity theme={null}
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

```solidity theme={null}
modifier onlyCampaignOwner();
```

**Effect:**

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

**Usage:**

```solidity theme={null}
function updateGoal(uint256 newGoal) external onlyCampaignOwner {
    // Only campaign owner can call
}
```

#### Only Protocol Admin

```solidity theme={null}
modifier onlyProtocolAdmin();
```

**Effect:**

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

#### Only Platform Admin

```solidity theme={null}
modifier onlyPlatformAdmin(bytes32 platformHash);
```

**Parameters:**

* `platformHash`: Platform identifier

**Effect:**

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

## Errors

### AccessCheckerUnauthorized

```solidity theme={null}
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

```solidity theme={null}
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

```javascript theme={null}
// 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

```javascript theme={null}
// 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

```solidity theme={null}
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

```javascript theme={null}
// 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

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

### Error Handling

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

## Next Steps

* [AdminAccessChecker](/contracts/admin-access-checker) - Protocol-level access control
* [PausableCancellable](/contracts/pausable-cancellable) - State management utilities
* [BaseTreasury](/contracts/base-treasury) - Uses campaign access control
