MON Price: $0.018848 (+2.88%)

Contract

0x0Bc03983Da93021a374C964A22b73865220Ce962

Overview

MON Balance

Monad Chain LogoMonad Chain LogoMonad Chain Logo0 MON

MON Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To

There are no matching entries

1 Internal Transaction found.

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Block From To
357327532025-11-15 9:46:0870 days ago1763199968  Contract Creation0 MON
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
BotListV3

Compiler Version
v0.8.23+commit.f704f362

Optimization Enabled:
Yes with 1000 runs

Other Settings:
shanghai EvmVersion
// SPDX-License-Identifier: BUSL-1.1
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2024.
pragma solidity ^0.8.17;

import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";

import {IBotListV3, BotInfo} from "../interfaces/IBotListV3.sol";
import {ICreditAccountV3} from "../interfaces/ICreditAccountV3.sol";
import {ICreditManagerV3} from "../interfaces/ICreditManagerV3.sol";
import {
    AddressIsNotContractException,
    CallerNotCreditFacadeException,
    IncorrectBotPermissionsException,
    InvalidBotException,
    TooManyActiveBotsException
} from "../interfaces/IExceptions.sol";
import {IAddressProvider} from "../interfaces/base/IAddressProvider.sol";
import {IBot} from "../interfaces/base/IBot.sol";

import {AP_INSTANCE_MANAGER_PROXY, MAX_SANE_ACTIVE_BOTS, NO_VERSION_CONTROL} from "../libraries/Constants.sol";

import {SanityCheckTrait} from "../traits/SanityCheckTrait.sol";

/// @title Bot list V3
/// @notice Stores bot permissions (bit masks dictating which actions can be performed with credit accounts in multicall).
contract BotListV3 is IBotListV3, SanityCheckTrait, Ownable {
    using EnumerableSet for EnumerableSet.AddressSet;

    /// @notice Contract version
    uint256 public constant override version = 3_10;

    /// @notice Contract type
    bytes32 public constant override contractType = "BOT_LIST";

    /// @dev Mapping bot => info
    mapping(address => BotInfo) internal _botInfo;

    /// @dev Mapping credit manager => credit account => set of bots with non-zero permissions
    mapping(address => mapping(address => EnumerableSet.AddressSet)) internal _activeBots;

    /// @notice Constructor
    /// @param addressProvider_ Address provider contract address
    constructor(address addressProvider_) {
        transferOwnership(
            IAddressProvider(addressProvider_).getAddressOrRevert(AP_INSTANCE_MANAGER_PROXY, NO_VERSION_CONTROL)
        );
    }

    // ----------- //
    // PERMISSIONS //
    // ----------- //

    /// @notice Returns `bot`'s permissions for `creditAccount` in its credit manager
    function botPermissions(address bot, address creditAccount) external view override returns (uint192) {
        address creditManager = ICreditAccountV3(creditAccount).creditManager();
        return _botInfo[bot].permissions[creditManager][creditAccount];
    }

    /// @notice Returns all bots with non-zero permissions for `creditAccount` in its credit manager
    function activeBots(address creditAccount) external view override returns (address[] memory) {
        address creditManager = ICreditAccountV3(creditAccount).creditManager();
        return _activeBots[creditManager][creditAccount].values();
    }

    /// @notice Returns `bot`'s permissions for `creditAccount` in its credit manager and whether it is forbidden
    function getBotStatus(address bot, address creditAccount)
        external
        view
        override
        returns (uint192 permissions, bool forbidden)
    {
        BotInfo storage info = _botInfo[bot];
        if (info.forbidden) return (0, true);

        address creditManager = ICreditAccountV3(creditAccount).creditManager();
        return (info.permissions[creditManager][creditAccount], false);
    }

    /// @notice Sets `bot`'s permissions for `creditAccount` in its credit manager to `permissions`
    /// @return activeBotsRemaining Number of bots with non-zero permissions remaining after the update
    /// @dev Reverts if `creditAccount` is not opened in its credit manager or caller is not a facade connected to it
    /// @dev Reverts if trying to set non-zero permissions that don't meet bot's requirements
    /// @dev Reverts if trying to set non-zero permissions for a forbidden bot
    /// @dev Reverts if trying to set non-zero permissions for too many bots
    /// @custom:tests U:[BL-1]
    function setBotPermissions(address bot, address creditAccount, uint192 permissions)
        external
        override
        nonZeroAddress(bot)
        returns (uint256 activeBotsRemaining)
    {
        address creditManager = ICreditAccountV3(creditAccount).creditManager();
        _validateCreditAccountAndCaller(creditManager, creditAccount);

        BotInfo storage info = _botInfo[bot];
        EnumerableSet.AddressSet storage accountBots = _activeBots[creditManager][creditAccount];
        if (permissions != 0) {
            if (IBot(bot).requiredPermissions() != permissions) revert IncorrectBotPermissionsException();
            if (info.forbidden) revert InvalidBotException();
            accountBots.add(bot);
        } else {
            accountBots.remove(bot);
        }
        activeBotsRemaining = accountBots.length();
        if (activeBotsRemaining > MAX_SANE_ACTIVE_BOTS) revert TooManyActiveBotsException();

        if (info.permissions[creditManager][creditAccount] != permissions) {
            info.permissions[creditManager][creditAccount] = permissions;
            emit SetBotPermissions(bot, creditManager, creditAccount, permissions);
        }
    }

    /// @notice Removes all bots' permissions for `creditAccount` in its credit manager
    /// @dev Reverts if `creditAccount` is not opened in its credit manager or caller is not a facade connected to it
    /// @custom:tests U:[BL-2]
    function eraseAllBotPermissions(address creditAccount) external override {
        address creditManager = ICreditAccountV3(creditAccount).creditManager();
        _validateCreditAccountAndCaller(creditManager, creditAccount);

        EnumerableSet.AddressSet storage accountBots = _activeBots[creditManager][creditAccount];
        unchecked {
            for (uint256 i = accountBots.length(); i != 0; --i) {
                address bot = accountBots.at(i - 1);
                accountBots.remove(bot);
                _botInfo[bot].permissions[creditManager][creditAccount] = 0;
                emit SetBotPermissions(bot, creditManager, creditAccount, 0);
            }
        }
    }

    // ------------- //
    // CONFIGURATION //
    // ------------- //

    /// @notice Returns `bot`'s forbidden status
    function botForbiddenStatus(address bot) external view override returns (bool) {
        return _botInfo[bot].forbidden;
    }

    /// @notice Forbid's `bot`
    function forbidBot(address bot) external override onlyOwner {
        BotInfo storage info = _botInfo[bot];
        if (!info.forbidden) {
            info.forbidden = true;
            emit ForbidBot(bot);
        }
    }

    // --------- //
    // INTERNALS //
    // --------- //

    /// @dev Reverts if `creditAccount` is not opened in `creditManager` or caller is not a facade connected to it
    function _validateCreditAccountAndCaller(address creditManager, address creditAccount) internal view {
        ICreditManagerV3(creditManager).getBorrowerOrRevert(creditAccount);
        if (ICreditManagerV3(creditManager).creditFacade() != msg.sender) {
            revert CallerNotCreditFacadeException();
        }
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)

pragma solidity ^0.8.0;

import "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby disabling any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableSet.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.

pragma solidity ^0.8.0;

/**
 * @dev Library for managing
 * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
 * types.
 *
 * Sets have the following properties:
 *
 * - Elements are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Elements are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```solidity
 * contract Example {
 *     // Add the library methods
 *     using EnumerableSet for EnumerableSet.AddressSet;
 *
 *     // Declare a set state variable
 *     EnumerableSet.AddressSet private mySet;
 * }
 * ```
 *
 * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
 * and `uint256` (`UintSet`) are supported.
 *
 * [WARNING]
 * ====
 * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
 * unusable.
 * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
 *
 * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
 * array of EnumerableSet.
 * ====
 */
library EnumerableSet {
    // To implement this library for multiple types with as little code
    // repetition as possible, we write it in terms of a generic Set type with
    // bytes32 values.
    // The Set implementation uses private functions, and user-facing
    // implementations (such as AddressSet) are just wrappers around the
    // underlying Set.
    // This means that we can only create new EnumerableSets for types that fit
    // in bytes32.

    struct Set {
        // Storage of set values
        bytes32[] _values;
        // Position of the value in the `values` array, plus 1 because index 0
        // means a value is not in the set.
        mapping(bytes32 => uint256) _indexes;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function _add(Set storage set, bytes32 value) private returns (bool) {
        if (!_contains(set, value)) {
            set._values.push(value);
            // The value is stored at length-1, but we add 1 to all indexes
            // and use 0 as a sentinel value
            set._indexes[value] = set._values.length;
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function _remove(Set storage set, bytes32 value) private returns (bool) {
        // We read and store the value's index to prevent multiple reads from the same storage slot
        uint256 valueIndex = set._indexes[value];

        if (valueIndex != 0) {
            // Equivalent to contains(set, value)
            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
            // the array, and then remove the last element (sometimes called as 'swap and pop').
            // This modifies the order of the array, as noted in {at}.

            uint256 toDeleteIndex = valueIndex - 1;
            uint256 lastIndex = set._values.length - 1;

            if (lastIndex != toDeleteIndex) {
                bytes32 lastValue = set._values[lastIndex];

                // Move the last value to the index where the value to delete is
                set._values[toDeleteIndex] = lastValue;
                // Update the index for the moved value
                set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex
            }

            // Delete the slot where the moved value was stored
            set._values.pop();

            // Delete the index for the deleted slot
            delete set._indexes[value];

            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function _contains(Set storage set, bytes32 value) private view returns (bool) {
        return set._indexes[value] != 0;
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function _length(Set storage set) private view returns (uint256) {
        return set._values.length;
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function _at(Set storage set, uint256 index) private view returns (bytes32) {
        return set._values[index];
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function _values(Set storage set) private view returns (bytes32[] memory) {
        return set._values;
    }

    // Bytes32Set

    struct Bytes32Set {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _add(set._inner, value);
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _remove(set._inner, value);
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
        return _contains(set._inner, value);
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(Bytes32Set storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
        return _at(set._inner, index);
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
        bytes32[] memory store = _values(set._inner);
        bytes32[] memory result;

        /// @solidity memory-safe-assembly
        assembly {
            result := store
        }

        return result;
    }

    // AddressSet

    struct AddressSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(AddressSet storage set, address value) internal returns (bool) {
        return _add(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(AddressSet storage set, address value) internal returns (bool) {
        return _remove(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(AddressSet storage set, address value) internal view returns (bool) {
        return _contains(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(AddressSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(AddressSet storage set, uint256 index) internal view returns (address) {
        return address(uint160(uint256(_at(set._inner, index))));
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(AddressSet storage set) internal view returns (address[] memory) {
        bytes32[] memory store = _values(set._inner);
        address[] memory result;

        /// @solidity memory-safe-assembly
        assembly {
            result := store
        }

        return result;
    }

    // UintSet

    struct UintSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(UintSet storage set, uint256 value) internal returns (bool) {
        return _add(set._inner, bytes32(value));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(UintSet storage set, uint256 value) internal returns (bool) {
        return _remove(set._inner, bytes32(value));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(UintSet storage set, uint256 value) internal view returns (bool) {
        return _contains(set._inner, bytes32(value));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(UintSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(UintSet storage set, uint256 index) internal view returns (uint256) {
        return uint256(_at(set._inner, index));
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(UintSet storage set) internal view returns (uint256[] memory) {
        bytes32[] memory store = _values(set._inner);
        uint256[] memory result;

        /// @solidity memory-safe-assembly
        assembly {
            result := store
        }

        return result;
    }
}

File 5 of 14 : Constants.sol
// SPDX-License-Identifier: BUSL-1.1
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2024.
pragma solidity ^0.8.17;

bytes32 constant AP_GEAR_TOKEN = "GLOBAL::GEAR_TOKEN";
bytes32 constant AP_INSTANCE_MANAGER_PROXY = "INSTANCE_MANAGER_PROXY";
bytes32 constant AP_CROSS_CHAIN_GOVERNANCE_PROXY = "CROSS_CHAIN_GOVERNANCE_PROXY";
bytes32 constant AP_PRICE_FEED_STORE = "PRICE_FEED_STORE";
uint256 constant NO_VERSION_CONTROL = 0;

uint256 constant WAD = 1e18;
uint256 constant RAY = 1e27;
uint16 constant PERCENTAGE_FACTOR = 1e4;

uint256 constant SECONDS_PER_YEAR = 365 days;
uint256 constant EPOCH_LENGTH = 7 days;
uint256 constant FIRST_EPOCH_TIMESTAMP = 1702900800;
uint256 constant EPOCHS_TO_WITHDRAW = 4;

uint8 constant MAX_SANE_ENABLED_TOKENS = 20;
uint256 constant MAX_SANE_EPOCH_LENGTH = 28 days;
uint256 constant MAX_SANE_ACTIVE_BOTS = 5;

uint8 constant MAX_WITHDRAW_FEE = 100;

uint8 constant DEFAULT_LIMIT_PER_BLOCK_MULTIPLIER = 2;

uint8 constant BOT_PERMISSIONS_SET_FLAG = 1;

uint256 constant UNDERLYING_TOKEN_MASK = 1;

address constant INACTIVE_CREDIT_ACCOUNT_ADDRESS = address(1);

// SPDX-License-Identifier: MIT
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2024.
pragma solidity ^0.8.17;

import {IVersion} from "./IVersion.sol";
import {IStateSerializer} from "./IStateSerializer.sol";

/// @title Bot interface
/// @notice Minimal interface contracts must conform to in order to be used as bots in Gearbox V3
/// @dev Bots must have type `BOT::{POSTFIX}`
interface IBot is IVersion, IStateSerializer {
    /// @notice Mask of permissions required for bot operation, see `ICreditFacadeV3Multicall`
    function requiredPermissions() external view returns (uint192);
}

// SPDX-License-Identifier: MIT
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2024.
pragma solidity ^0.8.17;

import {IVersion} from "./base/IVersion.sol";

/// @notice Bot info
/// @param forbidden Whether bot is forbidden
/// @param permissions Mapping credit manager => credit account => bot's permissions
struct BotInfo {
    bool forbidden;
    mapping(address => mapping(address => uint192)) permissions;
}

interface IBotListV3Events {
    // ----------- //
    // PERMISSIONS //
    // ----------- //

    /// @notice Emitted when new `bot`'s permissions are set for `creditAccount` in `creditManager`
    event SetBotPermissions(
        address indexed bot, address indexed creditManager, address indexed creditAccount, uint192 permissions
    );

    // ------------- //
    // CONFIGURATION //
    // ------------- //

    /// @notice Emitted when `bot` is forbidden
    event ForbidBot(address indexed bot);
}

/// @title Bot list V3 interface
interface IBotListV3 is IBotListV3Events, IVersion {
    // ----------- //
    // PERMISSIONS //
    // ----------- //

    function botPermissions(address bot, address creditAccount) external view returns (uint192);

    function activeBots(address creditAccount) external view returns (address[] memory);

    function getBotStatus(address bot, address creditAccount)
        external
        view
        returns (uint192 permissions, bool forbidden);

    function setBotPermissions(address bot, address creditAccount, uint192 permissions)
        external
        returns (uint256 activeBotsRemaining);

    function eraseAllBotPermissions(address creditAccount) external;

    // ------------- //
    // CONFIGURATION //
    // ------------- //

    function botForbiddenStatus(address bot) external view returns (bool);

    function forbidBot(address bot) external;
}

File 8 of 14 : IExceptions.sol
// SPDX-License-Identifier: MIT
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2024.
pragma solidity ^0.8.17;

// ------- //
// GENERAL //
// ------- //

/// @notice Thrown on attempting to set an important address to zero address
error ZeroAddressException();

/// @notice Thrown when attempting to pass a zero amount to a funding-related operation
error AmountCantBeZeroException();

/// @notice Thrown on incorrect input parameter
error IncorrectParameterException();

/// @notice Thrown when balance is insufficient to perform an operation
error InsufficientBalanceException();

/// @notice Thrown if parameter is out of range
error ValueOutOfRangeException();

/// @notice Thrown when trying to send ETH to a contract that is not allowed to receive ETH directly
error ReceiveIsNotAllowedException();

/// @notice Thrown on attempting to set an EOA as an important contract in the system
error AddressIsNotContractException(address);

/// @notice Thrown on attempting to receive a token that is not a collateral token or was forbidden
error TokenNotAllowedException();

/// @notice Thrown on attempting to add a token that is already in a collateral list
error TokenAlreadyAddedException();

/// @notice Thrown when attempting to use quota-related logic for a token that is not quoted in quota keeper
error TokenIsNotQuotedException();

/// @notice Thrown on attempting to interact with an address that is not a valid target contract
error TargetContractNotAllowedException();

/// @notice Thrown if function is not implemented
error NotImplementedException();

// ------------------ //
// CONTRACTS REGISTER //
// ------------------ //

/// @notice Thrown when an address is expected to be a registered credit manager, but is not
error RegisteredCreditManagerOnlyException();

/// @notice Thrown when an address is expected to be a registered pool, but is not
error RegisteredPoolOnlyException();

// ---------------- //
// ADDRESS PROVIDER //
// ---------------- //

/// @notice Reverts if address key isn't found in address provider
error AddressNotFoundException();

// ----------------- //
// POOL, PQK, GAUGES //
// ----------------- //

/// @notice Thrown by pool-adjacent contracts when a credit manager being connected has a wrong pool address
error IncompatibleCreditManagerException();

/// @notice Thrown when attempting to set an incompatible successor staking contract
error IncompatibleSuccessorException();

/// @notice Thrown when attempting to vote in a non-approved contract
error VotingContractNotAllowedException();

/// @notice Thrown when attempting to unvote more votes than there are
error InsufficientVotesException();

/// @notice Thrown when attempting to borrow more than the second point on a two-point curve
error BorrowingMoreThanU2ForbiddenException();

/// @notice Thrown when a credit manager attempts to borrow more than its limit in the current block, or in general
error CreditManagerCantBorrowException();

/// @notice Thrown when attempting to connect a quota keeper to an incompatible pool
error IncompatiblePoolQuotaKeeperException();

/// @notice Thrown when attempting to connect a gauge to an incompatible pool quota keeper
error IncompatibleGaugeException();

/// @notice Thrown when the quota is outside of min/max bounds
error QuotaIsOutOfBoundsException();

// -------------- //
// CREDIT MANAGER //
// -------------- //

/// @notice Thrown on failing a full collateral check after multicall
error NotEnoughCollateralException();

/// @notice Thrown if an attempt to approve a collateral token to adapter's target contract fails
error AllowanceFailedException();

/// @notice Thrown on attempting to perform an action for a credit account that does not exist
error CreditAccountDoesNotExistException();

/// @notice Thrown on configurator attempting to add more than 255 collateral tokens
error TooManyTokensException();

/// @notice Thrown if more than the maximum number of tokens were enabled on a credit account
error TooManyEnabledTokensException();

/// @notice Thrown when attempting to execute a protocol interaction without active credit account set
error ActiveCreditAccountNotSetException();

/// @notice Thrown when trying to update credit account's debt more than once in the same block
error DebtUpdatedTwiceInOneBlockException();

/// @notice Thrown when trying to repay all debt while having active quotas
error DebtToZeroWithActiveQuotasException();

/// @notice Thrown when a zero-debt account attempts to update quota
error UpdateQuotaOnZeroDebtAccountException();

/// @notice Thrown when attempting to close an account with non-zero debt
error CloseAccountWithNonZeroDebtException();

/// @notice Thrown when value of funds remaining on the account after liquidation is insufficient
error InsufficientRemainingFundsException();

/// @notice Thrown when Credit Facade tries to write over a non-zero active Credit Account
error ActiveCreditAccountOverridenException();

// ------------------- //
// CREDIT CONFIGURATOR //
// ------------------- //

/// @notice Thrown on attempting to use a non-ERC20 contract or an EOA as a token
error IncorrectTokenContractException();

/// @notice Thrown if the newly set LT if zero or greater than the underlying's LT
error IncorrectLiquidationThresholdException();

/// @notice Thrown if borrowing limits are incorrect: minLimit > maxLimit or maxLimit > blockLimit
error IncorrectLimitsException();

/// @notice Thrown if the new expiration date is less than the current expiration date or current timestamp
error IncorrectExpirationDateException();

/// @notice Thrown if a contract returns a wrong credit manager or reverts when trying to retrieve it
error IncompatibleContractException();

/// @notice Thrown if attempting to forbid an adapter that is not registered in the credit manager
error AdapterIsNotRegisteredException();

/// @notice Thrown if new credit configurator's set of allowed adapters differs from the current one
error IncorrectAdaptersSetException();

/// @notice Thrown if attempting to schedule a token's LT ramping that is too short in duration
error RampDurationTooShortException();

/// @notice Thrown if attempting to set liquidation fees such that the sum of premium and fee changes
error InconsistentLiquidationFeesException();

/// @notice Thrown if attempting to set expired liquidation fees such that the sum of premium and fee changes
error InconsistentExpiredLiquidationFeesException();

// ------------- //
// CREDIT FACADE //
// ------------- //

/// @notice Thrown when attempting to perform an action that is forbidden in whitelisted mode
error ForbiddenInWhitelistedModeException();

/// @notice Thrown if credit facade is not expirable, and attempted aciton requires expirability
error NotAllowedWhenNotExpirableException();

/// @notice Thrown if a selector that doesn't match any allowed function is passed to the credit facade in a multicall
error UnknownMethodException(bytes4 selector);

/// @notice Thrown if a liquidator tries to liquidate an account with a health factor above 1
error CreditAccountNotLiquidatableException();

/// @notice Thrown if a liquidator tries to liquidate an account with loss but violates the loss policy
error CreditAccountNotLiquidatableWithLossException();

/// @notice Thrown if too much new debt was taken within a single block
error BorrowedBlockLimitException();

/// @notice Thrown if the new debt principal for a credit account falls outside of borrowing limits
error BorrowAmountOutOfLimitsException();

/// @notice Thrown if a user attempts to open an account via an expired credit facade
error NotAllowedAfterExpirationException();

/// @notice Thrown if expected balances are attempted to be set twice without performing a slippage check
error ExpectedBalancesAlreadySetException();

/// @notice Thrown if attempting to perform a slippage check when excepted balances are not set
error ExpectedBalancesNotSetException();

/// @notice Thrown if balance of at least one token is less than expected during a slippage check
error BalanceLessThanExpectedException(address token);

/// @notice Thrown when trying to perform an action that is forbidden when credit account has enabled forbidden tokens
error ForbiddenTokensException(uint256 forbiddenTokensMask);

/// @notice Thrown when forbidden token quota is increased during the multicall
error ForbiddenTokenQuotaIncreasedException(address token);

/// @notice Thrown when enabled forbidden token balance is increased during the multicall
error ForbiddenTokenBalanceIncreasedException(address token);

/// @notice Thrown when the remaining token balance is increased during the liquidation
error RemainingTokenBalanceIncreasedException(address token);

/// @notice Thrown if `botMulticall` is called by an address that is not approved by account owner or is forbidden
error NotApprovedBotException(address bot);

/// @notice Thrown when attempting to perform a multicall action with no permission for it
error NoPermissionException(uint256 permission);

/// @notice Thrown when attempting to give a bot unexpected permissions
error UnexpectedPermissionsException(uint256 permissions);

/// @notice Thrown when a custom HF parameter lower than 10000 is passed into the full collateral check
error CustomHealthFactorTooLowException();

/// @notice Thrown when submitted collateral hint is not a valid token mask
error InvalidCollateralHintException(uint256 mask);

/// @notice Thrown when trying to seize underlying token during partial liquidation
error UnderlyingIsNotLiquidatableException();

/// @notice Thrown when amount of collateral seized during partial liquidation is less than required
error SeizedLessThanRequiredException(uint256 seizedAmount);

// ------ //
// ACCESS //
// ------ //

/// @notice Thrown on attempting to call an access restricted function not as credit account owner
error CallerNotCreditAccountOwnerException();

/// @notice Thrown on attempting to call an access restricted function not as configurator
error CallerNotConfiguratorException();

/// @notice Thrown on attempting to call an access-restructed function not as account factory
error CallerNotAccountFactoryException();

/// @notice Thrown on attempting to call an access restricted function not as credit manager
error CallerNotCreditManagerException();

/// @notice Thrown on attempting to call an access restricted function not as credit facade
error CallerNotCreditFacadeException();

/// @notice Thrown on attempting to pause a contract without pausable admin rights
error CallerNotPausableAdminException();

/// @notice Thrown on attempting to unpause a contract without unpausable admin rights
error CallerNotUnpausableAdminException();

/// @notice Thrown on attempting to call an access restricted function not as gauge
error CallerNotGaugeException();

/// @notice Thrown on attempting to call an access restricted function not as quota keeper
error CallerNotPoolQuotaKeeperException();

/// @notice Thrown on attempting to call an access restricted function not as voter
error CallerNotVoterException();

/// @notice Thrown on attempting to call an access restricted function not as allowed adapter
error CallerNotAdapterException();

/// @notice Thrown on attempting to call an access restricted function not as migrator
error CallerNotMigratorException();

/// @notice Thrown when an address that is not the designated executor attempts to execute a transaction
error CallerNotExecutorException();

/// @notice Thrown on attempting to call an access restricted function not as veto admin
error CallerNotVetoAdminException();

// -------- //
// BOT LIST //
// -------- //

/// @notice Thrown when attempting to set non-zero permissions for a forbidden bot
error InvalidBotException();

/// @notice Thrown when attempting to set permissions for a bot that don't meet its requirements
error IncorrectBotPermissionsException();

/// @notice Thrown when attempting to set non-zero permissions for too many bots
error TooManyActiveBotsException();

// --------------- //
// ACCOUNT FACTORY //
// --------------- //

/// @notice Thrown when trying to deploy second master credit account for a credit manager
error MasterCreditAccountAlreadyDeployedException();

/// @notice Thrown when trying to rescue funds from a credit account that is currently in use
error CreditAccountIsInUseException();

// ------------ //
// PRICE ORACLE //
// ------------ //

/// @notice Thrown on attempting to set a token price feed to an address that is not a correct price feed
error IncorrectPriceFeedException();

/// @notice Thrown on attempting to interact with a price feed for a token not added to the price oracle
error PriceFeedDoesNotExistException();

/// @notice Thrown when trying to apply an on-demand price update to a non-updatable price feed
error PriceFeedIsNotUpdatableException();

/// @notice Thrown when price feed returns incorrect price for a token
error IncorrectPriceException();

/// @notice Thrown when token's price feed becomes stale
error StalePriceException();

File 9 of 14 : SanityCheckTrait.sol
// SPDX-License-Identifier: BUSL-1.1
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2024.
pragma solidity ^0.8.17;

import {ZeroAddressException} from "../interfaces/IExceptions.sol";

/// @title Sanity check trait
abstract contract SanityCheckTrait {
    /// @dev Ensures that passed address is non-zero
    modifier nonZeroAddress(address addr) {
        _revertIfZeroAddress(addr);
        _;
    }

    /// @dev Reverts if address is zero
    function _revertIfZeroAddress(address addr) private pure {
        if (addr == address(0)) revert ZeroAddressException();
    }
}

// SPDX-License-Identifier: MIT
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2024.
pragma solidity ^0.8.17;

/// @title Version interface
/// @notice Defines contract version and type
interface IVersion {
    /// @notice Contract version
    function version() external view returns (uint256);

    /// @notice Contract type
    function contractType() external view returns (bytes32);
}

// SPDX-License-Identifier: MIT
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2024.
pragma solidity ^0.8.17;

import {IVersion} from "./base/IVersion.sol";

/// @title Credit account V3 interface
interface ICreditAccountV3 is IVersion {
    function factory() external view returns (address);

    function creditManager() external view returns (address);

    function safeTransfer(address token, address to, uint256 amount) external;

    function execute(address target, bytes calldata data) external returns (bytes memory result);

    function rescue(address target, bytes calldata data) external;
}

File 12 of 14 : ICreditManagerV3.sol
// SPDX-License-Identifier: MIT
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2024.
pragma solidity ^0.8.17;

import {IVersion} from "./base/IVersion.sol";

/// @notice Debt management type
///         - `INCREASE_DEBT` borrows additional funds from the pool, updates account's debt and cumulative interest index
///         - `DECREASE_DEBT` repays debt components (quota interest and fees -> base interest and fees -> debt principal)
///           and updates all corresponding state variables (base interest index, quota interest and fees, debt).
///           When repaying all the debt, ensures that account has no enabled quotas.
enum ManageDebtAction {
    INCREASE_DEBT,
    DECREASE_DEBT
}

/// @notice Collateral/debt calculation mode
///         - `GENERIC_PARAMS` returns generic data like account debt and cumulative indexes
///         - `DEBT_ONLY` is same as `GENERIC_PARAMS` but includes more detailed debt info, like accrued base/quota
///           interest and fees
///         - `FULL_COLLATERAL_CHECK_LAZY` checks whether account is sufficiently collateralized in a lazy fashion,
///           i.e. it stops iterating over collateral tokens once TWV reaches the desired target.
///           Since it may return underestimated TWV, it's only available for internal use.
///         - `DEBT_COLLATERAL` is same as `DEBT_ONLY` but also returns total value and total LT-weighted value of
///           account's tokens, this mode is used during account liquidation
///         - `DEBT_COLLATERAL_SAFE_PRICES` is same as `DEBT_COLLATERAL` but uses safe prices from price oracle
enum CollateralCalcTask {
    GENERIC_PARAMS,
    DEBT_ONLY,
    FULL_COLLATERAL_CHECK_LAZY,
    DEBT_COLLATERAL,
    DEBT_COLLATERAL_SAFE_PRICES
}

struct CreditAccountInfo {
    uint256 debt;
    uint256 cumulativeIndexLastUpdate;
    uint128 cumulativeQuotaInterest;
    uint128 quotaFees;
    uint256 enabledTokensMask;
    uint16 flags;
    uint64 lastDebtUpdate;
    address borrower;
}

struct CollateralDebtData {
    uint256 debt;
    uint256 cumulativeIndexNow;
    uint256 cumulativeIndexLastUpdate;
    uint128 cumulativeQuotaInterest;
    uint256 accruedInterest;
    uint256 accruedFees;
    uint256 totalDebtUSD;
    uint256 totalValue;
    uint256 totalValueUSD;
    uint256 twvUSD;
    uint256 enabledTokensMask;
    uint256 quotedTokensMask;
    address[] quotedTokens;
    address _poolQuotaKeeper;
}

struct CollateralTokenData {
    address token;
    uint16 ltInitial;
    uint16 ltFinal;
    uint40 timestampRampStart;
    uint24 rampDuration;
}

interface ICreditManagerV3Events {
    /// @notice Emitted when new credit configurator is set
    event SetCreditConfigurator(address indexed newConfigurator);
}

/// @title Credit manager V3 interface
interface ICreditManagerV3 is IVersion, ICreditManagerV3Events {
    function pool() external view returns (address);

    function underlying() external view returns (address);

    function creditFacade() external view returns (address);

    function creditConfigurator() external view returns (address);

    function accountFactory() external view returns (address);

    function name() external view returns (string memory);

    // ------------------ //
    // ACCOUNT MANAGEMENT //
    // ------------------ //

    function openCreditAccount(address onBehalfOf) external returns (address);

    function closeCreditAccount(address creditAccount) external;

    function liquidateCreditAccount(
        address creditAccount,
        CollateralDebtData calldata collateralDebtData,
        address to,
        bool isExpired
    ) external returns (uint256 remainingFunds, uint256 loss);

    function manageDebt(address creditAccount, uint256 amount, uint256 enabledTokensMask, ManageDebtAction action)
        external
        returns (uint256 newDebt, uint256, uint256);

    function addCollateral(address payer, address creditAccount, address token, uint256 amount)
        external
        returns (uint256);

    function withdrawCollateral(address creditAccount, address token, uint256 amount, address to)
        external
        returns (uint256);

    function externalCall(address creditAccount, address target, bytes calldata callData)
        external
        returns (bytes memory result);

    function approveToken(address creditAccount, address token, address spender, uint256 amount) external;

    // -------- //
    // ADAPTERS //
    // -------- //

    function adapterToContract(address adapter) external view returns (address targetContract);

    function contractToAdapter(address targetContract) external view returns (address adapter);

    function execute(bytes calldata data) external returns (bytes memory result);

    function approveCreditAccount(address token, uint256 amount) external;

    function setActiveCreditAccount(address creditAccount) external;

    function getActiveCreditAccountOrRevert() external view returns (address creditAccount);

    // ----------------- //
    // COLLATERAL CHECKS //
    // ----------------- //

    function priceOracle() external view returns (address);

    function fullCollateralCheck(
        address creditAccount,
        uint256 enabledTokensMask,
        uint256[] calldata collateralHints,
        uint16 minHealthFactor,
        bool useSafePrices
    ) external returns (uint256);

    function isLiquidatable(address creditAccount, uint16 minHealthFactor) external view returns (bool);

    function calcDebtAndCollateral(address creditAccount, CollateralCalcTask task)
        external
        view
        returns (CollateralDebtData memory cdd);

    // ------ //
    // QUOTAS //
    // ------ //

    function poolQuotaKeeper() external view returns (address);

    function quotedTokensMask() external view returns (uint256);

    function updateQuota(address creditAccount, address token, int96 quotaChange, uint96 minQuota, uint96 maxQuota)
        external
        returns (uint256 tokensToEnable, uint256 tokensToDisable);

    // --------------------- //
    // CREDIT MANAGER PARAMS //
    // --------------------- //

    function maxEnabledTokens() external view returns (uint8);

    function fees()
        external
        view
        returns (
            uint16 feeInterest,
            uint16 feeLiquidation,
            uint16 liquidationDiscount,
            uint16 feeLiquidationExpired,
            uint16 liquidationDiscountExpired
        );

    function collateralTokensCount() external view returns (uint8);

    function getTokenMaskOrRevert(address token) external view returns (uint256 tokenMask);

    function getTokenByMask(uint256 tokenMask) external view returns (address token);

    function liquidationThresholds(address token) external view returns (uint16 lt);

    function ltParams(address token)
        external
        view
        returns (uint16 ltInitial, uint16 ltFinal, uint40 timestampRampStart, uint24 rampDuration);

    function collateralTokenByMask(uint256 tokenMask)
        external
        view
        returns (address token, uint16 liquidationThreshold);

    // ------------ //
    // ACCOUNT INFO //
    // ------------ //

    function creditAccountInfo(address creditAccount)
        external
        view
        returns (
            uint256 debt,
            uint256 cumulativeIndexLastUpdate,
            uint128 cumulativeQuotaInterest,
            uint128 quotaFees,
            uint256 enabledTokensMask,
            uint16 flags,
            uint64 lastDebtUpdate,
            address borrower
        );

    function getBorrowerOrRevert(address creditAccount) external view returns (address borrower);

    function flagsOf(address creditAccount) external view returns (uint16);

    function setFlagFor(address creditAccount, uint16 flag, bool value) external;

    function enabledTokensMaskOf(address creditAccount) external view returns (uint256);

    function creditAccounts() external view returns (address[] memory);

    function creditAccounts(uint256 offset, uint256 limit) external view returns (address[] memory);

    function creditAccountsLen() external view returns (uint256);

    // ------------- //
    // CONFIGURATION //
    // ------------- //

    function addToken(address token) external;

    function setCollateralTokenData(
        address token,
        uint16 ltInitial,
        uint16 ltFinal,
        uint40 timestampRampStart,
        uint24 rampDuration
    ) external;

    function setFees(
        uint16 feeInterest,
        uint16 feeLiquidation,
        uint16 liquidationDiscount,
        uint16 feeLiquidationExpired,
        uint16 liquidationDiscountExpired
    ) external;

    function setContractAllowance(address adapter, address targetContract) external;

    function setCreditFacade(address creditFacade) external;

    function setPriceOracle(address priceOracle) external;

    function setCreditConfigurator(address creditConfigurator) external;
}

// SPDX-License-Identifier: MIT
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2024.
pragma solidity ^0.8.17;

interface IAddressProvider {
    function getAddressOrRevert(bytes32 key, uint256 version) external view returns (address);
}

File 14 of 14 : IStateSerializer.sol
// SPDX-License-Identifier: MIT
// Gearbox Protocol. Generalized leverage for DeFi protocols
// (c) Gearbox Foundation, 2024.
pragma solidity ^0.8.17;

/// @title State serializer interface
/// @notice Generic interface for a contract that can serialize its state into a bytes array
interface IStateSerializer {
    /// @notice Serializes the state of the contract into a bytes array `serializedData`
    function serialize() external view returns (bytes memory serializedData);
}

Settings
{
  "remappings": [
    "@1inch/=lib/@1inch/",
    "@gearbox-protocol/=lib/@gearbox-protocol/",
    "@openzeppelin/=lib/@openzeppelin/",
    "@redstone-finance/=node_modules/@redstone-finance/",
    "@solady/=lib/@solady/src/",
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "erc4626-tests/=lib/@openzeppelin/lib/erc4626-tests/",
    "forge-std/=lib/forge-std/src/",
    "openzeppelin/=lib/@openzeppelin/contracts/"
  ],
  "optimizer": {
    "runs": 1000,
    "enabled": true
  },
  "metadata": {
    "bytecodeHash": "none",
    "useLiteralContent": true
  },
  "evmVersion": "shanghai",
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  }
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"addressProvider_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"CallerNotCreditFacadeException","type":"error"},{"inputs":[],"name":"IncorrectBotPermissionsException","type":"error"},{"inputs":[],"name":"InvalidBotException","type":"error"},{"inputs":[],"name":"TooManyActiveBotsException","type":"error"},{"inputs":[],"name":"ZeroAddressException","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"bot","type":"address"}],"name":"ForbidBot","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"bot","type":"address"},{"indexed":true,"internalType":"address","name":"creditManager","type":"address"},{"indexed":true,"internalType":"address","name":"creditAccount","type":"address"},{"indexed":false,"internalType":"uint192","name":"permissions","type":"uint192"}],"name":"SetBotPermissions","type":"event"},{"inputs":[{"internalType":"address","name":"creditAccount","type":"address"}],"name":"activeBots","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"bot","type":"address"}],"name":"botForbiddenStatus","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"bot","type":"address"},{"internalType":"address","name":"creditAccount","type":"address"}],"name":"botPermissions","outputs":[{"internalType":"uint192","name":"","type":"uint192"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contractType","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"creditAccount","type":"address"}],"name":"eraseAllBotPermissions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"bot","type":"address"}],"name":"forbidBot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"bot","type":"address"},{"internalType":"address","name":"creditAccount","type":"address"}],"name":"getBotStatus","outputs":[{"internalType":"uint192","name":"permissions","type":"uint192"},{"internalType":"bool","name":"forbidden","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"bot","type":"address"},{"internalType":"address","name":"creditAccount","type":"address"},{"internalType":"uint192","name":"permissions","type":"uint192"}],"name":"setBotPermissions","outputs":[{"internalType":"uint256","name":"activeBotsRemaining","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]

608060405234801562000010575f80fd5b50604051620011a4380380620011a483398101604081905262000033916200020e565b6200003e33620000df565b604051632bdad0e360e11b81527f494e5354414e43455f4d414e414745525f50524f58590000000000000000000060048201525f6024820152620000d8906001600160a01b038316906357b5a1c690604401602060405180830381865afa158015620000ac573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620000d291906200020e565b6200012e565b506200023d565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b62000138620001b1565b6001600160a01b038116620001a35760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b620001ae81620000df565b50565b5f546001600160a01b031633146200020c5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016200019a565b565b5f602082840312156200021f575f80fd5b81516001600160a01b038116811462000236575f80fd5b9392505050565b610f59806200024b5f395ff3fe608060405234801561000f575f80fd5b50600436106100cf575f3560e01c80638da5cb5b1161007d578063cb2ef6f711610058578063cb2ef6f7146101cd578063f2fde38b146101f4578063f439dc6714610207575f80fd5b80638da5cb5b1461016e578063997a072314610188578063c5b73ed0146101ba575f80fd5b806354fd4d50116100ad57806354fd4d501461012457806356e0381a1461013b578063715018a614610166575f80fd5b80630e2b0c94146100d3578063348f46ab146100fc57806342a3b4d614610111575b5f80fd5b6100e66100e1366004610dd5565b610242565b6040516100f39190610df0565b60405180910390f35b61010f61010a366004610dd5565b6102dc565b005b61010f61011f366004610dd5565b610347565b61012d61013681565b6040519081526020016100f3565b61014e610149366004610e3c565b6104a3565b6040516001600160c01b0390911681526020016100f3565b61010f61054c565b5f546040516001600160a01b0390911681526020016100f3565b61019b610196366004610e3c565b61055f565b604080516001600160c01b0390931683529015156020830152016100f3565b61012d6101c8366004610e87565b610631565b61012d7f424f545f4c49535400000000000000000000000000000000000000000000000081565b61010f610202366004610dd5565b61090a565b610232610215366004610dd5565b6001600160a01b03165f9081526001602052604090205460ff1690565b60405190151581526020016100f3565b60605f826001600160a01b031663c12c21c06040518163ffffffff1660e01b8152600401602060405180830381865afa158015610281573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102a59190610ecf565b6001600160a01b038082165f9081526002602090815260408083209388168352929052209091506102d59061099f565b9392505050565b6102e46109ab565b6001600160a01b0381165f908152600160205260409020805460ff1661034357805460ff191660011781556040516001600160a01b038316907fd4f28d440c8ecafba8352a114af75945a172e5b26ef0b7d79f5edfe6a1dc65cd905f90a25b5050565b5f816001600160a01b031663c12c21c06040518163ffffffff1660e01b8152600401602060405180830381865afa158015610384573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103a89190610ecf565b90506103b48183610a04565b6001600160a01b038082165f9081526002602090815260408083209386168352929052908120906103e482610b30565b90505b801561049d575f6103fb835f198401610b39565b90506104078382610b44565b506001600160a01b038181165f8181526001602081815260408084208a871680865293018252808420958b1680855295825280842080547fffffffffffffffff000000000000000000000000000000000000000000000000169055519283529092917f802ff2032a278b366ea5f1bafd7e2e4ffb3d106da98810fa7cd9b495be1e33a4910160405180910390a4505f19016103e7565b50505050565b5f80826001600160a01b031663c12c21c06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104e1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105059190610ecf565b6001600160a01b038086165f908152600160208181526040808420958516845294909101815283822092871682529190915220546001600160c01b03169150505b92915050565b6105546109ab565b61055d5f610b58565b565b6001600160a01b0382165f908152600160205260408120805482919060ff1615610590575f6001925092505061062a565b5f846001600160a01b031663c12c21c06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105cd573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105f19190610ecf565b6001600160a01b039081165f90815260019093016020908152604080852092881685529190528220546001600160c01b03169350909150505b9250929050565b5f8361063c81610bbf565b5f846001600160a01b031663c12c21c06040518163ffffffff1660e01b8152600401602060405180830381865afa158015610679573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061069d9190610ecf565b90506106a98186610a04565b6001600160a01b038087165f908152600160209081526040808320858516845260028352818420948a1684529390915290206001600160c01b038616156107e057856001600160c01b0316886001600160a01b0316632e7ad41f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610730573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107549190610eea565b6001600160c01b031614610794576040517f3f7a58ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815460ff16156107d0576040517ff472068000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6107da8189610bff565b506107ec565b6107ea8189610b44565b505b6107f581610b30565b94506005851115610832576040517f0d02d57000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038381165f9081526001840160209081526040808320938b16835292905220546001600160c01b038781169116146108ff576001600160a01b038381165f81815260018501602090815260408083208c86168085529083529281902080547fffffffffffffffff000000000000000000000000000000000000000000000000166001600160c01b038d16908117909155905190815291938c16917f802ff2032a278b366ea5f1bafd7e2e4ffb3d106da98810fa7cd9b495be1e33a4910160405180910390a45b505050509392505050565b6109126109ab565b6001600160a01b0381166109935760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61099c81610b58565b50565b60605f6102d583610c13565b5f546001600160a01b0316331461055d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161098a565b6040517fc53afb1e0000000000000000000000000000000000000000000000000000000081526001600160a01b03828116600483015283169063c53afb1e90602401602060405180830381865afa158015610a61573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a859190610ecf565b50336001600160a01b0316826001600160a01b0316632f7a18816040518163ffffffff1660e01b8152600401602060405180830381865afa158015610acc573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610af09190610ecf565b6001600160a01b031614610343576040517f0c1d6a3f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f610546825490565b5f6102d58383610c6c565b5f6102d5836001600160a01b038416610c92565b5f80546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811661099c576040517fb2335f2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6102d5836001600160a01b038416610d75565b6060815f01805480602002602001604051908101604052809291908181526020018280548015610c6057602002820191905f5260205f20905b815481526020019060010190808311610c4c575b50505050509050919050565b5f825f018281548110610c8157610c81610f05565b905f5260205f200154905092915050565b5f8181526001830160205260408120548015610d6c575f610cb4600183610f19565b85549091505f90610cc790600190610f19565b9050818114610d26575f865f018281548110610ce557610ce5610f05565b905f5260205f200154905080875f018481548110610d0557610d05610f05565b5f918252602080832090910192909255918252600188019052604090208390555b8554869080610d3757610d37610f38565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050610546565b5f915050610546565b5f818152600183016020526040812054610dba57508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610546565b505f610546565b6001600160a01b038116811461099c575f80fd5b5f60208284031215610de5575f80fd5b81356102d581610dc1565b602080825282518282018190525f9190848201906040850190845b81811015610e305783516001600160a01b031683529284019291840191600101610e0b565b50909695505050505050565b5f8060408385031215610e4d575f80fd5b8235610e5881610dc1565b91506020830135610e6881610dc1565b809150509250929050565b6001600160c01b038116811461099c575f80fd5b5f805f60608486031215610e99575f80fd5b8335610ea481610dc1565b92506020840135610eb481610dc1565b91506040840135610ec481610e73565b809150509250925092565b5f60208284031215610edf575f80fd5b81516102d581610dc1565b5f60208284031215610efa575f80fd5b81516102d581610e73565b634e487b7160e01b5f52603260045260245ffd5b8181038181111561054657634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52603160045260245ffdfea164736f6c6343000817000a000000000000000000000000f7f0a609bfab9a0a98786951ef10e5fe26cc1e38

Deployed Bytecode

0x608060405234801561000f575f80fd5b50600436106100cf575f3560e01c80638da5cb5b1161007d578063cb2ef6f711610058578063cb2ef6f7146101cd578063f2fde38b146101f4578063f439dc6714610207575f80fd5b80638da5cb5b1461016e578063997a072314610188578063c5b73ed0146101ba575f80fd5b806354fd4d50116100ad57806354fd4d501461012457806356e0381a1461013b578063715018a614610166575f80fd5b80630e2b0c94146100d3578063348f46ab146100fc57806342a3b4d614610111575b5f80fd5b6100e66100e1366004610dd5565b610242565b6040516100f39190610df0565b60405180910390f35b61010f61010a366004610dd5565b6102dc565b005b61010f61011f366004610dd5565b610347565b61012d61013681565b6040519081526020016100f3565b61014e610149366004610e3c565b6104a3565b6040516001600160c01b0390911681526020016100f3565b61010f61054c565b5f546040516001600160a01b0390911681526020016100f3565b61019b610196366004610e3c565b61055f565b604080516001600160c01b0390931683529015156020830152016100f3565b61012d6101c8366004610e87565b610631565b61012d7f424f545f4c49535400000000000000000000000000000000000000000000000081565b61010f610202366004610dd5565b61090a565b610232610215366004610dd5565b6001600160a01b03165f9081526001602052604090205460ff1690565b60405190151581526020016100f3565b60605f826001600160a01b031663c12c21c06040518163ffffffff1660e01b8152600401602060405180830381865afa158015610281573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102a59190610ecf565b6001600160a01b038082165f9081526002602090815260408083209388168352929052209091506102d59061099f565b9392505050565b6102e46109ab565b6001600160a01b0381165f908152600160205260409020805460ff1661034357805460ff191660011781556040516001600160a01b038316907fd4f28d440c8ecafba8352a114af75945a172e5b26ef0b7d79f5edfe6a1dc65cd905f90a25b5050565b5f816001600160a01b031663c12c21c06040518163ffffffff1660e01b8152600401602060405180830381865afa158015610384573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103a89190610ecf565b90506103b48183610a04565b6001600160a01b038082165f9081526002602090815260408083209386168352929052908120906103e482610b30565b90505b801561049d575f6103fb835f198401610b39565b90506104078382610b44565b506001600160a01b038181165f8181526001602081815260408084208a871680865293018252808420958b1680855295825280842080547fffffffffffffffff000000000000000000000000000000000000000000000000169055519283529092917f802ff2032a278b366ea5f1bafd7e2e4ffb3d106da98810fa7cd9b495be1e33a4910160405180910390a4505f19016103e7565b50505050565b5f80826001600160a01b031663c12c21c06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104e1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105059190610ecf565b6001600160a01b038086165f908152600160208181526040808420958516845294909101815283822092871682529190915220546001600160c01b03169150505b92915050565b6105546109ab565b61055d5f610b58565b565b6001600160a01b0382165f908152600160205260408120805482919060ff1615610590575f6001925092505061062a565b5f846001600160a01b031663c12c21c06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105cd573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105f19190610ecf565b6001600160a01b039081165f90815260019093016020908152604080852092881685529190528220546001600160c01b03169350909150505b9250929050565b5f8361063c81610bbf565b5f846001600160a01b031663c12c21c06040518163ffffffff1660e01b8152600401602060405180830381865afa158015610679573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061069d9190610ecf565b90506106a98186610a04565b6001600160a01b038087165f908152600160209081526040808320858516845260028352818420948a1684529390915290206001600160c01b038616156107e057856001600160c01b0316886001600160a01b0316632e7ad41f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610730573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107549190610eea565b6001600160c01b031614610794576040517f3f7a58ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815460ff16156107d0576040517ff472068000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6107da8189610bff565b506107ec565b6107ea8189610b44565b505b6107f581610b30565b94506005851115610832576040517f0d02d57000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b038381165f9081526001840160209081526040808320938b16835292905220546001600160c01b038781169116146108ff576001600160a01b038381165f81815260018501602090815260408083208c86168085529083529281902080547fffffffffffffffff000000000000000000000000000000000000000000000000166001600160c01b038d16908117909155905190815291938c16917f802ff2032a278b366ea5f1bafd7e2e4ffb3d106da98810fa7cd9b495be1e33a4910160405180910390a45b505050509392505050565b6109126109ab565b6001600160a01b0381166109935760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61099c81610b58565b50565b60605f6102d583610c13565b5f546001600160a01b0316331461055d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161098a565b6040517fc53afb1e0000000000000000000000000000000000000000000000000000000081526001600160a01b03828116600483015283169063c53afb1e90602401602060405180830381865afa158015610a61573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a859190610ecf565b50336001600160a01b0316826001600160a01b0316632f7a18816040518163ffffffff1660e01b8152600401602060405180830381865afa158015610acc573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610af09190610ecf565b6001600160a01b031614610343576040517f0c1d6a3f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f610546825490565b5f6102d58383610c6c565b5f6102d5836001600160a01b038416610c92565b5f80546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811661099c576040517fb2335f2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6102d5836001600160a01b038416610d75565b6060815f01805480602002602001604051908101604052809291908181526020018280548015610c6057602002820191905f5260205f20905b815481526020019060010190808311610c4c575b50505050509050919050565b5f825f018281548110610c8157610c81610f05565b905f5260205f200154905092915050565b5f8181526001830160205260408120548015610d6c575f610cb4600183610f19565b85549091505f90610cc790600190610f19565b9050818114610d26575f865f018281548110610ce557610ce5610f05565b905f5260205f200154905080875f018481548110610d0557610d05610f05565b5f918252602080832090910192909255918252600188019052604090208390555b8554869080610d3757610d37610f38565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050610546565b5f915050610546565b5f818152600183016020526040812054610dba57508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610546565b505f610546565b6001600160a01b038116811461099c575f80fd5b5f60208284031215610de5575f80fd5b81356102d581610dc1565b602080825282518282018190525f9190848201906040850190845b81811015610e305783516001600160a01b031683529284019291840191600101610e0b565b50909695505050505050565b5f8060408385031215610e4d575f80fd5b8235610e5881610dc1565b91506020830135610e6881610dc1565b809150509250929050565b6001600160c01b038116811461099c575f80fd5b5f805f60608486031215610e99575f80fd5b8335610ea481610dc1565b92506020840135610eb481610dc1565b91506040840135610ec481610e73565b809150509250925092565b5f60208284031215610edf575f80fd5b81516102d581610dc1565b5f60208284031215610efa575f80fd5b81516102d581610e73565b634e487b7160e01b5f52603260045260245ffd5b8181038181111561054657634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52603160045260245ffdfea164736f6c6343000817000a

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000f7f0a609bfab9a0a98786951ef10e5fe26cc1e38

-----Decoded View---------------
Arg [0] : addressProvider_ (address): 0xF7f0a609BfAb9a0A98786951ef10e5FE26cC1E38

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000f7f0a609bfab9a0a98786951ef10e5fe26cc1e38


Block Transaction Gas Used Reward
view all blocks produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.