ETH Price: $2,482.38 (-0.94%)

Contract Diff Checker

Contract Name:
Projects

Contract Source Code:

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)

pragma solidity ^0.8.0;

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

/**
 * @dev Contract module which allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 *
 * This module is used through inheritance. It will make available the
 * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
 * the functions of your contract. Note that they will not be pausable by
 * simply including this module, only once the modifiers are put in place.
 */
abstract contract Pausable is Context {
    /**
     * @dev Emitted when the pause is triggered by `account`.
     */
    event Paused(address account);

    /**
     * @dev Emitted when the pause is lifted by `account`.
     */
    event Unpaused(address account);

    bool private _paused;

    /**
     * @dev Initializes the contract in unpaused state.
     */
    constructor() {
        _paused = false;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    modifier whenNotPaused() {
        _requireNotPaused();
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    modifier whenPaused() {
        _requirePaused();
        _;
    }

    /**
     * @dev Returns true if the contract is paused, and false otherwise.
     */
    function paused() public view virtual returns (bool) {
        return _paused;
    }

    /**
     * @dev Throws if the contract is paused.
     */
    function _requireNotPaused() internal view virtual {
        require(!paused(), "Pausable: paused");
    }

    /**
     * @dev Throws if the contract is not paused.
     */
    function _requirePaused() internal view virtual {
        require(paused(), "Pausable: not paused");
    }

    /**
     * @dev Triggers stopped state.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    function _pause() internal virtual whenNotPaused {
        _paused = true;
        emit Paused(_msgSender());
    }

    /**
     * @dev Returns to normal state.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    function _unpause() internal virtual whenPaused {
        _paused = false;
        emit Unpaused(_msgSender());
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (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;
    }
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

import {Pausable} from "./abstract/Pausable.sol";
import {AllowList} from "./abstract/AllowList.sol";
import {IProjects} from "./interfaces/IProjects.sol";
import {IPausable} from "./interfaces/IPausable.sol";

/// @title Projects - Tracks projects and their owners
/// @notice A storage contract that tracks project IDs and owner accounts.
contract Projects is IProjects, AllowList, Pausable {
    string public constant NAME = "Projects";
    string public constant VERSION = "0.0.1";

    mapping(uint32 => address) public owners;
    mapping(uint32 => address) public pendingOwners;

    uint32 internal _nextProjectId;

    constructor(address _controller) AllowList(_controller) {}

    /// @inheritdoc IProjects
    function create(address owner) external override onlyAllowed whenNotPaused returns (uint32 id) {
        emit CreateProject(id = ++_nextProjectId);
        owners[id] = owner;
    }

    /// @inheritdoc IProjects
    function transferOwnership(uint32 projectId, address newOwner) external override onlyAllowed whenNotPaused {
        pendingOwners[projectId] = newOwner;
        emit TransferOwnership(projectId, owners[projectId], newOwner);
    }

    /// @inheritdoc IProjects
    function acceptOwnership(uint32 projectId) external override onlyAllowed whenNotPaused {
        address oldOwner = owners[projectId];
        address newOwner = pendingOwnerOf(projectId);
        owners[projectId] = newOwner;
        delete pendingOwners[projectId];
        emit AcceptOwnership(projectId, oldOwner, newOwner);
    }

    /// @inheritdoc IProjects
    function ownerOf(uint32 projectId) external view override returns (address owner) {
        owner = owners[projectId];
        if (owner == address(0)) {
            revert NotFound();
        }
    }

    /// @inheritdoc IProjects
    function pendingOwnerOf(uint32 projectId) public view override returns (address pendingOwner) {
        pendingOwner = pendingOwners[projectId];
        if (pendingOwner == address(0)) {
            revert NotFound();
        }
    }

    /// @inheritdoc IProjects
    function exists(uint32 projectId) external view override returns (bool) {
        return owners[projectId] != address(0);
    }

    /// @inheritdoc IPausable
    function pause() external override onlyController {
        _pause();
    }

    /// @inheritdoc IPausable
    function unpause() external override onlyController {
        _unpause();
    }
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

import {Controllable} from "./Controllable.sol";
import {IAllowList} from "../interfaces/IAllowList.sol";

/// @title AllowList - Tracks approved addresses
/// @notice An abstract contract for tracking allowed and denied addresses.
abstract contract AllowList is IAllowList, Controllable {
    mapping(address => bool) public allowed;

    modifier onlyAllowed() {
        if (!allowed[msg.sender]) {
            revert Forbidden();
        }
        _;
    }

    constructor(address _controller) Controllable(_controller) {}

    /// @inheritdoc IAllowList
    function denied(address caller) external view returns (bool) {
        return !allowed[caller];
    }

    /// @inheritdoc IAllowList
    function allow(address caller) external onlyController {
        allowed[caller] = true;
        emit Allow(caller);
    }

    /// @inheritdoc IAllowList
    function deny(address caller) external onlyController {
        allowed[caller] = false;
        emit Deny(caller);
    }
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

import {IControllable} from "../interfaces/IControllable.sol";

/// @title Controllable - Controller management functions
/// @notice An abstract base contract for contracts managed by the Controller.
abstract contract Controllable is IControllable {
    address public controller;

    modifier onlyController() {
        if (msg.sender != controller) {
            revert Forbidden();
        }
        _;
    }

    constructor(address _controller) {
        if (_controller == address(0)) {
            revert ZeroAddress();
        }
        controller = _controller;
    }

    /// @inheritdoc IControllable
    function setDependency(bytes32 _name, address) external virtual onlyController {
        revert InvalidDependency(_name);
    }
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

import {Pausable as OZPausable} from "openzeppelin-contracts/security/Pausable.sol";
import {IPausable} from "../interfaces/IPausable.sol";

/// @title Pausable - Pause and unpause functionality
/// @notice Wraps OZ Pausable and adds an IPausable interface.
abstract contract Pausable is IPausable, OZPausable {}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

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

interface IAllowList is IControllable {
    event Allow(address caller);
    event Deny(address caller);

    /// @notice Check whether the given `caller` address is allowed.
    /// @param caller The caller address.
    /// @return True if caller is allowed, false if caller is denied.
    function allowed(address caller) external view returns (bool);

    /// @notice Check whether the given `caller` address is denied.
    /// @param caller The caller address.
    /// @return True if caller is denied, false if caller is allowed.
    function denied(address caller) external view returns (bool);

    /// @notice Add a caller address to the allowlist.
    /// @param caller The caller address.
    function allow(address caller) external;

    /// @notice Remove a caller address from the allowlist.
    /// @param caller The caller address.
    function deny(address caller) external;
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

interface IAnnotated {
    /// @notice Get contract name.
    /// @return Contract name.
    function NAME() external returns (string memory);

    /// @notice Get contract version.
    /// @return Contract version.
    function VERSION() external returns (string memory);
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

interface ICommonErrors {
    /// @notice The provided address is the zero address.
    error ZeroAddress();
    /// @notice The attempted action is not allowed.
    error Forbidden();
    /// @notice The requested entity cannot be found.
    error NotFound();
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

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

interface IControllable is ICommonErrors {
    /// @notice The dependency with the given `name` is invalid.
    error InvalidDependency(bytes32 name);

    /// @notice Get controller address.
    /// @return Controller address.
    function controller() external returns (address);

    /// @notice Set a named dependency to the given contract address.
    /// @param _name bytes32 name of the dependency to set.
    /// @param _contract address of the dependency.
    function setDependency(bytes32 _name, address _contract) external;
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

interface IPausable {
    /// @notice Pause the contract.
    function pause() external;

    /// @notice Unpause the contract.
    function unpause() external;
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

import {IAnnotated} from "./IAnnotated.sol";
import {ICommonErrors} from "./ICommonErrors.sol";
import {IPausable} from "./IPausable.sol";
import {IAllowList} from "./IAllowList.sol";

interface IProjects is IAllowList, IPausable, IAnnotated {
    event CreateProject(uint32 id);
    event TransferOwnership(uint32 indexed projectId, address indexed owner, address indexed newOwner);
    event AcceptOwnership(uint32 indexed projectId, address indexed owner, address indexed newOwner);

    /// @notice Create a new project owned by the given `owner`.
    /// @param owner address of project owner.
    /// @return uint32 Project ID.
    function create(address owner) external returns (uint32);

    /// @notice Start transfer of `projectId` to `newOwner`. The new owner must
    /// accept the transfer in order to assume ownership of the project.
    /// @param projectId uint32 project ID.
    /// @param newOwner address of proposed new owner.
    function transferOwnership(uint32 projectId, address newOwner) external;

    /// @notice Transfer ownership of `projectId` to `pendingOwner`.
    /// @param projectId uint32 project ID.
    function acceptOwnership(uint32 projectId) external;

    /// @notice Get owner of project by ID.
    /// @param projectId uint32 project ID.
    /// @return address of project owner.
    function ownerOf(uint32 projectId) external view returns (address);

    /// @notice Get pending owner of project by ID.
    /// @param projectId uint32 project ID.
    /// @return address of pending project owner.
    function pendingOwnerOf(uint32 projectId) external view returns (address);

    /// @notice Check whether project exists by ID.
    /// @param projectId uint32 project ID.
    /// @return True if project exists, false if project does not exist.
    function exists(uint32 projectId) external view returns (bool);
}

Please enter a contract address above to load the contract details and source code.

Context size (optional):