> For the complete documentation index, see [llms.txt](https://world-book.gitbook.io/worldbook/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://world-book.gitbook.io/worldbook/technical-documentation/manager-contract.md).

# Manager Contract

The `Manager.sol` contract serves as the central coordination layer for the entire Worldbook ecosystem. It implements sophisticated access control, fee management, orderbook registration, and emergency response capabilities.

## Contract Overview

* **File**: `Manager.sol`
* **Size**: \~900 lines of code
* **Role**: Central coordination and control layer
* **Security**: Role-based access control with inheritance hierarchy

## Key Responsibilities

### 1. Access Control System

* **Role Management**: Hierarchical role system with inheritance
* **Permission Delegation**: Centralized permission checking for all OrderBooks
* **Emergency Controls**: Pause/unpause capabilities across the entire system

### 2. OrderBook Registry

* **Registration**: Validates and registers new OrderBook contracts
* **Bytecode Verification**: Ensures only legitimate contracts are registered
* **Pair Management**: Manages unique trading pairs and prevents duplicates

### 3. Fee Management

* **4-Tier Fee System**: Sophisticated fee structure with customization options
* **Maker Rebates**: Support for negative maker fees (rebates)
* **Fee Collection**: Centralized fee collection and distribution
* **User Discounts**: Percentage and absolute discount mechanisms

### 4. Token Whitelist and Standard Token Registry

* **Quote Token Control**: Manages which tokens can be used as quote assets
* **Minimum Amounts**: Sets minimum order sizes per token
* **Standard Tokens**: Registry for exact-transfer ERC-20s and optional enforcement for BASE on registration
* **Dynamic Management**: Add/remove tokens from whitelist

### 5. Self-Trade Prevention (STP)

* **User STP Modes**: Configurable self-trade prevention behavior
* **Three Modes**: NONE, EXPIRE\_MAKER, and SKIP
* **Default Mode**: EXPIRE\_MAKER for new users

## Access Control Architecture

### Role Hierarchy

```solidity
DEFAULT_ADMIN_ROLE (Role Management Only)
    │
    ▼
ADMIN_ROLE (Full Operational Control + PAUSER privileges)
    │
    ▼
PAUSER_ROLE (Emergency Response)
```

**Important:** ADMIN\_ROLE automatically has PAUSER\_ROLE privileges through the `hasOrderBookRole` function implementation. The `Manager` contract itself also holds `PAUSER_ROLE` to perform batch pause/unpause.

### Role Definitions

```solidity
// Role constants
bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");
bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");
bytes32 public constant FACTORY_ROLE = keccak256("FACTORY_ROLE");

// Role checking function used by all OrderBooks with inheritance
function hasOrderBookRole(bytes32 role, address account) external view returns (bool) {
    // Direct role check
    if (hasRole(role, account)) {
        return true;
    }
    
    // Implement role inheritance: ADMIN_ROLE includes PAUSER_ROLE privileges
    if (role == PAUSER_ROLE && hasRole(ADMIN_ROLE, account)) {
        return true;
    }
    
    return false;
}
```

### Role Capabilities

**DEFAULT\_ADMIN\_ROLE:**

* Grant and revoke ADMIN\_ROLE
* Grant and revoke PAUSER\_ROLE
* Role management only (no operational privileges)

**ADMIN\_ROLE:**

* All operational functions
* Fee management
* OrderBook registration control
* Token whitelist management
* System configuration
* Inherits PAUSER\_ROLE privileges

**PAUSER\_ROLE:**

* Emergency pause/unpause operations
* Community managers and emergency responders
* Limited to emergency response only

## Fee Management System

### 4-Tier Fee Structure

Worldbook implements a sophisticated fee system with four layers:

#### Layer 1: Default Fees

```solidity
int256 public override makerFee;    // Can be negative for rebates
uint256 public override takerFee;   // Always non-negative
```

**Maker Rebates:**

* Maker fees can be negative to incentivize liquidity provision
* Rebates are funded from taker fees
* Maximum rebate: 0.05% (500 basis points, different from max fee of 0.5%)

#### Layer 2: OrderBook-Specific Overrides

```solidity
mapping(address => int256) public orderbookMakerFeeOverrides;
mapping(address => uint256) public orderbookTakerFeeOverrides;
```

#### Layer 3: User Percentage Discounts

```solidity
mapping(address => uint256) public userMakerFeeDiscountFactor;
mapping(address => uint256) public userTakerFeeDiscountFactor;
```

#### Layer 4: User Absolute Discounts

```solidity
mapping(address => uint256) public userMakerFeeDiscountAbs;
mapping(address => uint256) public userTakerFeeDiscountAbs;
```

### Fee Calculation Logic

```solidity
// Fee calculation with rebate support
function _calculateMakerFeeRate(address orderbook, address user) internal view returns (int256) {
    // Step 1: Get base rate (orderbook override OR default)
    int256 baseRate = orderbookMakerFeeOverrides[orderbook] != 0 ? 
                      orderbookMakerFeeOverrides[orderbook] : 
                      makerFee;

    // Step 2: Apply percentage discount ONLY if base rate is positive
    int256 afterPercentageDiscount = baseRate;
    if (baseRate > 0) {
        uint256 discountFactor = userMakerFeeDiscountFactor[user];
        if (discountFactor > 0 && discountFactor < 10000000) {
            afterPercentageDiscount = int256(uint256(baseRate) * discountFactor / FEE_DENOM);
        }
    }

    // Step 3: Apply absolute discount (can turn positive fees into rebates)
    uint256 absoluteDiscount = userMakerFeeDiscountAbs[user];
    return afterPercentageDiscount - int256(absoluteDiscount);
}
```

### Fee Collection

```solidity
address public override feeCollector;

function setFeeCollector(address _feeCollector) external override onlyAdminRole {
    if (_feeCollector == address(0)) revert Manager__InvalidFeeCollector();
    if (_feeCollector != feeCollector) {
        address oldFeeCollector = feeCollector;
        feeCollector = _feeCollector;
        emit FeeCollectorUpdated(oldFeeCollector, _feeCollector);
    }
}
```

## OrderBook Registration System

### Registration Process

```solidity
function registerOrderBook(
    address baseToken,
    address quoteToken,
    address orderBookAddress
) external payable virtual override
```

**Validation Steps:**

1. **Access Control**: If `allowAnyoneRegisterOrderBook` is false, only ADMIN\_ROLE may register. Callers with `FACTORY_ROLE` bypass bytecode checks.
2. **Registration Fee**: Require payment of `registrationFee` (admins exempt)
3. **Input Validation**: Verify token addresses and uniqueness
4. **Quote Token Check**: Ensure quote token is whitelisted (if active)
5. **Bytecode Verification**: Verify contract matches expected bytecode (exact or normalized hash)
6. **Parameter Verification**: Validate OrderBook configuration
7. **Storage**: Store registration and emit event
8. **Fee Transfer**: Send fee to collector, refund excess

### Registration Fee System

The Manager supports optional registration fees for OrderBook creation:

```solidity
uint256 public registrationFee = 0.001 ether; // Default: 0.001 ETH

function setRegistrationFee(uint256 _fee) external onlyAdminRole
```

**Key Features:**

* Admin role is exempt from registration fees
* Fees are sent directly to the fee collector
* Excess payment is automatically refunded
* Can be set to 0 to disable fees
* Prevents spam OrderBook creation

### Bytecode Verification

```solidity
bytes32 public override expectedBytecodeHash;

function setExpectedBytecodeHash(bytes32 _newHash) external override onlyAdminRole {
    if (_newHash == bytes32(0)) revert Manager__ZeroBytecodeHash();
    if (_newHash != expectedBytecodeHash) {
        bytes32 oldHash = expectedBytecodeHash;
        expectedBytecodeHash = _newHash;
        emit ExpectedBytecodeHashSet(oldHash, _newHash);
    }
}
```

**Security Benefits:**

* Prevents registration of malicious contracts
* Ensures only approved OrderBook versions are used
* Maintains system integrity and user trust

#### Normalized Bytecode Verification

To support OrderBooks with different immutable constructor parameters (manager/base/quote addresses, decimals, scales), the Manager can verify a canonical normalized runtime hash:

```solidity
bytes32 public override expectedNormalizedBytecodeHash;

function setExpectedNormalizedBytecodeHash(bytes32 _newHash) external onlyAdminRole {
    if (_newHash == bytes32(0)) revert Manager__ZeroBytecodeHash();
    if (_newHash != expectedNormalizedBytecodeHash) {
        bytes32 oldHash = expectedNormalizedBytecodeHash;
        expectedNormalizedBytecodeHash = _newHash;
        emit ExpectedNormalizedBytecodeHashSet(oldHash, _newHash);
    }
}

// Optional fast-path: zero-out configured [offset,length] windows before hashing
function setNormalizationMask(uint32[] calldata offsets, uint32[] calldata lengths) external onlyAdminRole;

// Tooling helper
function computeNormalizedRuntimeHash(address orderBook) external view returns (bytes32);
```

If the caller has `FACTORY_ROLE`, bytecode checks are skipped to allow trusted factories to register books.

#### Normalized Bytecode Verification

To support OrderBooks with different immutable constructor parameters (manager/base/quote addresses, decimals, scales), the Manager can verify a canonical normalized runtime hash:

```solidity
bytes32 public override expectedNormalizedBytecodeHash;

function setExpectedNormalizedBytecodeHash(bytes32 _newHash) external onlyAdminRole {
    if (_newHash == bytes32(0)) revert Manager__ZeroBytecodeHash();
    if (_newHash != expectedNormalizedBytecodeHash) {
        bytes32 oldHash = expectedNormalizedBytecodeHash;
        expectedNormalizedBytecodeHash = _newHash;
        emit ExpectedNormalizedBytecodeHashSet(oldHash, _newHash);
    }
}

// Optional fast-path: zero-out configured [offset,length] windows before hashing
function setNormalizationMask(uint32[] calldata offsets, uint32[] calldata lengths) external onlyAdminRole;

// Tooling helper
function computeNormalizedRuntimeHash(address orderBook) external view returns (bytes32);
```

If the caller has `FACTORY_ROLE`, bytecode checks are skipped to allow trusted factories to register books.

### Pair Management

```solidity
mapping(bytes32 => address) public override orderBooks;
address[] public allOrderBooks;

function getPairHash(address baseToken, address quoteToken) public pure returns (bytes32) {
    // Deterministic hash regardless of token order
    (address token0, address token1) = baseToken < quoteToken ? 
        (baseToken, quoteToken) : (quoteToken, baseToken);
    return keccak256(abi.encodePacked(token0, token1));
}

// Append-only per-pair index (latest registered remains the canonical pointer above)
function getPairOrderBooks(address tokenA, address tokenB) external view returns (address[] memory);
 
// Append-only per-pair index (latest registered remains the canonical pointer above)
function getPairOrderBooks(address tokenA, address tokenB) external view returns (address[] memory);
```

## Quote Token Whitelist System

### Whitelist Control

```solidity
bool public override isQuoteWhitelistActive;
mapping(address => bool) public override isQuoteTokenWhitelisted;
mapping(address => uint256) public override quoteTokenMinAmounts;
```

### Whitelist Management

```solidity
function addOrUpdateQuoteToken(address _token, uint256 _minQuoteAmount) external override onlyAdminRole {
    if (_token == address(0)) revert Manager__ZeroAddressToken();

    bool wasWhitelisted = isQuoteTokenWhitelisted[_token];
    uint256 oldMinAmount = quoteTokenMinAmounts[_token];

    if (!wasWhitelisted || oldMinAmount != _minQuoteAmount) {
        isQuoteTokenWhitelisted[_token] = true;
        quoteTokenMinAmounts[_token] = _minQuoteAmount;
        
        if (!wasWhitelisted) {
            allWhitelistedQuoteTokens.push(_token);
            quoteTokenToIndex[_token] = allWhitelistedQuoteTokens.length - 1;
            emit QuoteTokenWhitelisted(_token, _minQuoteAmount);
        } else {
            emit QuoteTokenMinAmountUpdated(_token, oldMinAmount, _minQuoteAmount);
        }
    }
}
```

## Emergency Controls

### System-Wide Pause

```solidity
function pauseAllOrderBooks() external onlyPauserRole returns (uint256[] memory pausedIndices) {
    uint256 length = allOrderBooks.length;
    uint256[] memory tempIndices = new uint256[](length);
    uint256 pausedCount = 0;
    
    for (uint256 i = 0; i < length; i++) {
        try IOrderBook(allOrderBooks[i]).pause() {
            tempIndices[pausedCount] = i;
            pausedCount++;
        } catch {
            // Continue even if individual pause fails
        }
    }
    
    // Return successfully paused indices
    pausedIndices = new uint256[](pausedCount);
    for (uint256 i = 0; i < pausedCount; i++) {
        pausedIndices[i] = tempIndices[i];
    }
    
    emit AllOrderBooksPaused(msg.sender, pausedIndices);
    return pausedIndices;
}
```

### System-Wide Unpause

```solidity
function unpauseAllOrderBooks() external onlyPauserRole returns (uint256[] memory unpausedIndices) {
    // Similar implementation for unpausing all OrderBooks
}
```

### Batch Pause/Unpause Operations

For more granular control and gas efficiency when dealing with many OrderBooks:

```solidity
function pauseOrderBooksBatch(uint256 startIndex, uint256 count) 
    external 
    onlyPauserRole 
    returns (address[] memory pausedAddresses)

function unpauseOrderBooksBatch(uint256 startIndex, uint256 count) 
    external 
    onlyPauserRole 
    returns (address[] memory unpausedAddresses)
```

**Batch Operation Benefits:**

* Avoids gas limits when pausing/unpausing many OrderBooks
* Provides pagination for large-scale operations
* Returns specific addresses that were successfully affected
* Enables targeted emergency responses
* Continues operation even if individual OrderBooks fail to pause/unpause

**Usage Example:**

```solidity
// Pause OrderBooks 0-99
pauseOrderBooksBatch(0, 100);

// Pause OrderBooks 100-199
pauseOrderBooksBatch(100, 100);

// Returns array of successfully paused addresses
```

### Pauser Management

Admins can manage who has emergency pause privileges:

```solidity
function addPauser(address account) external {
    // Only ADMIN_ROLE can add pausers
    if (!this.hasOrderBookRole(ADMIN_ROLE, msg.sender)) {
        revert AccessControlUnauthorizedAccount(msg.sender, ADMIN_ROLE);
    }
    _grantRole(PAUSER_ROLE, account);
}

function removePauser(address account) external {
    // Only ADMIN_ROLE can remove pausers
    if (!this.hasOrderBookRole(ADMIN_ROLE, msg.sender)) {
        revert AccessControlUnauthorizedAccount(msg.sender, ADMIN_ROLE);
    }
    _revokeRole(PAUSER_ROLE, account);
}
```

**Emergency Use Cases:**

* Critical security vulnerabilities discovered
* Market manipulation attempts
* Extreme market conditions
* Regulatory compliance requirements

## Configuration Functions

### Fee Configuration

```solidity
function setFees(int256 _makerFee, uint256 _takerFee) external override onlyAdminRole {
    // Validate taker fee
    if (_takerFee > MAX_FEE) revert Manager__FeeTooHigh();
    
    // Validate maker fee (different limits for fees vs rebates)
    if (_makerFee < 0) {
        // For rebates: limit to MAX_REBATE (0.05%)
        if (uint256(-_makerFee) > MAX_REBATE) revert Manager__FeeTooHigh();
    } else {
        // For positive fees: limit to MAX_FEE (0.5%)
        if (uint256(_makerFee) > MAX_FEE) revert Manager__FeeTooHigh();
    }
    
    if (makerFee != _makerFee || takerFee != _takerFee) {
        int256 oldMakerFee = makerFee;
        uint256 oldTakerFee = takerFee;
        makerFee = _makerFee;
        takerFee = _takerFee;
        emit FeesUpdated(oldMakerFee, _makerFee, oldTakerFee, _takerFee);
    }
}
```

### Registration Control

```solidity
function setAllowAnyoneRegisterOrderBook(bool _allowed) external override onlyAdminRole {
    if (_allowed != allowAnyoneRegisterOrderBook) {
        allowAnyoneRegisterOrderBook = _allowed;
        emit AllowAnyoneRegisterOrderBookSet(_allowed);
    }
}
```

## Events

### Registration Events

```solidity
event OrderBookRegistered(
    bytes32 indexed pairHash,
    address indexed baseToken,
    address indexed quoteToken,
    address orderBookAddress
);

event ExpectedBytecodeHashSet(bytes32 oldHash, bytes32 newHash);
event ExpectedNormalizedBytecodeHashSet(bytes32 oldHash, bytes32 newHash);
event AllowAnyoneRegisterOrderBookSet(bool allowed);
```

### Fee Events

```solidity
event FeesUpdated(
    int256 oldMakerFee,
    int256 newMakerFee,
    uint256 oldTakerFee,
    uint256 newTakerFee
);

event FeeCollectorUpdated(
    address indexed oldCollector,
    address indexed newCollector
);
```

### Emergency Events

```solidity
event AllOrderBooksPaused(
    address indexed pauser,
    uint256[] pausedIndices
);

event AllOrderBooksUnpaused(
    address indexed unpauser,
    uint256[] unpausedIndices
);

event OrderBooksPausedBatch(
    address indexed pauser,
    uint256 startIndex,
    uint256 endIndex,
    address[] pausedAddresses
);

event OrderBooksUnpausedBatch(
    address indexed unpauser,
    uint256 startIndex,
    uint256 endIndex,
    address[] unpausedAddresses
);
```

## Security Features

### Input Validation

* Zero address checks for all critical parameters
* Fee rate bounds checking (MAX\_FEE = 0.5%, MAX\_REBATE = 0.05%)
* Bytecode hash validation
* Token pair uniqueness enforcement

### Access Control

* Role-based permissions with inheritance
* Centralized role checking for all OrderBooks
* Emergency response capabilities

### Emergency Response

* System-wide pause/unpause functionality
* Graceful error handling (continues if individual OrderBook fails)
* Event emission for transparency

## Standard Token Registry and Token Denylist

### Standard ERC-20 Registry

```solidity
function setStandardToken(address token, bool isStandard) external onlyAdminRole;
function isStandardToken(address token) external view returns (bool);
function setEnforceStandardBaseOnRegister(bool enforce) external onlyAdminRole;
```

* When enforcement is enabled, `registerOrderBook` requires the BASE token to be marked standard.
* “Standard” means exact-transfer, non-rebasing ERC-20 for gas-fast paths.

### Emergency Token Denylist

```solidity
function setTokenDenied(address token, bool denied) external onlyAdminRole;
function isTokenDenied(address token) external view returns (bool);
```

Denied tokens cannot be used in new OrderBooks (applies to both base and quote), regardless of whitelist status.

## Self-Trade Prevention (STP)

### STP Modes

The Manager contract supports three STP modes for preventing self-trading:

```solidity
enum STPMode {
    NONE,          // No self-trade prevention
    EXPIRE_MAKER,  // Cancel maker order when self-trade detected (default)
    SKIP           // Skip maker order without matching
}
```

### STP Configuration

```solidity
// Set user's STP mode
function setUserSTPMode(STPMode mode) external override {
    userSTPMode[msg.sender] = mode;
    _isStpModeExplicitlySet[msg.sender] = true;
}

// Get user's STP mode (defaults to EXPIRE_MAKER)
function getUserSTPMode(address user) external view override returns (STPMode) {
    if (!_isStpModeExplicitlySet[user]) {
        return STPMode.EXPIRE_MAKER;
    }
    return userSTPMode[user];
}
```

### STP Behavior

**NONE**: Self-trades are allowed and executed normally

**EXPIRE\_MAKER**: When self-trade is detected:

* Maker order is automatically cancelled
* Collateral is refunded to the maker
* Taker order continues to match with other orders

**SKIP**: When self-trade is detected:

* Maker order is skipped (remains active)
* Taker order continues to match with other orders

## Integration Points

### OrderBook Integration

```solidity
// OrderBooks call this for role checking
function hasOrderBookRole(bytes32 role, address account) external view returns (bool);

// OrderBooks call this for fee calculation
function getMakerFeeRate(address orderbook, address user) external view returns (int256);
function getTakerFeeRate(address orderbook, address user) external view returns (uint256);

// OrderBooks call this for STP mode checking
function getUserSTPMode(address user) external view returns (STPMode);
```

### Frontend Integration

* Event monitoring for system changes
* Role-based UI elements
* Real-time fee calculation
* Emergency status indicators

The Manager contract provides the foundational infrastructure for secure, scalable, and maintainable decentralized exchange operations while maintaining flexibility for future enhancements and community governance.
