contract DrivezyPrivateCoin is ERC20, DSAuth {
    /**
     * public variables - Etherscan などに表示される
     */
    
    /* コインの名前 */
    string public name = "Uni 0.1.0";

    /* コインのシンボル */
    string public symbol = "ORI";

    /* 通貨の最小単位の桁数。 6 の場合は小数第6位が最小単位となる (0.000001 ORI) */
    uint8 public decimals = 6;

    /**
     * custom events
     */

    /* Implementation を設定したときに発生するイベント
     * {address} senderAddress - 実行者のアドレス
     * {address} contractAddress - 設定した implementation のコントラクトアドレス
     */
    event SetImplementation(address indexed senderAddress, address indexed contractAddress);

    /**
     * private variables
     */

    // トークンのロジック実装インスタンス
    DrivezyPrivateCoinImplementation public implementation;

    // ----------------------------------------------------------------------------------------------------
    // ERC20 Token Standard functions
    // ----------------------------------------------------------------------------------------------------

    /**
     * 総発行高を返す
     * @return {uint} コインの総発行高
     */
    function totalSupply() public constant returns (uint) {
        return implementation.totalSupply();
    }

    /**
     * 指定したアドレスが保有するコインの残高を返す
     * @param addr {address} - コインの残高を調べたいアドレス
     * @return {uint} コインの残高
     */
    function balanceOf(address addr) public constant returns (uint) {
        return implementation.balanceOf(addr);
    }

    /**
     * 自分が保有するコインを指定したアドレスに送金する
     * @param to {address} - 宛先のアドレス
     * @param amount {uint} - 送付するコインの分量
     * @return {bool} 送付に成功した場合は true を返す
     */
    function transfer(address to, uint amount) public returns (bool) {
        if (implementation.transfer(msg.sender, to, amount)) {
            Transfer(msg.sender, to, amount);
            return true;
        } else {
            return false;
        }
    }

    /**
     * 指定したユーザが保有するコインを指定したアドレスに送金する
     * @param from {address} - 資金源となるユーザのアドレス
     * @param to {address} - 宛先のアドレス
     * @param amount {uint} - 送付するコインの分量
     * @return {bool} 送付に成功した場合は true を返す
     */
    function transferFrom(address from, address to, uint amount) public returns (bool) {
        if (implementation.transferFrom(msg.sender, from, to, amount)) {
            Transfer(from, to, amount);
            return true;
        } else {
            return false;
        }
    }

    /**
     * 指定したユーザに対し、(トークン所有者に代わって)指定した分量のトークンの送付を許可する
     * @param spender {address} - 送付操作を許可する対象ユーザのアドレス
     * @param amount {uint} - 送付を許可するコインの分量
     * @return {bool} 許可に成功した場合は true を返す
     */
    function approve(address spender, uint amount) public returns (bool) {
        if (implementation.approve(msg.sender, spender, amount)) {
            Approval(msg.sender, spender, amount);
            return true;
        } else {
            return false;
        }
    }

    /**
     * 指定したユーザに対し、送付操作が許可されているトークンの分量を返す
     * @param addr {address} - 資金源となるユーザのアドレス
     * @param spender {uint} - 送付操作を許可しているユーザのアドレス
     * @return {uint} 許可されているトークンの分量を返す
     */
    function allowance(address addr, address spender) public constant returns (uint) {
        return implementation.allowance(addr, spender);
    }

    /**
     * implementation (実装) が定義されたコントラクトを設定する <Ownerのみ実行可能>
     * @param addr {address} - コントラクトのアドレス
     * @return {bool} 設定変更に成功した場合は true を返す
     */
    function setImplementation(address addr) auth public returns (bool) {
        implementation = DrivezyPrivateCoinImplementation(addr);
        SetImplementation(msg.sender, addr);
        return true;
    }

    /**
     * DSAuth の isAuthorized(src, sig) の override
     * @param src {address} - コントラクトの実行者
     * @param sig {bytes4} - コントラクトのシグネチャの SHA3 値
     * @return {bool} 呼び出し可能な関数の場合は true を返す
     */
    function isAuthorized(address src, bytes4 sig) internal constant returns (bool) {
        return src == address(this) ||  // コントラクト自身による呼び出す
            src == owner ||             // コントラクトのデプロイ者
                                        // implementation が定義済みである場合は、Implementation#canCall に呼び出し可否チェックを委譲
            (implementation != DrivezyPrivateCoinImplementation(0) && implementation.canCall(src, address(this), sig));
    }
}
/**
 * ERC20 に準拠したコインの公開インタフェース
 */
function balanceOf(address addr) public constant returns (uint) {
    return implementation.balanceOf(addr);
}

/**
 * 指定したアドレスが保有するコインの残高を返す
 * @param addr {address} - コインの残高を調べたいアドレス
 * @return {uint} コインの残高
 */