Overview
BotListV3 manages bot permissions for credit accounts, storing bit masks that dictate which actions bots can perform during multicall operations. Each bot can have different permissions for different credit accounts.
Contract Type: BOT_LIST
Version: 3.10
Source: BotListV3.sol
Key Features
Granular Permissions
Bot permissions are stored as 192-bit masks, allowing fine-grained control over which actions each bot can perform on each credit account.
Per-Account Permissions
Permissions are set per credit account, not globally. This allows:
- Users to grant different permissions to the same bot across their accounts
- Different permission levels for different accounts
- Account-specific automation strategies
Active Bot Tracking
The contract maintains a set of all bots with non-zero permissions for each account, enabling efficient permission management and lookups.
Bot Forbidding
The DAO can forbid specific bots, preventing them from receiving any new permissions while preserving the ability to remove existing permissions.
Core Functions
Permission Queries
botPermissions
function botPermissions(address bot, address creditAccount)
external
view
returns (uint192)
Returns the bot’s permission bit mask for a specific credit account.
Returns: 192-bit permission mask
Example:
uint192 permissions = botList.botPermissions(botAddress, accountAddress);
if (permissions != 0) {
// Bot has some permissions for this account
}
activeBots
function activeBots(address creditAccount)
external
view
returns (address[] memory)
Returns all bots with non-zero permissions for a credit account.
Returns: Array of bot addresses
Example:
address[] memory bots = botList.activeBots(accountAddress);
for (uint256 i = 0; i < bots.length; i++) {
// Process each active bot
}
getBotStatus
function getBotStatus(address bot, address creditAccount)
external
view
returns (uint192 permissions, bool forbidden)
Returns both the bot’s permissions and its forbidden status.
Returns:
permissions: Bot’s permission bit mask (0 if forbidden)
forbidden: Whether the bot is forbidden
Example:
(uint192 permissions, bool forbidden) = botList.getBotStatus(bot, account);
if (forbidden) {
// Bot is forbidden, cannot add new permissions
}
Permission Management
setBotPermissions
function setBotPermissions(
address bot,
address creditAccount,
uint192 permissions
) external returns (uint256 activeBotsRemaining)
Sets the bot’s permissions for a specific credit account.
Bot address (must be non-zero)
Permission bit mask to set (0 to revoke all permissions)
Returns: Number of bots with non-zero permissions remaining after the update
Access: Only callable by credit facade connected to the credit account’s manager
Reverts:
IncorrectBotPermissionsException if permissions don’t match bot’s required permissions
InvalidBotException if trying to set non-zero permissions for a forbidden bot
TooManyActiveBotsException if exceeding maximum active bots limit
Emits: SetBotPermissions(bot, creditManager, creditAccount, permissions)
When setting non-zero permissions, they must exactly match the bot’s requiredPermissions() value.
Example:
// Grant bot permissions
uint192 requiredPerms = IBot(bot).requiredPermissions();
uint256 activeBots = botList.setBotPermissions(
bot,
creditAccount,
requiredPerms
);
// Revoke bot permissions
botList.setBotPermissions(bot, creditAccount, 0);
eraseAllBotPermissions
function eraseAllBotPermissions(address creditAccount) external
Removes all bot permissions for a credit account.
Credit account to clear permissions for
Access: Only callable by credit facade connected to the credit account’s manager
Emits: SetBotPermissions event for each bot with zeroed permissions
Example:
// Revoke all bot permissions when closing account
botList.eraseAllBotPermissions(creditAccount);
Configuration Functions
botForbiddenStatus
function botForbiddenStatus(address bot)
external
view
returns (bool)
Returns whether a bot is currently forbidden.
Returns: True if bot is forbidden
forbidBot
function forbidBot(address bot) external
Forbids a bot, preventing it from receiving new permissions.
Access: Only callable by owner (Instance Manager)
Emits: ForbidBot(bot)
Forbidding a bot does not automatically remove its existing permissions. Users must manually revoke permissions from forbidden bots.
Example:
// Forbid a malicious or buggy bot
botList.forbidBot(problematicBot);
Structures
BotInfo
struct BotInfo {
bool forbidden;
mapping(address => mapping(address => uint192)) permissions;
}
Stores bot information:
forbidden: Whether the bot is forbidden from receiving new permissions
permissions: Nested mapping of (credit manager => credit account => permissions)
Constants
MAX_SANE_ACTIVE_BOTS
The maximum number of bots that can have non-zero permissions for a single credit account. This limit prevents excessive gas costs when processing bot permissions.
Permission System
How Permissions Work
- Permission Bit Mask: Each bot declares a
requiredPermissions() value representing the specific actions it needs
- Exact Match Required: When granting permissions, the provided mask must exactly match the bot’s requirements
- Per-Account: Permissions are isolated per credit account
- Zero to Revoke: Setting permissions to 0 revokes all permissions
Permission Flow
┌─────────────┐
│ User │
└──────┬──────┘
│ Calls Credit Facade
↓
┌─────────────────┐
│ Credit Facade │
└──────┬──────────┘
│ Calls setBotPermissions
↓
┌─────────────────┐ ┌──────────────┐
│ BotList │←──────│ Bot │
│ │ │ (validates) │
│ - Validates │ └──────────────┘
│ - Stores perms │
│ - Tracks active│
└─────────────────┘
Events
SetBotPermissions
event SetBotPermissions(
address indexed bot,
address indexed creditManager,
address indexed creditAccount,
uint192 permissions
)
Emitted when bot permissions are set for a credit account.
ForbidBot
event ForbidBot(address indexed bot)
Emitted when a bot is forbidden.
Security Considerations
Bot Validation
The contract validates that:
- Provided permissions match the bot’s
requiredPermissions()
- The bot is not forbidden when setting non-zero permissions
- The caller is the credit facade connected to the credit manager
- The credit account is currently open
Active Bot Limit
The MAX_SANE_ACTIVE_BOTS limit prevents:
- Excessive gas costs when iterating over active bots
- DoS attacks through bot permission spam
Caller Validation
Only the credit facade connected to a credit manager can modify permissions for accounts managed by that credit manager. This ensures:
- Only authorized contracts can modify permissions
- Permissions can only be set for open accounts
Usage Example
// Check if bot has permissions
uint192 perms = IBotListV3(botList).botPermissions(bot, account);
if (perms != 0) {
// Bot can perform actions
// Execute bot operations
}
// Grant permissions to a bot (from credit facade)
uint192 requiredPerms = IBot(bot).requiredPermissions();
IBotListV3(botList).setBotPermissions(bot, account, requiredPerms);
// Revoke permissions
IBotListV3(botList).setBotPermissions(bot, account, 0);
// Get all active bots for an account
address[] memory bots = IBotListV3(botList).activeBots(account);
// Check bot status
(uint192 permissions, bool forbidden) = IBotListV3(botList).getBotStatus(
bot,
account
);
// Forbid a bot (from owner)
IBotListV3(botList).forbidBot(maliciousBot);
Integration with Bots
Bots must implement the IBot interface:
interface IBot {
function requiredPermissions() external view returns (uint192);
}
The bot declares which permissions it needs, and those exact permissions must be granted by the user through the credit facade.