abstract contract CoreRef is ICoreRef, Pausable {
    ICore private _core;

    /// @notice CoreRef constructor
    /// @param newCore Ring Core to reference
    constructor(address newCore) {
        _core = ICore(newCore);
    }

    modifier ifMinterSelf() {
        if (_core.isMinter(address(this))) {
            _;
        }
    }

    modifier ifBurnerSelf() {
        if (_core.isBurner(address(this))) {
            _;
        }
    }

    modifier onlyMinter() {
        require(_core.isMinter(msg.sender), "CoreRef: Caller is not a minter");
        _;
    }

    modifier onlyBurner() {
        require(_core.isBurner(msg.sender), "CoreRef: Caller is not a burner");
        _;
    }

    modifier onlyPCVController() {
        require(
            _core.isPCVController(msg.sender),
            "CoreRef: Caller is not a PCV controller"
        );
        _;
    }

    modifier onlyGovernor() {
        require(
            _core.isGovernor(msg.sender),
            "CoreRef: Caller is not a governor"
        );
        _;
    }

    modifier onlyGuardianOrGovernor() {
        require(
            _core.isGovernor(msg.sender) ||
            _core.isGuardian(msg.sender),
            "CoreRef: Caller is not a guardian or governor"
        );
        _;
    }

    modifier onlyRusd() {
        require(msg.sender == address(rusd()), "CoreRef: Caller is not RUSD");
        _;
    }

    modifier onlyGenesisGroup() {
        require(
            msg.sender == _core.genesisGroup(),
            "CoreRef: Caller is not GenesisGroup"
        );
        _;
    }

    modifier nonContract() {
        require(!Address.isContract(msg.sender), "CoreRef: Caller is a contract");
        _;
    }

    /// @notice set new Core reference address
    /// @param _newCore the new core address
    function setCore(address _newCore) external override onlyGovernor {
        _core = ICore(_newCore);
        emit CoreUpdate(_newCore);
    }

    /// @notice set pausable methods to paused
    function pause() public override onlyGuardianOrGovernor {
        _pause();
    }

    /// @notice set pausable methods to unpaused
    function unpause() public override onlyGuardianOrGovernor {
        _unpause();
    }

    /// @notice address of the Core contract referenced
    /// @return ICore implementation address
    function core() public view override returns (ICore) {
        return _core;
    }

    /// @notice address of the Rusd contract referenced by Core
    /// @return IRusd implementation address
    function rusd() public view override returns (IRusd) {
        return _core.rusd();
    }

    /// @notice address of the Ring contract referenced by Core
    /// @return IERC20 implementation address
    function ring() public view override returns (IERC20) {
        return _core.ring();
    }

    /// @notice rusd balance of contract
    /// @return rusd amount held
    function rusdBalance() public view override returns (uint256) {
        return rusd().balanceOf(address(this));
    }

    /// @notice ring balance of contract
    /// @return ring amount held
    function ringBalance() public view override returns (uint256) {
        return ring().balanceOf(address(this));
    }

    function _burnRusdHeld() internal {
        rusd().burn(rusdBalance());
    }

    function _mintRusd(uint256 amount) internal {
        rusd().mint(address(this), amount);
    }
}
/// @title A Reference to Core
/// @author Ring Protocol
/// @notice defines some modifiers and utilities around interacting with Core
function unpause() public override onlyGuardianOrGovernor {
    _unpause();
}

/// @notice set pausable methods to unpaused