ETH Price: $2,078.19 (-1.16%)
Gas: 0.04 Gwei

Contract

0x0061E516886A0540F63157f112C0588eE0651dCF
 

Overview

ETH Balance

0 ETH

Eth 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 Method Block
From
To
0x60c06040233341982025-09-10 17:36:11185 days ago1757525771  Contract Creation0 ETH
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
JBDirectory

Compiler Version
v0.8.23+commit.f704f362

Optimization Enabled:
Yes with 200 runs

Other Settings:
paris EvmVersion
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import {JBPermissionIds} from "@bananapus/permission-ids-v5/src/JBPermissionIds.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";

import {JBPermissioned} from "./abstract/JBPermissioned.sol";
import {IJBDirectory} from "./interfaces/IJBDirectory.sol";
import {IJBDirectoryAccessControl} from "./interfaces/IJBDirectoryAccessControl.sol";
import {IJBMigratable} from "./interfaces/IJBMigratable.sol";
import {IJBPermissions} from "./interfaces/IJBPermissions.sol";
import {IJBProjects} from "./interfaces/IJBProjects.sol";
import {IJBTerminal} from "./interfaces/IJBTerminal.sol";

/// @notice `JBDirectory` tracks the terminals and the controller used by each project.
/// @dev Tracks which `IJBTerminal`s each project is currently accepting funds through, and which `IJBController` is
/// managing each project's tokens and rulesets.
contract JBDirectory is JBPermissioned, Ownable, IJBDirectory {
    //*********************************************************************//
    // --------------------------- custom errors ------------------------- //
    //*********************************************************************//

    error JBDirectory_DuplicateTerminals(IJBTerminal terminal);
    error JBDirectory_InvalidProjectIdInDirectory(uint256 projectId, uint256 limit);
    error JBDirectory_SetControllerNotAllowed();
    error JBDirectory_SetTerminalsNotAllowed();
    error JBDirectory_TokenNotAccepted(uint256 projectId, address token, IJBTerminal terminal);

    //*********************************************************************//
    // ---------------- public immutable stored properties --------------- //
    //*********************************************************************//

    /// @notice Mints ERC-721s that represent project ownership and transfers.
    IJBProjects public immutable override PROJECTS;

    //*********************************************************************//
    // --------------------- public stored properties -------------------- //
    //*********************************************************************//

    /// @notice The specified project's controller, which dictates how its terminals interact with its tokens and
    /// rulesets.
    /// @custom:param projectId The ID of the project to get the controller of.
    mapping(uint256 projectId => IERC165) public override controllerOf;

    /// @notice Whether the specified address is allowed to set a project's first controller on their behalf.
    /// @dev These addresses/contracts have been vetted by this contract's owner.
    /// @custom:param addr The address to check.
    mapping(address addr => bool) public override isAllowedToSetFirstController;

    //*********************************************************************//
    // --------------------- internal stored properties ------------------ //
    //*********************************************************************//

    /// @notice The primary terminal that a project uses for the specified token.
    /// @custom:param projectId The ID of the project to get the primary terminal of.
    /// @custom:param token The token that the terminal accepts.
    mapping(uint256 projectId => mapping(address token => IJBTerminal)) internal _primaryTerminalOf;

    /// @notice The specified project's terminals.
    /// @custom:param projectId The ID of the project to get the terminals of.
    mapping(uint256 projectId => IJBTerminal[]) internal _terminalsOf;

    //*********************************************************************//
    // -------------------------- constructor ---------------------------- //
    //*********************************************************************//

    /// @param permissions A contract storing permissions.
    /// @param projects A contract which mints ERC-721s that represent project ownership and transfers.
    /// @param owner The address that will own the contract.
    constructor(
        IJBPermissions permissions,
        IJBProjects projects,
        address owner
    )
        JBPermissioned(permissions)
        Ownable(owner)
    {
        PROJECTS = projects;
    }

    //*********************************************************************//
    // ------------------------- external views -------------------------- //
    //*********************************************************************//

    /// @notice The primary terminal that a project uses for the specified token.
    /// @dev Returns the first terminal that accepts the token if the project hasn't explicitly set a primary terminal
    /// for it.
    /// @dev Returns the zero address if no terminal accepts the token.
    /// @param projectId The ID of the project to get the primary terminal of.
    /// @param token The token that the terminal accepts.
    /// @return The primary terminal's address.
    function primaryTerminalOf(uint256 projectId, address token) external view override returns (IJBTerminal) {
        // Keep a reference to the primary terminal for the provided project ID and token.
        IJBTerminal primaryTerminal = _primaryTerminalOf[projectId][token];

        // If a primary terminal for the token was explicitly set and it's one of the project's terminals, return it.
        if (primaryTerminal != IJBTerminal(address(0)) && isTerminalOf(projectId, primaryTerminal)) {
            return primaryTerminal;
        }

        // Keep a reference to the project's terminals.
        IJBTerminal[] memory terminals = _terminalsOf[projectId];

        // Keep a reference to the number of terminals the project has.
        uint256 numberOfTerminals = terminals.length;

        // Return the first terminal which accepts the specified token.
        for (uint256 i; i < numberOfTerminals; i++) {
            // Keep a reference to the terminal being iterated on.
            IJBTerminal terminal = terminals[i];

            // If the terminal accepts the specified token, return it.
            // slither-disable-next-line calls-loop
            if (terminal.accountingContextForTokenOf(projectId, token).token != address(0)) {
                return terminal;
            }
        }

        // Not found.
        return IJBTerminal(address(0));
    }

    /// @notice The specified project's terminals.
    /// @param projectId The ID of the project to get the terminals of.
    /// @return An array of the project's terminal addresses.
    function terminalsOf(uint256 projectId) external view override returns (IJBTerminal[] memory) {
        return _terminalsOf[projectId];
    }

    //*********************************************************************//
    // -------------------------- public views --------------------------- //
    //*********************************************************************//

    /// @notice Check if a project uses a specific terminal.
    /// @param projectId The ID of the project to check.
    /// @param terminal The terminal to check for.
    /// @return A flag indicating whether the project uses the terminal.
    function isTerminalOf(uint256 projectId, IJBTerminal terminal) public view override returns (bool) {
        // Keep a reference to the project's terminals.
        IJBTerminal[] memory terminals = _terminalsOf[projectId];

        // Keep a reference to the number of terminals the project has.
        uint256 numberOfTerminals = terminals.length;

        // Loop through and return true if the terminal is found.
        for (uint256 i; i < numberOfTerminals; i++) {
            if (terminals[i] == terminal) return true;
        }

        // Otherwise, return false.
        return false;
    }

    //*********************************************************************//
    // ---------------------- external transactions ---------------------- //
    //*********************************************************************//

    /// @notice Add or remove an address/contract from a list of trusted addresses which are allowed to set a first
    /// controller for projects.
    /// @dev Only this contract's owner can call this function.
    /// @dev These addresses are vetted controllers as well as contracts designed to launch new projects.
    /// @dev A project can set its own controller without being on this list.
    /// @dev If you would like to add an address/contract to this list, please reach out to this contract's owner.
    /// @param addr The address to allow or not allow.
    /// @param flag Whether the address is allowed to set first controllers for projects. Use `true` to allow and
    /// `false` to not allow.
    function setIsAllowedToSetFirstController(address addr, bool flag) external override onlyOwner {
        // Set the flag in the allowlist.
        isAllowedToSetFirstController[addr] = flag;

        emit SetIsAllowedToSetFirstController({addr: addr, isAllowed: flag, caller: msg.sender});
    }

    /// @notice Set a project's controller. Controllers manage how terminals interact with tokens and rulesets.
    /// @dev Can only be called if:
    /// - The ruleset's metadata has `allowSetController` enabled, and the message's sender is the project's owner or an
    /// address with the owner's permission to `SET_CONTROLLER`.
    /// - OR the message's sender is the project's current controller.
    /// - OR an address which `isAllowedToSetFirstController` is setting a project's first controller.
    /// @param projectId The ID of the project whose controller is being set.
    /// @param controller The address of the controller to set.
    function setControllerOf(uint256 projectId, IERC165 controller) external override {
        // Keep a reference to the current controller.
        IERC165 currentController = controllerOf[projectId];

        // Enforce permissions.
        _requirePermissionAllowingOverrideFrom({
            account: PROJECTS.ownerOf(projectId),
            projectId: projectId,
            permissionId: JBPermissionIds.SET_CONTROLLER,
            alsoGrantAccessIf: (isAllowedToSetFirstController[msg.sender] && address(currentController) == address(0))
        });

        // The project must exist.
        if (projectId > PROJECTS.count()) revert JBDirectory_InvalidProjectIdInDirectory(projectId, PROJECTS.count());

        // Get a reference to a flag indicating whether the project is allowed to set its controller.
        // Setting the controller is allowed if the project doesn't have a controller,
        // OR if the caller is the current controller,
        // OR if the project's ruleset allows setting the controller.
        bool allowSetController = address(currentController) == address(0)
            || !currentController.supportsInterface(type(IJBDirectoryAccessControl).interfaceId)
            ? true
            : IJBDirectoryAccessControl(address(currentController)).setControllerAllowed(projectId);

        // If setting the controller is not allowed, revert.
        if (!allowSetController) {
            revert JBDirectory_SetControllerNotAllowed();
        }

        // Prepare the new controller to receive the project.
        if (address(currentController) != address(0) && controller.supportsInterface(type(IJBMigratable).interfaceId)) {
            IJBMigratable(address(controller)).beforeReceiveMigrationFrom(currentController, projectId);
        }

        // Set the new controller.
        // slither-disable-next-line reentrancy-no-eth
        controllerOf[projectId] = controller;

        emit SetController({projectId: projectId, controller: controller, caller: msg.sender});

        // Migrate if needed.
        if (
            address(currentController) != address(0)
                && currentController.supportsInterface(type(IJBMigratable).interfaceId)
        ) {
            IJBMigratable(address(currentController)).migrate(projectId, controller);
        }
    }

    /// @notice Set a project's primary terminal for a token.
    /// @dev The primary terminal for a token is where payments in that token are routed to by default.
    /// @dev This is useful in cases where a project has multiple terminals which accept the same token.
    /// @dev Can only be called by the project's owner, or an address with the owner's permission to
    /// `SET_PRIMARY_TERMINAL`.
    /// @param projectId The ID of the project whose primary terminal is being set.
    /// @param token The token to set the primary terminal for.
    /// @param terminal The terminal being set as the primary terminal.
    function setPrimaryTerminalOf(uint256 projectId, address token, IJBTerminal terminal) external override {
        // Enforce permissions.
        _requirePermissionFrom({
            account: PROJECTS.ownerOf(projectId),
            projectId: projectId,
            permissionId: JBPermissionIds.SET_PRIMARY_TERMINAL
        });

        // If the terminal doesn't accept the token, revert.
        if (terminal.accountingContextForTokenOf(projectId, token).token == address(0)) {
            revert JBDirectory_TokenNotAccepted(projectId, token, terminal);
        }

        // If the terminal hasn't already been added to the project, add it.
        _addTerminalIfNeeded(projectId, terminal);

        // Store the terminal as the project's primary terminal for the token.
        _primaryTerminalOf[projectId][token] = terminal;

        emit SetPrimaryTerminal({projectId: projectId, token: token, terminal: terminal, caller: msg.sender});
    }

    /// @notice Set a project's terminals.
    /// @dev Can only be called by the project's owner, an address with the owner's permission to `SET_TERMINALS`, or
    /// the project's controller.
    /// @dev Unless the caller is the project's controller, the project's ruleset must allow setting terminals.
    /// @param projectId The ID of the project whose terminals are being set.
    /// @param terminals An array of terminal addresses to set for the project.
    function setTerminalsOf(uint256 projectId, IJBTerminal[] calldata terminals) external override {
        // Enforce permissions.
        _requirePermissionAllowingOverrideFrom({
            account: PROJECTS.ownerOf(projectId),
            projectId: projectId,
            permissionId: JBPermissionIds.SET_TERMINALS,
            alsoGrantAccessIf: msg.sender == address(controllerOf[projectId])
        });

        // Keep a reference to the project's controller.
        IERC165 controller = controllerOf[projectId];

        // Get a reference to the flag indicating whether the project is allowed to set its terminals.
        bool allowSetTerminals = !controller.supportsInterface(type(IJBDirectoryAccessControl).interfaceId)
            || IJBDirectoryAccessControl(address(controller)).setTerminalsAllowed(projectId);

        // If the caller is not the project's controller, the project's ruleset must allow setting terminals.
        if (msg.sender != address(controllerOf[projectId]) && !allowSetTerminals) {
            revert JBDirectory_SetTerminalsNotAllowed();
        }

        // Set the stored terminals for the project.
        _terminalsOf[projectId] = terminals;

        // If there are any duplicates, revert.
        if (terminals.length > 1) {
            for (uint256 i; i < terminals.length; i++) {
                for (uint256 j = i + 1; j < terminals.length; j++) {
                    if (terminals[i] == terminals[j]) revert JBDirectory_DuplicateTerminals(terminals[i]);
                }
            }
        }
        emit SetTerminals({projectId: projectId, terminals: terminals, caller: msg.sender});
    }

    //*********************************************************************//
    // ------------------------ internal functions ----------------------- //
    //*********************************************************************//

    /// @notice If a terminal hasn't already been added to a project's list of terminals, add it.
    /// @dev The project's ruleset must have `allowSetTerminals` set to `true`.
    /// @param projectId The ID of the project to add the terminal to.
    /// @param terminal The terminal to add.
    function _addTerminalIfNeeded(uint256 projectId, IJBTerminal terminal) internal {
        // Ensure that the terminal has not already been added.
        if (isTerminalOf(projectId, terminal)) return;

        // Keep a reference to the current controller.
        IERC165 controller = controllerOf[projectId];

        // Get a reference to a flag indicating whether the project is allowed to set its terminals.
        bool allowSetTerminals = !controller.supportsInterface(type(IJBDirectoryAccessControl).interfaceId)
            || IJBDirectoryAccessControl(address(controller)).setTerminalsAllowed(projectId);

        // The project's ruleset must allow setting terminals.
        if (!allowSetTerminals) {
            revert JBDirectory_SetTerminalsNotAllowed();
        }

        // Add the new terminal.
        _terminalsOf[projectId].push(terminal);

        emit AddTerminal({projectId: projectId, terminal: terminal, caller: msg.sender});
    }
}

File 2 of 20 : JBPermissionIds.sol
// SPDX-License-Identifier: MIT
// slither-disable-next-line solc-version
pragma solidity ^0.8.0;

/// @notice Permission IDs for `JBPermissions`, used throughout the Bananapus ecosystem. See
/// [`JBPermissions`](https://github.com/Bananapus/nana-core/blob/main/src/JBPermissions.sol)
/// @dev `JBPermissions` allows one address to grant another address permission to call functions in Juicebox contracts
/// on their behalf. Each ID in `JBPermissionIds` grants access to a specific set of these functions.
library JBPermissionIds {
    uint8 internal constant ROOT = 1; // All permissions across every contract. Very dangerous. BE CAREFUL!

    /* Used by `nana-core`: https://github.com/Bananapus/nana-core */
    uint8 internal constant QUEUE_RULESETS = 2; // Permission to call `JBController.queueRulesetsOf` and
        // `JBController.launchRulesetsFor`.
    uint8 internal constant CASH_OUT_TOKENS = 3; // Permission to call `JBMultiTerminal.cashOutTokensOf`.
    uint8 internal constant SEND_PAYOUTS = 4; // Permission to call `JBMultiTerminal.sendPayoutsOf`.
    uint8 internal constant MIGRATE_TERMINAL = 5; // Permission to call `JBMultiTerminal.migrateBalanceOf`.
    uint8 internal constant SET_PROJECT_URI = 6; // Permission to call `JBController.setUriOf`.
    uint8 internal constant DEPLOY_ERC20 = 7; // Permission to call `JBController.deployERC20For`.
    uint8 internal constant SET_TOKEN = 8; // Permission to call `JBController.setTokenFor`.
    uint8 internal constant MINT_TOKENS = 9; // Permission to call `JBController.mintTokensOf`.
    uint8 internal constant BURN_TOKENS = 10; // Permission to call `JBController.burnTokensOf`.
    uint8 internal constant CLAIM_TOKENS = 11; // Permission to call `JBController.claimTokensFor`.
    uint8 internal constant TRANSFER_CREDITS = 12; // Permission to call `JBController.transferCreditsFrom`.
    uint8 internal constant SET_CONTROLLER = 13; // Permission to call `JBDirectory.setControllerOf`.
    uint8 internal constant SET_TERMINALS = 14; // Permission to call `JBDirectory.setTerminalsOf`.
    // Be careful - `SET_TERMINALS` can be used to remove the primary terminal.
    uint8 internal constant SET_PRIMARY_TERMINAL = 15; // Permission to call `JBDirectory.setPrimaryTerminalOf`.
    uint8 internal constant USE_ALLOWANCE = 16; // Permission to call `JBMultiTerminal.useAllowanceOf`.
    uint8 internal constant SET_SPLIT_GROUPS = 17; // Permission to call `JBController.setSplitGroupsOf`.
    uint8 internal constant ADD_PRICE_FEED = 18; // Permission to call `JBPrices.addPriceFeedFor`.
    uint8 internal constant ADD_ACCOUNTING_CONTEXTS = 19; // Permission to call
        // `JBMultiTerminal.addAccountingContextsFor`.

    /* Used by `nana-721-hook`: https://github.com/Bananapus/nana-721-hook */
    uint8 internal constant ADJUST_721_TIERS = 20; // Permission to call `JB721TiersHook.adjustTiers`.
    uint8 internal constant SET_721_METADATA = 21; // Permission to call `JB721TiersHook.setMetadata`.
    uint8 internal constant MINT_721 = 22; // Permission to call `JB721TiersHook.mintFor`.
    uint8 internal constant SET_721_DISCOUNT_PERCENT = 23; // Permission to call `JB721TiersHook.setDiscountPercentOf`.

    /* Used by `nana-buyback-hook`: https://github.com/Bananapus/nana-buyback-hook */
    uint8 internal constant SET_BUYBACK_TWAP = 24; // Permission to call `JBBuybackHook.setTwapWindowOf` and
        // `JBBuybackHook.setTwapSlippageToleranceOf`.
    uint8 internal constant SET_BUYBACK_POOL = 25; // Permission to call `JBBuybackHook.setPoolFor`.

    /* Used by `nana-swap-terminal`: https://github.com/Bananapus/nana-swap-terminal */
    uint8 internal constant ADD_SWAP_TERMINAL_POOL = 26; // Permission to call `JBSwapTerminal.addDefaultPool`.
    uint8 internal constant ADD_SWAP_TERMINAL_TWAP_PARAMS = 27; // Permission to call
        // `JBSwapTerminal.addTwapParamsFor`.

    /* Used by `nana-suckers`: https://github.com/Bananapus/nana-suckers */
    uint8 internal constant MAP_SUCKER_TOKEN = 28; // Permission to call `BPSucker.mapToken`.
    uint8 internal constant DEPLOY_SUCKERS = 29; // Permission to call `BPSuckerRegistry.deploySuckersFor`.
    uint8 internal constant SUCKER_SAFETY = 30; // Permission to call `BPSucker.enableEmergencyHatchFor` and
        // `BPSucker.setDeprecation`.
}

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

pragma solidity ^0.8.20;

import {Context} from "../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.
 *
 * The initial owner is set to the address provided by the deployer. 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;

    /**
     * @dev The caller account is not authorized to perform an operation.
     */
    error OwnableUnauthorizedAccount(address account);

    /**
     * @dev The owner is not a valid owner account. (eg. `address(0)`)
     */
    error OwnableInvalidOwner(address owner);

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

    /**
     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.
     */
    constructor(address initialOwner) {
        if (initialOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(initialOwner);
    }

    /**
     * @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 {
        if (owner() != _msgSender()) {
            revert OwnableUnauthorizedAccount(_msgSender());
        }
    }

    /**
     * @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 {
        if (newOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _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 v5.1.0) (token/ERC721/IERC721.sol)

pragma solidity ^0.8.20;

import {IERC165} from "../../utils/introspection/IERC165.sol";

/**
 * @dev Required interface of an ERC-721 compliant contract.
 */
interface IERC721 is IERC165 {
    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
     */
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
     */
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /**
     * @dev Returns the number of tokens in ``owner``'s account.
     */
    function balanceOf(address owner) external view returns (uint256 balance);

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon
     *   a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC-721 protocol to prevent tokens from being forever locked.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or
     *   {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon
     *   a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(address from, address to, uint256 tokenId) external;

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC-721
     * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
     * understand this adds an external call which potentially creates a reentrancy vulnerability.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 tokenId) external;

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account.
     * The approval is cleared when the token is transferred.
     *
     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.
     *
     * Requirements:
     *
     * - The caller must own the token or be an approved operator.
     * - `tokenId` must exist.
     *
     * Emits an {Approval} event.
     */
    function approve(address to, uint256 tokenId) external;

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the address zero.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool approved) external;

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) external view returns (address operator);

    /**
     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
     *
     * See {setApprovalForAll}
     */
    function isApprovedForAll(address owner, address operator) external view returns (bool);
}

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

pragma solidity ^0.8.20;

/**
 * @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 v5.1.0) (utils/introspection/IERC165.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC-165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[ERC].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {Context} from "@openzeppelin/contracts/utils/Context.sol";

import {IJBPermissioned} from "./../interfaces/IJBPermissioned.sol";
import {IJBPermissions} from "./../interfaces/IJBPermissions.sol";

/// @notice Modifiers to allow access to transactions based on which permissions the message's sender has.
abstract contract JBPermissioned is Context, IJBPermissioned {
    //*********************************************************************//
    // --------------------------- custom errors -------------------------- //
    //*********************************************************************//

    error JBPermissioned_Unauthorized(address account, address sender, uint256 projectId, uint256 permissionId);

    //*********************************************************************//
    // ---------------- public immutable stored properties --------------- //
    //*********************************************************************//

    /// @notice A contract storing permissions.
    IJBPermissions public immutable override PERMISSIONS;

    //*********************************************************************//
    // -------------------------- constructor ---------------------------- //
    //*********************************************************************//

    /// @param permissions A contract storing permissions.
    constructor(IJBPermissions permissions) {
        PERMISSIONS = permissions;
    }

    //*********************************************************************//
    // -------------------------- internal views ------------------------- //
    //*********************************************************************//

    /// @notice Require the message sender to be the account or have the relevant permission.
    /// @param account The account to allow.
    /// @param projectId The project ID to check the permission under.
    /// @param permissionId The required permission ID. The operator must have this permission within the specified
    /// project ID.
    function _requirePermissionFrom(address account, uint256 projectId, uint256 permissionId) internal view {
        address sender = _msgSender();
        if (
            sender != account
                && !PERMISSIONS.hasPermission({
                    operator: sender,
                    account: account,
                    projectId: projectId,
                    permissionId: permissionId,
                    includeRoot: true,
                    includeWildcardProjectId: true
                })
        ) revert JBPermissioned_Unauthorized(account, sender, projectId, permissionId);
    }

    /// @notice If the 'alsoGrantAccessIf' condition is truthy, proceed. Otherwise, require the message sender to be the
    /// account or
    /// have the relevant permission.
    /// @param account The account to allow.
    /// @param projectId The project ID to check the permission under.
    /// @param permissionId The required permission ID. The operator must have this permission within the specified
    /// project ID.
    /// @param alsoGrantAccessIf An override condition which will allow access regardless of permissions.
    function _requirePermissionAllowingOverrideFrom(
        address account,
        uint256 projectId,
        uint256 permissionId,
        bool alsoGrantAccessIf
    )
        internal
        view
    {
        if (alsoGrantAccessIf) return;
        _requirePermissionFrom(account, projectId, permissionId);
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";

import {IJBProjects} from "./IJBProjects.sol";
import {IJBTerminal} from "./IJBTerminal.sol";

interface IJBDirectory {
    event AddTerminal(uint256 indexed projectId, IJBTerminal indexed terminal, address caller);
    event SetController(uint256 indexed projectId, IERC165 indexed controller, address caller);
    event SetIsAllowedToSetFirstController(address indexed addr, bool indexed isAllowed, address caller);
    event SetPrimaryTerminal(
        uint256 indexed projectId, address indexed token, IJBTerminal indexed terminal, address caller
    );
    event SetTerminals(uint256 indexed projectId, IJBTerminal[] terminals, address caller);

    function PROJECTS() external view returns (IJBProjects);

    function controllerOf(uint256 projectId) external view returns (IERC165);
    function isAllowedToSetFirstController(address account) external view returns (bool);
    function isTerminalOf(uint256 projectId, IJBTerminal terminal) external view returns (bool);
    function primaryTerminalOf(uint256 projectId, address token) external view returns (IJBTerminal);
    function terminalsOf(uint256 projectId) external view returns (IJBTerminal[] memory);

    function setControllerOf(uint256 projectId, IERC165 controller) external;
    function setIsAllowedToSetFirstController(address account, bool flag) external;
    function setPrimaryTerminalOf(uint256 projectId, address token, IJBTerminal terminal) external;
    function setTerminalsOf(uint256 projectId, IJBTerminal[] calldata terminals) external;
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IJBDirectoryAccessControl {
    function setControllerAllowed(uint256 projectId) external view returns (bool);
    function setTerminalsAllowed(uint256 projectId) external view returns (bool);
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";

interface IJBMigratable is IERC165 {
    event Migrate(uint256 indexed projectId, IERC165 to, address caller);

    function migrate(uint256 projectId, IERC165 to) external;
    function beforeReceiveMigrationFrom(IERC165 from, uint256 projectId) external;
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";

import {JBAfterPayRecordedContext} from "./../structs/JBAfterPayRecordedContext.sol";

/// @notice Hook called after a terminal's `pay(...)` logic completes (if passed by the ruleset's data hook).
interface IJBPayHook is IERC165 {
    /// @notice This function is called by the terminal's `pay(...)` function after the payment has been recorded in the
    /// terminal store.
    /// @dev Critical business logic should be protected by appropriate access control.
    /// @param context The context passed in by the terminal, as a `JBAfterPayRecordedContext` struct.
    function afterPayRecordedWith(JBAfterPayRecordedContext calldata context) external payable;
}

File 12 of 20 : IJBPermissioned.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {IJBPermissions} from "./IJBPermissions.sol";

interface IJBPermissioned {
    function PERMISSIONS() external view returns (IJBPermissions);
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {JBPermissionsData} from "./../structs/JBPermissionsData.sol";

interface IJBPermissions {
    event OperatorPermissionsSet(
        address indexed operator,
        address indexed account,
        uint256 indexed projectId,
        uint8[] permissionIds,
        uint256 packed,
        address caller
    );

    function WILDCARD_PROJECT_ID() external view returns (uint256);

    function permissionsOf(address operator, address account, uint256 projectId) external view returns (uint256);

    function hasPermission(
        address operator,
        address account,
        uint256 projectId,
        uint256 permissionId,
        bool includeRoot,
        bool includeWildcardProjectId
    )
        external
        view
        returns (bool);

    function hasPermissions(
        address operator,
        address account,
        uint256 projectId,
        uint256[] calldata permissionIds,
        bool includeRoot,
        bool includeWildcardProjectId
    )
        external
        view
        returns (bool);

    function setPermissionsFor(address account, JBPermissionsData calldata permissionsData) external;
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol";

import {IJBTokenUriResolver} from "./IJBTokenUriResolver.sol";

interface IJBProjects is IERC721 {
    event Create(uint256 indexed projectId, address indexed owner, address caller);
    event SetTokenUriResolver(IJBTokenUriResolver indexed resolver, address caller);

    function count() external view returns (uint256);
    function tokenUriResolver() external view returns (IJBTokenUriResolver);

    function createFor(address owner) external returns (uint256 projectId);
    function setTokenUriResolver(IJBTokenUriResolver resolver) external;
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";

import {IJBPayHook} from "./IJBPayHook.sol";
import {JBAccountingContext} from "../structs/JBAccountingContext.sol";
import {JBAfterPayRecordedContext} from "../structs/JBAfterPayRecordedContext.sol";

/// @notice A terminal that accepts payments and can be migrated.
interface IJBTerminal is IERC165 {
    event AddToBalance(
        uint256 indexed projectId, uint256 amount, uint256 returnedFees, string memo, bytes metadata, address caller
    );
    event HookAfterRecordPay(
        IJBPayHook indexed hook, JBAfterPayRecordedContext context, uint256 specificationAmount, address caller
    );

    event MigrateTerminal(
        uint256 indexed projectId, address indexed token, IJBTerminal indexed to, uint256 amount, address caller
    );
    event Pay(
        uint256 indexed rulesetId,
        uint256 indexed rulesetCycleNumber,
        uint256 indexed projectId,
        address payer,
        address beneficiary,
        uint256 amount,
        uint256 newlyIssuedTokenCount,
        string memo,
        bytes metadata,
        address caller
    );
    event SetAccountingContext(uint256 indexed projectId, JBAccountingContext context, address caller);

    function accountingContextForTokenOf(
        uint256 projectId,
        address token
    )
        external
        view
        returns (JBAccountingContext memory);
    function accountingContextsOf(uint256 projectId) external view returns (JBAccountingContext[] memory);
    function currentSurplusOf(
        uint256 projectId,
        JBAccountingContext[] memory accountingContexts,
        uint256 decimals,
        uint256 currency
    )
        external
        view
        returns (uint256);

    function addAccountingContextsFor(uint256 projectId, JBAccountingContext[] calldata accountingContexts) external;
    function addToBalanceOf(
        uint256 projectId,
        address token,
        uint256 amount,
        bool shouldReturnHeldFees,
        string calldata memo,
        bytes calldata metadata
    )
        external
        payable;
    function migrateBalanceOf(uint256 projectId, address token, IJBTerminal to) external returns (uint256 balance);
    function pay(
        uint256 projectId,
        address token,
        uint256 amount,
        address beneficiary,
        uint256 minReturnedTokens,
        string calldata memo,
        bytes calldata metadata
    )
        external
        payable
        returns (uint256 beneficiaryTokenCount);
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IJBTokenUriResolver {
    function getUri(uint256 projectId) external view returns (string memory tokenUri);
}

File 17 of 20 : JBAccountingContext.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/// @custom:member token The address of the token that accounting is being done with.
/// @custom:member decimals The number of decimals expected in that token's fixed point accounting.
/// @custom:member currency The currency that the token is priced in terms of. By convention, this is
/// `uint32(uint160(tokenAddress))` for tokens, or a constant ID from e.g. `JBCurrencyIds` for other currencies.
struct JBAccountingContext {
    address token;
    uint8 decimals;
    uint32 currency;
}

File 18 of 20 : JBAfterPayRecordedContext.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {JBTokenAmount} from "./JBTokenAmount.sol";

/// @custom:member payer The address the payment originated from.
/// @custom:member projectId The ID of the project being paid.
/// @custom:member rulesetId The ID of the ruleset the payment is being made during.
/// @custom:member amount The payment's token amount. Includes the token being paid, the value, the number of decimals
/// included, and the currency of the amount.
/// @custom:member forwardedAmount The token amount being forwarded to the pay hook. Includes the token
/// being paid, the value, the number of decimals included, and the currency of the amount.
/// @custom:member weight The current ruleset's weight (used to determine how many tokens should be minted).
/// @custom:member newlyIssuedTokenCount The number of project tokens minted for the beneficiary.
/// @custom:member beneficiary The address which receives any tokens this payment yields.
/// @custom:member hookMetadata Extra data specified by the data hook, which is sent to the pay hook.
/// @custom:member payerMetadata Extra data specified by the payer, which is sent to the pay hook.
struct JBAfterPayRecordedContext {
    address payer;
    uint256 projectId;
    uint256 rulesetId;
    JBTokenAmount amount;
    JBTokenAmount forwardedAmount;
    uint256 weight;
    uint256 newlyIssuedTokenCount;
    address beneficiary;
    bytes hookMetadata;
    bytes payerMetadata;
}

File 19 of 20 : JBPermissionsData.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/// @custom:member operator The address that permissions are being given to.
/// @custom:member projectId The ID of the project the operator is being given permissions for. Operators only have
/// permissions under this project's scope. An ID of 0 is a wildcard, which gives an operator permissions across all
/// projects.
/// @custom:member permissionIds The IDs of the permissions being given. See the `JBPermissionIds` library.
struct JBPermissionsData {
    address operator;
    uint64 projectId;
    uint8[] permissionIds;
}

File 20 of 20 : JBTokenAmount.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/// @custom:member token The token the payment was made in.
/// @custom:member decimals The number of decimals included in the value fixed point number.
/// @custom:member currency The currency. By convention, this is `uint32(uint160(tokenAddress))` for tokens, or a
/// constant ID from e.g. `JBCurrencyIds` for other currencies.
/// @custom:member value The amount of tokens that was paid, as a fixed point number.
struct JBTokenAmount {
    address token;
    uint8 decimals;
    uint32 currency;
    uint256 value;
}

Settings
{
  "evmVersion": "paris",
  "metadata": {
    "appendCBOR": true,
    "bytecodeHash": "ipfs",
    "useLiteralContent": false
  },
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "remappings": [
    "@sphinx-labs/contracts/=lib/sphinx/packages/contracts/contracts/foundry/",
    "@arbitrum/=node_modules/@arbitrum/",
    "@bananapus/=node_modules/@bananapus/",
    "@chainlink/=node_modules/@chainlink/",
    "@eth-optimism/=node_modules/@eth-optimism/",
    "@offchainlabs/=node_modules/@offchainlabs/",
    "@openzeppelin/=node_modules/@openzeppelin/",
    "@prb/=node_modules/@prb/",
    "@scroll-tech/=node_modules/@scroll-tech/",
    "@uniswap/=node_modules/@uniswap/",
    "@zksync/=node_modules/@zksync/",
    "forge-std/=lib/forge-std/src/",
    "hardhat/=node_modules/hardhat/",
    "solmate/=node_modules/solmate/",
    "sphinx/=lib/sphinx/packages/contracts/contracts/forge-std/src/"
  ],
  "viaIR": false
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"contract IJBPermissions","name":"permissions","type":"address"},{"internalType":"contract IJBProjects","name":"projects","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"contract IJBTerminal","name":"terminal","type":"address"}],"name":"JBDirectory_DuplicateTerminals","type":"error"},{"inputs":[{"internalType":"uint256","name":"projectId","type":"uint256"},{"internalType":"uint256","name":"limit","type":"uint256"}],"name":"JBDirectory_InvalidProjectIdInDirectory","type":"error"},{"inputs":[],"name":"JBDirectory_SetControllerNotAllowed","type":"error"},{"inputs":[],"name":"JBDirectory_SetTerminalsNotAllowed","type":"error"},{"inputs":[{"internalType":"uint256","name":"projectId","type":"uint256"},{"internalType":"address","name":"token","type":"address"},{"internalType":"contract IJBTerminal","name":"terminal","type":"address"}],"name":"JBDirectory_TokenNotAccepted","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"projectId","type":"uint256"},{"internalType":"uint256","name":"permissionId","type":"uint256"}],"name":"JBPermissioned_Unauthorized","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"projectId","type":"uint256"},{"indexed":true,"internalType":"contract IJBTerminal","name":"terminal","type":"address"},{"indexed":false,"internalType":"address","name":"caller","type":"address"}],"name":"AddTerminal","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":"uint256","name":"projectId","type":"uint256"},{"indexed":true,"internalType":"contract IERC165","name":"controller","type":"address"},{"indexed":false,"internalType":"address","name":"caller","type":"address"}],"name":"SetController","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addr","type":"address"},{"indexed":true,"internalType":"bool","name":"isAllowed","type":"bool"},{"indexed":false,"internalType":"address","name":"caller","type":"address"}],"name":"SetIsAllowedToSetFirstController","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"projectId","type":"uint256"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"contract IJBTerminal","name":"terminal","type":"address"},{"indexed":false,"internalType":"address","name":"caller","type":"address"}],"name":"SetPrimaryTerminal","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"projectId","type":"uint256"},{"indexed":false,"internalType":"contract IJBTerminal[]","name":"terminals","type":"address[]"},{"indexed":false,"internalType":"address","name":"caller","type":"address"}],"name":"SetTerminals","type":"event"},{"inputs":[],"name":"PERMISSIONS","outputs":[{"internalType":"contract IJBPermissions","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PROJECTS","outputs":[{"internalType":"contract IJBProjects","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"projectId","type":"uint256"}],"name":"controllerOf","outputs":[{"internalType":"contract IERC165","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"isAllowedToSetFirstController","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"projectId","type":"uint256"},{"internalType":"contract IJBTerminal","name":"terminal","type":"address"}],"name":"isTerminalOf","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"projectId","type":"uint256"},{"internalType":"address","name":"token","type":"address"}],"name":"primaryTerminalOf","outputs":[{"internalType":"contract IJBTerminal","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"projectId","type":"uint256"},{"internalType":"contract IERC165","name":"controller","type":"address"}],"name":"setControllerOf","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bool","name":"flag","type":"bool"}],"name":"setIsAllowedToSetFirstController","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"projectId","type":"uint256"},{"internalType":"address","name":"token","type":"address"},{"internalType":"contract IJBTerminal","name":"terminal","type":"address"}],"name":"setPrimaryTerminalOf","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"projectId","type":"uint256"},{"internalType":"contract IJBTerminal[]","name":"terminals","type":"address[]"}],"name":"setTerminalsOf","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"projectId","type":"uint256"}],"name":"terminalsOf","outputs":[{"internalType":"contract IJBTerminal[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60c06040523480156200001157600080fd5b5060405162001926380380620019268339810160408190526200003491620000f4565b6001600160a01b03808416608052819081166200006b57604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b62000076816200008b565b50506001600160a01b031660a0525062000148565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b0381168114620000f157600080fd5b50565b6000806000606084860312156200010a57600080fd5b83516200011781620000db565b60208501519093506200012a81620000db565b60408501519092506200013d81620000db565b809150509250925092565b60805160a05161178f620001976000396000818160f40152818161029001528181610541015281816105e00152818161066a0152610a9c01526000818161025401526110aa015261178f6000f3fe608060405234801561001057600080fd5b50600436106100ea5760003560e01c8063862026501161008c578063c5664e2111610066578063c5664e21146101f9578063d17541531461021c578063f2fde38b1461023c578063f434c9141461024f57600080fd5b806386202650146101c25780638da5cb5b146101d5578063a1ed3175146101e657600080fd5b80636e49181f116100c85780636e49181f14610171578063714e7f3214610194578063715018a6146101a7578063821b9fd8146101af57600080fd5b8063293c4999146100ef5780635dd8f6aa1461013357806363d0850a1461015c575b600080fd5b6101167f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b6101166101413660046113fc565b6001602052600090815260409020546001600160a01b031681565b61016f61016a36600461142a565b610276565b005b61018461017f36600461146c565b610444565b604051901515815260200161012a565b61016f6101a236600461146c565b61050b565b61016f610a6e565b61016f6101bd36600461149c565b610a82565b6101166101d036600461146c565b610dbd565b6000546001600160a01b0316610116565b61016f6101f4366004611529565b610f3e565b610184610207366004611557565b60026020526000908152604090205460ff1681565b61022f61022a3660046113fc565b610fa8565b60405161012a919061157b565b61016f61024a366004611557565b611014565b6101167f000000000000000000000000000000000000000000000000000000000000000081565b6040516331a9108f60e11b81526004810184905261030b907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa1580156102df573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030391906115c8565b84600f611052565b604051633a01714f60e01b8152600481018490526001600160a01b03838116602483015260009190831690633a01714f90604401606060405180830381865afa15801561035c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061038091906115e5565b516001600160a01b0316036103c75760405163027bb87960e11b8152600481018490526001600160a01b038084166024830152821660448201526064015b60405180910390fd5b6103d18382611156565b60008381526003602090815260408083206001600160a01b038681168086529184529382902080546001600160a01b03191694861694851790559051338152909186917fc670a502bbb9f8a4315f95eca901a9f99b65f89a2eb5705a58050e5c00f9d672910160405180910390a4505050565b6000828152600460209081526040808320805482518185028101850190935280835284938301828280156104a157602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610483575b505083519394506000925050505b818110156104fd57846001600160a01b03168382815181106104d3576104d3611674565b60200260200101516001600160a01b0316036104f55760019350505050610505565b6001016104af565b506000925050505b92915050565b600082815260016020526040908190205490516331a9108f60e11b8152600481018490526001600160a01b03918216916105de917f000000000000000000000000000000000000000000000000000000000000000090911690636352211e90602401602060405180830381865afa15801561058a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ae91906115c8565b336000908152600260205260409020548590600d9060ff1680156105d957506001600160a01b038516155b6112f7565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166306661abd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561063c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610660919061168a565b83111561070c57827f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166306661abd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106ea919061168a565b6040516317140d0f60e31b8152600481019290925260248201526044016103be565b60006001600160a01b038216158061079557506040516301ffc9a760e01b81526001600160a01b038316906301ffc9a79061075290632877540760e01b906004016116a3565b602060405180830381865afa15801561076f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061079391906116b8565b155b61080757604051632674968d60e21b8152600481018590526001600160a01b038316906399d25a3490602401602060405180830381865afa1580156107de573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061080291906116b8565b61080a565b60015b90508061082a5760405163cf211e7f60e01b815260040160405180910390fd5b6001600160a01b038216158015906108b157506040516301ffc9a760e01b81526001600160a01b038416906301ffc9a79061087090635825057160e11b906004016116a3565b602060405180830381865afa15801561088d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108b191906116b8565b1561091957604051631e0231c360e31b81526001600160a01b0383811660048301526024820186905284169063f0118e1890604401600060405180830381600087803b15801561090057600080fd5b505af1158015610914573d6000803e3d6000fd5b505050505b60008481526001602090815260409182902080546001600160a01b0319166001600160a01b038716908117909155915133815286917f7f9a7dcb234c909a09de2f344661ad9e5b24067adb97c908647c2edcbb121c30910160405180910390a36001600160a01b03821615801590610a0057506040516301ffc9a760e01b81526001600160a01b038316906301ffc9a7906109bf90635825057160e11b906004016116a3565b602060405180830381865afa1580156109dc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a0091906116b8565b15610a685760405163202dc27d60e11b8152600481018590526001600160a01b03848116602483015283169063405b84fa90604401600060405180830381600087803b158015610a4f57600080fd5b505af1158015610a63573d6000803e3d6000fd5b505050505b50505050565b610a76611307565b610a806000611334565b565b6040516331a9108f60e11b815260048101849052610b33907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610aeb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b0f91906115c8565b6000858152600160205260409020548590600e906001600160a01b031633146112f7565b6000838152600160205260408082205490516301ffc9a760e01b81526001600160a01b03909116919082906301ffc9a790610b7990632877540760e01b906004016116a3565b602060405180830381865afa158015610b96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bba91906116b8565b1580610c2a575060405163b1a50e3360e01b8152600481018690526001600160a01b0383169063b1a50e3390602401602060405180830381865afa158015610c06573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2a91906116b8565b6000868152600160205260409020549091506001600160a01b03163314801590610c52575080155b15610c7057604051630fed236960e21b815260040160405180910390fd5b6000858152600460205260409020610c89908585611384565b506001831115610d7a5760005b83811015610d78576000610cab8260016116d5565b90505b84811015610d6f57858582818110610cc857610cc8611674565b9050602002016020810190610cdd9190611557565b6001600160a01b0316868684818110610cf857610cf8611674565b9050602002016020810190610d0d9190611557565b6001600160a01b031603610d6757858583818110610d2d57610d2d611674565b9050602002016020810190610d429190611557565b604051638a53d99f60e01b81526001600160a01b0390911660048201526024016103be565b600101610cae565b50600101610c96565b505b847fb648241d83df6540fc10f2acc641e4bf80a1e84e7ae2f1f6b0ad204b8fee635b858533604051610dae939291906116f6565b60405180910390a25050505050565b60008281526003602090815260408083206001600160a01b0380861685529252822054168015801590610df55750610df58482610444565b15610e01579050610505565b600084815260046020908152604080832080548251818502810185019093528083529192909190830182828015610e6157602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610e43575b505083519394506000925050505b81811015610f31576000838281518110610e8b57610e8b611674565b6020908102919091010151604051633a01714f60e01b8152600481018a90526001600160a01b038981166024830152919250600091831690633a01714f90604401606060405180830381865afa158015610ee9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f0d91906115e5565b516001600160a01b031614610f285794506105059350505050565b50600101610e6f565b5060009695505050505050565b610f46611307565b6001600160a01b038216600081815260026020908152604091829020805460ff191685151590811790915591513381529192917f11207664cc48b0fa81c8674795f1d8f642960f38d5d2d305ad813093bed85fab910160405180910390a35050565b60008181526004602090815260409182902080548351818402810184019094528084526060939283018282801561100857602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610fea575b50505050509050919050565b61101c611307565b6001600160a01b03811661104657604051631e4fbdf760e01b8152600060048201526024016103be565b61104f81611334565b50565b336001600160a01b03841681148015906111175750604051631a45b42760e11b81526001600160a01b0382811660048301528581166024830152604482018590526064820184905260016084830181905260a48301527f0000000000000000000000000000000000000000000000000000000000000000169063348b684e9060c401602060405180830381865afa1580156110f1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061111591906116b8565b155b15610a6857604051631326f75560e11b81526001600160a01b0380861660048301528216602482015260448101849052606481018390526084016103be565b6111608282610444565b15611169575050565b6000828152600160205260408082205490516301ffc9a760e01b81526001600160a01b03909116919082906301ffc9a7906111af90632877540760e01b906004016116a3565b602060405180830381865afa1580156111cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f091906116b8565b1580611260575060405163b1a50e3360e01b8152600481018590526001600160a01b0383169063b1a50e3390602401602060405180830381865afa15801561123c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061126091906116b8565b90508061128057604051630fed236960e21b815260040160405180910390fd5b600084815260046020908152604080832080546001810182559084529282902090920180546001600160a01b0319166001600160a01b038716908117909155915133815286917f409bccc07b7cf7807930526a24318212d614c59f2dde05a017a41efee144e7c8910160405180910390a350505050565b80610a6857610a68848484611052565b6000546001600160a01b03163314610a805760405163118cdaa760e01b81523360048201526024016103be565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b8280548282559060005260206000209081019282156113d7579160200282015b828111156113d75781546001600160a01b0319166001600160a01b038435161782556020909201916001909101906113a4565b506113e39291506113e7565b5090565b5b808211156113e357600081556001016113e8565b60006020828403121561140e57600080fd5b5035919050565b6001600160a01b038116811461104f57600080fd5b60008060006060848603121561143f57600080fd5b83359250602084013561145181611415565b9150604084013561146181611415565b809150509250925092565b6000806040838503121561147f57600080fd5b82359150602083013561149181611415565b809150509250929050565b6000806000604084860312156114b157600080fd5b83359250602084013567ffffffffffffffff808211156114d057600080fd5b818601915086601f8301126114e457600080fd5b8135818111156114f357600080fd5b8760208260051b850101111561150857600080fd5b6020830194508093505050509250925092565b801515811461104f57600080fd5b6000806040838503121561153c57600080fd5b823561154781611415565b915060208301356114918161151b565b60006020828403121561156957600080fd5b813561157481611415565b9392505050565b6020808252825182820181905260009190848201906040850190845b818110156115bc5783516001600160a01b031683529284019291840191600101611597565b50909695505050505050565b6000602082840312156115da57600080fd5b815161157481611415565b6000606082840312156115f757600080fd5b6040516060810181811067ffffffffffffffff8211171561162857634e487b7160e01b600052604160045260246000fd5b604052825161163681611415565b8152602083015160ff8116811461164c57600080fd5b6020820152604083015163ffffffff8116811461166857600080fd5b60408201529392505050565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561169c57600080fd5b5051919050565b6001600160e01b031991909116815260200190565b6000602082840312156116ca57600080fd5b81516115748161151b565b8082018082111561050557634e487b7160e01b600052601160045260246000fd5b6040808252810183905260008460608301825b8681101561173957823561171c81611415565b6001600160a01b0316825260209283019290910190600101611709565b506001600160a01b0394909416602093909301929092525090939250505056fea2646970667358221220e023368f049ac60d7a5275cb961c9de2bcc8f70c76610ee585527395a7c3930864736f6c6343000817003300000000000000000000000004fd6913d6c32d8c216e153a43c04b1857a7793d000000000000000000000000885f707efa18d2cb12f05a3a8eba6b4b26c8c1d400000000000000000000000080a8f7a4bd75b539ce26937016df607fdc9abeb5

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106100ea5760003560e01c8063862026501161008c578063c5664e2111610066578063c5664e21146101f9578063d17541531461021c578063f2fde38b1461023c578063f434c9141461024f57600080fd5b806386202650146101c25780638da5cb5b146101d5578063a1ed3175146101e657600080fd5b80636e49181f116100c85780636e49181f14610171578063714e7f3214610194578063715018a6146101a7578063821b9fd8146101af57600080fd5b8063293c4999146100ef5780635dd8f6aa1461013357806363d0850a1461015c575b600080fd5b6101167f000000000000000000000000885f707efa18d2cb12f05a3a8eba6b4b26c8c1d481565b6040516001600160a01b0390911681526020015b60405180910390f35b6101166101413660046113fc565b6001602052600090815260409020546001600160a01b031681565b61016f61016a36600461142a565b610276565b005b61018461017f36600461146c565b610444565b604051901515815260200161012a565b61016f6101a236600461146c565b61050b565b61016f610a6e565b61016f6101bd36600461149c565b610a82565b6101166101d036600461146c565b610dbd565b6000546001600160a01b0316610116565b61016f6101f4366004611529565b610f3e565b610184610207366004611557565b60026020526000908152604090205460ff1681565b61022f61022a3660046113fc565b610fa8565b60405161012a919061157b565b61016f61024a366004611557565b611014565b6101167f00000000000000000000000004fd6913d6c32d8c216e153a43c04b1857a7793d81565b6040516331a9108f60e11b81526004810184905261030b907f000000000000000000000000885f707efa18d2cb12f05a3a8eba6b4b26c8c1d46001600160a01b031690636352211e90602401602060405180830381865afa1580156102df573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030391906115c8565b84600f611052565b604051633a01714f60e01b8152600481018490526001600160a01b03838116602483015260009190831690633a01714f90604401606060405180830381865afa15801561035c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061038091906115e5565b516001600160a01b0316036103c75760405163027bb87960e11b8152600481018490526001600160a01b038084166024830152821660448201526064015b60405180910390fd5b6103d18382611156565b60008381526003602090815260408083206001600160a01b038681168086529184529382902080546001600160a01b03191694861694851790559051338152909186917fc670a502bbb9f8a4315f95eca901a9f99b65f89a2eb5705a58050e5c00f9d672910160405180910390a4505050565b6000828152600460209081526040808320805482518185028101850190935280835284938301828280156104a157602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610483575b505083519394506000925050505b818110156104fd57846001600160a01b03168382815181106104d3576104d3611674565b60200260200101516001600160a01b0316036104f55760019350505050610505565b6001016104af565b506000925050505b92915050565b600082815260016020526040908190205490516331a9108f60e11b8152600481018490526001600160a01b03918216916105de917f000000000000000000000000885f707efa18d2cb12f05a3a8eba6b4b26c8c1d490911690636352211e90602401602060405180830381865afa15801561058a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ae91906115c8565b336000908152600260205260409020548590600d9060ff1680156105d957506001600160a01b038516155b6112f7565b7f000000000000000000000000885f707efa18d2cb12f05a3a8eba6b4b26c8c1d46001600160a01b03166306661abd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561063c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610660919061168a565b83111561070c57827f000000000000000000000000885f707efa18d2cb12f05a3a8eba6b4b26c8c1d46001600160a01b03166306661abd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106ea919061168a565b6040516317140d0f60e31b8152600481019290925260248201526044016103be565b60006001600160a01b038216158061079557506040516301ffc9a760e01b81526001600160a01b038316906301ffc9a79061075290632877540760e01b906004016116a3565b602060405180830381865afa15801561076f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061079391906116b8565b155b61080757604051632674968d60e21b8152600481018590526001600160a01b038316906399d25a3490602401602060405180830381865afa1580156107de573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061080291906116b8565b61080a565b60015b90508061082a5760405163cf211e7f60e01b815260040160405180910390fd5b6001600160a01b038216158015906108b157506040516301ffc9a760e01b81526001600160a01b038416906301ffc9a79061087090635825057160e11b906004016116a3565b602060405180830381865afa15801561088d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108b191906116b8565b1561091957604051631e0231c360e31b81526001600160a01b0383811660048301526024820186905284169063f0118e1890604401600060405180830381600087803b15801561090057600080fd5b505af1158015610914573d6000803e3d6000fd5b505050505b60008481526001602090815260409182902080546001600160a01b0319166001600160a01b038716908117909155915133815286917f7f9a7dcb234c909a09de2f344661ad9e5b24067adb97c908647c2edcbb121c30910160405180910390a36001600160a01b03821615801590610a0057506040516301ffc9a760e01b81526001600160a01b038316906301ffc9a7906109bf90635825057160e11b906004016116a3565b602060405180830381865afa1580156109dc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a0091906116b8565b15610a685760405163202dc27d60e11b8152600481018590526001600160a01b03848116602483015283169063405b84fa90604401600060405180830381600087803b158015610a4f57600080fd5b505af1158015610a63573d6000803e3d6000fd5b505050505b50505050565b610a76611307565b610a806000611334565b565b6040516331a9108f60e11b815260048101849052610b33907f000000000000000000000000885f707efa18d2cb12f05a3a8eba6b4b26c8c1d46001600160a01b031690636352211e90602401602060405180830381865afa158015610aeb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b0f91906115c8565b6000858152600160205260409020548590600e906001600160a01b031633146112f7565b6000838152600160205260408082205490516301ffc9a760e01b81526001600160a01b03909116919082906301ffc9a790610b7990632877540760e01b906004016116a3565b602060405180830381865afa158015610b96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bba91906116b8565b1580610c2a575060405163b1a50e3360e01b8152600481018690526001600160a01b0383169063b1a50e3390602401602060405180830381865afa158015610c06573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2a91906116b8565b6000868152600160205260409020549091506001600160a01b03163314801590610c52575080155b15610c7057604051630fed236960e21b815260040160405180910390fd5b6000858152600460205260409020610c89908585611384565b506001831115610d7a5760005b83811015610d78576000610cab8260016116d5565b90505b84811015610d6f57858582818110610cc857610cc8611674565b9050602002016020810190610cdd9190611557565b6001600160a01b0316868684818110610cf857610cf8611674565b9050602002016020810190610d0d9190611557565b6001600160a01b031603610d6757858583818110610d2d57610d2d611674565b9050602002016020810190610d429190611557565b604051638a53d99f60e01b81526001600160a01b0390911660048201526024016103be565b600101610cae565b50600101610c96565b505b847fb648241d83df6540fc10f2acc641e4bf80a1e84e7ae2f1f6b0ad204b8fee635b858533604051610dae939291906116f6565b60405180910390a25050505050565b60008281526003602090815260408083206001600160a01b0380861685529252822054168015801590610df55750610df58482610444565b15610e01579050610505565b600084815260046020908152604080832080548251818502810185019093528083529192909190830182828015610e6157602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610e43575b505083519394506000925050505b81811015610f31576000838281518110610e8b57610e8b611674565b6020908102919091010151604051633a01714f60e01b8152600481018a90526001600160a01b038981166024830152919250600091831690633a01714f90604401606060405180830381865afa158015610ee9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f0d91906115e5565b516001600160a01b031614610f285794506105059350505050565b50600101610e6f565b5060009695505050505050565b610f46611307565b6001600160a01b038216600081815260026020908152604091829020805460ff191685151590811790915591513381529192917f11207664cc48b0fa81c8674795f1d8f642960f38d5d2d305ad813093bed85fab910160405180910390a35050565b60008181526004602090815260409182902080548351818402810184019094528084526060939283018282801561100857602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610fea575b50505050509050919050565b61101c611307565b6001600160a01b03811661104657604051631e4fbdf760e01b8152600060048201526024016103be565b61104f81611334565b50565b336001600160a01b03841681148015906111175750604051631a45b42760e11b81526001600160a01b0382811660048301528581166024830152604482018590526064820184905260016084830181905260a48301527f00000000000000000000000004fd6913d6c32d8c216e153a43c04b1857a7793d169063348b684e9060c401602060405180830381865afa1580156110f1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061111591906116b8565b155b15610a6857604051631326f75560e11b81526001600160a01b0380861660048301528216602482015260448101849052606481018390526084016103be565b6111608282610444565b15611169575050565b6000828152600160205260408082205490516301ffc9a760e01b81526001600160a01b03909116919082906301ffc9a7906111af90632877540760e01b906004016116a3565b602060405180830381865afa1580156111cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f091906116b8565b1580611260575060405163b1a50e3360e01b8152600481018590526001600160a01b0383169063b1a50e3390602401602060405180830381865afa15801561123c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061126091906116b8565b90508061128057604051630fed236960e21b815260040160405180910390fd5b600084815260046020908152604080832080546001810182559084529282902090920180546001600160a01b0319166001600160a01b038716908117909155915133815286917f409bccc07b7cf7807930526a24318212d614c59f2dde05a017a41efee144e7c8910160405180910390a350505050565b80610a6857610a68848484611052565b6000546001600160a01b03163314610a805760405163118cdaa760e01b81523360048201526024016103be565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b8280548282559060005260206000209081019282156113d7579160200282015b828111156113d75781546001600160a01b0319166001600160a01b038435161782556020909201916001909101906113a4565b506113e39291506113e7565b5090565b5b808211156113e357600081556001016113e8565b60006020828403121561140e57600080fd5b5035919050565b6001600160a01b038116811461104f57600080fd5b60008060006060848603121561143f57600080fd5b83359250602084013561145181611415565b9150604084013561146181611415565b809150509250925092565b6000806040838503121561147f57600080fd5b82359150602083013561149181611415565b809150509250929050565b6000806000604084860312156114b157600080fd5b83359250602084013567ffffffffffffffff808211156114d057600080fd5b818601915086601f8301126114e457600080fd5b8135818111156114f357600080fd5b8760208260051b850101111561150857600080fd5b6020830194508093505050509250925092565b801515811461104f57600080fd5b6000806040838503121561153c57600080fd5b823561154781611415565b915060208301356114918161151b565b60006020828403121561156957600080fd5b813561157481611415565b9392505050565b6020808252825182820181905260009190848201906040850190845b818110156115bc5783516001600160a01b031683529284019291840191600101611597565b50909695505050505050565b6000602082840312156115da57600080fd5b815161157481611415565b6000606082840312156115f757600080fd5b6040516060810181811067ffffffffffffffff8211171561162857634e487b7160e01b600052604160045260246000fd5b604052825161163681611415565b8152602083015160ff8116811461164c57600080fd5b6020820152604083015163ffffffff8116811461166857600080fd5b60408201529392505050565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561169c57600080fd5b5051919050565b6001600160e01b031991909116815260200190565b6000602082840312156116ca57600080fd5b81516115748161151b565b8082018082111561050557634e487b7160e01b600052601160045260246000fd5b6040808252810183905260008460608301825b8681101561173957823561171c81611415565b6001600160a01b0316825260209283019290910190600101611709565b506001600160a01b0394909416602093909301929092525090939250505056fea2646970667358221220e023368f049ac60d7a5275cb961c9de2bcc8f70c76610ee585527395a7c3930864736f6c63430008170033

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

00000000000000000000000004fd6913d6c32d8c216e153a43c04b1857a7793d000000000000000000000000885f707efa18d2cb12f05a3a8eba6b4b26c8c1d400000000000000000000000080a8f7a4bd75b539ce26937016df607fdc9abeb5

-----Decoded View---------------
Arg [0] : permissions (address): 0x04fD6913d6c32D8C216e153a43C04b1857a7793d
Arg [1] : projects (address): 0x885f707EFA18D2cb12f05a3a8eBA6B4B26c8c1D4
Arg [2] : owner (address): 0x80a8F7a4bD75b539CE26937016Df607fdC9ABeb5

-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 00000000000000000000000004fd6913d6c32d8c216e153a43c04b1857a7793d
Arg [1] : 000000000000000000000000885f707efa18d2cb12f05a3a8eba6b4b26c8c1d4
Arg [2] : 00000000000000000000000080a8f7a4bd75b539ce26937016df607fdc9abeb5


Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ 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.