contract Delegable is Ownable {
    address private _delegator;
    
    event DelegateAppointed(address indexed previousDelegator, address indexed newDelegator);
    
    constructor () internal {
        _delegator = address(0);
    }
    
    /*
     * delegator를 가져옴
     */
    /*
     * Call-up Delegator
     */
    function delegator() public view returns (address) {
        return _delegator;
    }
    
    /*
     * delegator만 실행 가능하도록 지정하는 접근 제한
     */
    /*
     * Access restriction in which only appointed delegator is executable
     */
    modifier onlyDelegator() {
        require(isDelegator());
        _;
    }
    
    /*
     * owner 또는 delegator가 실행 가능하도록 지정하는 접근 제한
     */
    /*
     * Access restriction in which only appointed delegator or Owner are executable
     */
    modifier ownerOrDelegator() {
        require(isOwner() || isDelegator());
        _;
    }
    
    function isDelegator() public view returns (bool) {
        return msg.sender == _delegator;
    }
    
    /*
     * delegator를 임명
     */
    /*
     * Appoint the delegator
     */
    function appointDelegator(address delegator_) public onlyOwner returns (bool) {
        require(delegator_ != address(0));
        require(delegator_ != owner());
        return _appointDelegator(delegator_);
    }
    
    /*
     * 지정된 delegator를 해임
     */
    /*
     * Dimiss the appointed delegator
     */
    function dissmissDelegator() public onlyOwner returns (bool) {
        require(_delegator != address(0));
        return _appointDelegator(address(0));
    }
    
    /*
     * delegator를 변경하는 내부 함수
     */
    /*
     * An internal function that allows delegator changes 
     */
    function _appointDelegator(address delegator_) private returns (bool) {
        require(_delegator != delegator_);
        emit DelegateAppointed(_delegator, delegator_);
        _delegator = delegator_;
        return true;
    }
}
/*
 * It defines an interface where the Owner can appoint / dismiss an agent that can partially excercize privileges in lieu of the Owner's 
 */
function delegator() public view returns (address) {
    return _delegator;
}

/*
 * Call-up Delegator
 */