contract Registry is IRegistry, Ownable {

    /**
     * @notice Emitted when address for `key` contract is changed to `newValue`
     */
    event Registration(string indexed key, address newValue);

    /**
     * @notice USDC token contract
     */
    address public usdc;

    /**
     * @notice Compound protocol cUSDC pool
     */
    address public cUsdc;

    /**
     * @notice ESD stablecoin contract
     */
    address public dollar;

    /**
     * @notice ESDS governance token contract
     */
    address public stake;

    /**
     * @notice ESD reserve contract
     */
    address public reserve;

    /**
     * @notice ESD governor contract
     */
    address public governor;

    /**
     * @notice ESD timelock contract, owner for the protocol
     */
    address public timelock;

    /**
     * @notice Migration contract to bridge v1 assets with current system
     */
    address public migrator;

    // ADMIN

    /**
     * @notice Registers a new address for USDC
     * @dev Owner only - governance hook
     * @param newValue New address to register
     */
    function setUsdc(address newValue) external validate(newValue) onlyOwner {
        usdc = newValue;
        emit Registration("USDC", newValue);
    }

    /**
     * @notice Registers a new address for cUSDC
     * @dev Owner only - governance hook
     * @param newValue New address to register
     */
    function setCUsdc(address newValue) external validate(newValue) onlyOwner {
        cUsdc = newValue;
        emit Registration("CUSDC", newValue);
    }

    /**
     * @notice Registers a new address for ESD
     * @dev Owner only - governance hook
     * @param newValue New address to register
     */
    function setDollar(address newValue) external validate(newValue) onlyOwner {
        dollar = newValue;
        emit Registration("DOLLAR", newValue);
    }

    /**
     * @notice Registers a new address for ESDS
     * @dev Owner only - governance hook
     * @param newValue New address to register
     */
    function setStake(address newValue) external validate(newValue) onlyOwner {
        stake = newValue;
        emit Registration("STAKE", newValue);
    }

    /**
     * @notice Registers a new address for the reserve
     * @dev Owner only - governance hook
     * @param newValue New address to register
     */
    function setReserve(address newValue) external validate(newValue) onlyOwner {
        reserve = newValue;
        emit Registration("RESERVE", newValue);
    }

    /**
     * @notice Registers a new address for the governor
     * @dev Owner only - governance hook
     * @param newValue New address to register
     */
    function setGovernor(address newValue) external validate(newValue) onlyOwner {
        governor = newValue;
        emit Registration("GOVERNOR", newValue);
    }

    /**
     * @notice Registers a new address for the timelock
     * @dev Owner only - governance hook
     *      Does not automatically update the owner of all owned protocol contracts
     * @param newValue New address to register
     */
    function setTimelock(address newValue) external validate(newValue) onlyOwner {
        timelock = newValue;
        emit Registration("TIMELOCK", newValue);
    }

    /**
     * @notice Registers a new address for the v1 migration contract
     * @dev Owner only - governance hook
     * @param newValue New address to register
     */
    function setMigrator(address newValue) external validate(newValue) onlyOwner {
        migrator = newValue;
        emit Registration("MIGRATOR", newValue);
    }

    /**
     * @notice Ensures the newly supplied value is a deployed contract
     * @param newValue New address to validate
     */
    modifier validate(address newValue) {
        require(newValue != address(this), "Registry: this");
        require(Address.isContract(newValue), "Registry: not contract");

        _;
    }
}
/**
 * @title Registry
 * @notice Single source of truth for the addresses of all contracts int he protocol
 * @dev Should be governance-owned to allow contracts addresses to change by vote
 */
function setDollar(address newValue) external validate(newValue) onlyOwner {
    dollar = newValue;
    emit Registration("DOLLAR", newValue);
}

/**
 * @notice Registers a new address for ESD
 * @dev Owner only - governance hook
 * @param newValue New address to register
 */