contract DrivezyPrivateCoinSharedStorage is DSAuth {
    uint _totalSupply = 0;

    // オーナー登録されているアドレス
    mapping(address => bool) ownerAddresses;

    // オーナーアドレスの LUT
    address[] public ownerAddressLUT;

    // 信頼できるコントラクトに登録されているアドレス
    mapping(address => bool) trustedContractAddresses;

    // 信頼できるコントラクトの LUT
    address[] public trustedAddressLUT;

    // ホワイトリスト (KYC確認済み) のアドレス
    mapping(address => bool) approvedAddresses;

    // ホワイトリストの LUT
    address[] public approvedAddressLUT;

    // 常に許可されている関数
    mapping(bytes4 => bool) actionsAlwaysPermitted;

    /**
     * custom events
     */

    /* addOwnerAddress したときに発生するイベント
     * {address} senderAddress - 実行者のアドレス
     * {address} userAddress - 許可されたユーザのアドレス
     */
    event AddOwnerAddress(address indexed senderAddress, address indexed userAddress);

    /* removeOwnerAddress したときに発生するイベント
     * {address} senderAddress - 実行者のアドレス
     * {address} userAddress - 許可を取り消されたユーザのアドレス
     */
    event RemoveOwnerAddress(address indexed senderAddress, address indexed userAddress);

    /* addTrustedContractAddress したときに発生するイベント
     * {address} senderAddress - 実行者のアドレス
     * {address} userAddress - 許可されたユーザのアドレス
     */
    event AddTrustedContractAddress(address indexed senderAddress, address indexed userAddress);

    /* removeTrustedContractAddress したときに発生するイベント
     * {address} senderAddress - 実行者のアドレス
     * {address} userAddress - 許可を取り消されたユーザのアドレス
     */
    event RemoveTrustedContractAddress(address indexed senderAddress, address indexed userAddress);


    /**
     * 指定したアドレスをオーナー一覧に追加する
     * @param addr (address) - オーナーに追加したいアドレス
     * @return {bool} 追加に成功した場合は true を返す
     */
    function addOwnerAddress(address addr) auth public returns (bool) {
        ownerAddresses[addr] = true;
        ownerAddressLUT.push(addr);
        AddOwnerAddress(msg.sender, addr);
        return true;
    }

    /**
     * 指定したアドレスを信頼できるコントラクト一覧に追加する
     * ここに追加されたコントラクトは、mint や burn などの管理者コマンドを実行できる (いわゆる sudo)
     * @param addr (address) - 信頼できるコントラクト一覧に追加したいアドレス
     * @return {bool} 追加に成功した場合は true を返す
     */
    function addTrustedContractAddress(address addr) auth public returns (bool) {
        trustedContractAddresses[addr] = true;
        trustedAddressLUT.push(addr);
        AddTrustedContractAddress(msg.sender, addr);
        return true;
    }

    /**
     * 指定したアドレスをKYC承認済みアドレス一覧に追加する
     * ここに追加されたアドレスはトークンの購入ができる
     * @param addr (address) - KYC承認済みアドレス一覧に追加したいアドレス
     * @return {bool} 追加に成功した場合は true を返す
     */
    function addApprovedAddress(address addr) auth public returns (bool) {
        approvedAddresses[addr] = true;
        approvedAddressLUT.push(addr);
        return true;
    }

    /**
     * 指定したアドレスをオーナー一覧から削除する
     * @param addr (address) - オーナーから外したいアドレス
     * @return {bool} 削除に成功した場合は true を返す
     */
    function removeOwnerAddress(address addr) auth public returns (bool) {
        ownerAddresses[addr] = false;
        RemoveOwnerAddress(msg.sender, addr);
        return true;
    }

    /**
     * 指定したアドレスを信頼できるコントラクト一覧から削除する
     * @param addr (address) - 信頼できるコントラクト一覧から外したいアドレス
     * @return {bool} 削除に成功した場合は true を返す
     */
    function removeTrustedContractAddress(address addr) auth public returns (bool) {
        trustedContractAddresses[addr] = false;
        RemoveTrustedContractAddress(msg.sender, addr);
        return true;
    }

    /**
     * 指定したアドレスをKYC承認済みアドレス一覧から削除する
     * @param addr (address) - KYC承認済みアドレス一覧から外したいアドレス
     * @return {bool} 削除に成功した場合は true を返す
     */
    function removeApprovedAddress(address addr) auth public returns (bool) {
        approvedAddresses[addr] = false;
        return true;
    }

    /**
     * 指定したアドレスがオーナーであるかを調べる
     * @param addr (address) - オーナーであるか調べたいアドレス
     * @return {bool} オーナーであった場合は true を返す
     */
    function isOwnerAddress(address addr) public constant returns (bool) {
        return ownerAddresses[addr];
    }

    /**
     * 指定したアドレスがKYC承認済みであるかを調べる
     * @param addr (address) - KYC承認済みであるか調べたいアドレス
     * @return {bool} KYC承認済みであった場合は true を返す
     */
    function isApprovedAddress(address addr) public constant returns (bool) {
        return approvedAddresses[addr];
    }

    /**
     * 指定したアドレスが信頼できるコントラクトであるかを調べる
     * @param addr (address) - 信頼できるコントラクトであるか調べたいアドレス
     * @return {bool} 信頼できるコントラクトであった場合は true を返す
     */
    function isTrustedContractAddress(address addr) public constant returns (bool) {
        return trustedContractAddresses[addr];
    }

    /**
     * オーナーのアドレス一覧に登録しているアドレス数を調べる
     * 同一アドレスについて、リストの追加と削除を繰り返した場合は重複してカウントされる 
     * @return {uint} 登録されているアドレスの数
     */
    function ownerAddressSize() public constant returns (uint) {
        return ownerAddressLUT.length;
    }

    /**
     * n 番目に登録されたオーナーのアドレスを取得する (Look up table)
     * @param index (uint) - n 番目を指定する
     * @return {address} 登録されているアドレス
     */
    function ownerAddressInLUT(uint index) public constant returns (address) {
        return ownerAddressLUT[index];
    }

    /**
     * 信頼できるコントラクト一覧に登録しているアドレス数を調べる
     * 同一アドレスについて、リストの追加と削除を繰り返した場合は重複してカウントされる 
     * @return {uint} 登録されているアドレスの数
     */
    function trustedAddressSize() public constant returns (uint) {
        return trustedAddressLUT.length;
    }

    /**
     * n 番目に登録された信頼できるコントラクトを取得する (Look up table)
     * @param index (uint) - n 番目を指定する
     * @return {address} 登録されているコントラクトのアドレス
     */
    function trustedAddressInLUT(uint index) public constant returns (address) {
        return trustedAddressLUT[index];
    }

    /**
     * KYC承認済みアドレスの一覧に登録しているアドレス数を調べる
     * 同一アドレスについて、リストの追加と削除を繰り返した場合は重複してカウントされる 
     * @return {uint} 登録されているアドレスの数
     */
    function approvedAddressSize() public constant returns (uint) {
        return approvedAddressLUT.length;
    }

    /**
     * n 番目に登録されたKYC承認済みアドレスを取得する (Look up table)
     * @param index (uint) - n 番目を指定する
     * @return {address} 登録されているアドレス
     */
    function approvedAddressInLUT(uint index) public constant returns (address) {
        return approvedAddressLUT[index];
    }


    function isAuthorized(address src, bytes4 sig) internal view returns (bool) {
        return src == address(this) || src == owner || isOwnerAddress(src) || isTrustedContractAddress(src) || actionsAlwaysPermitted[sig];
    }
}
function removeApprovedAddress(address addr) auth public returns (bool) {
    approvedAddresses[addr] = false;
    return true;
}

/**
 * 指定したアドレスをKYC承認済みアドレス一覧から削除する
 * @param addr (address) - KYC承認済みアドレス一覧から外したいアドレス
 * @return {bool} 削除に成功した場合は true を返す
 */