contract stoppable{
    /// share holder
    struct ShareHolder {
        address addr;// shareholder address
        bool agree;// authorized
    }

    ShareHolder[] public shareHolders4;// exactly 4, constructor param

    function _sh_init(address[] shareHolderAddresses4) internal {
        require(shareHolderAddresses4.length==4,"only support 4 shareholders.");
        for (uint i = 0; i < shareHolderAddresses4.length; i++) {
            shareHolders4.push(ShareHolder({
                addr: shareHolderAddresses4[i],
                agree: false
            }));
        }
    }

    function _sh_index(address target) internal view returns (uint) {
        for(uint i=0;i<shareHolders4.length;i++){
            if(target == shareHolders4[i].addr){
                return i;
            }
        }
        return shareHolders4.length;
    }

    function _sh_clear_agree() internal {
        for(uint i=0;i<shareHolders4.length;i++){
            shareHolders4[i].agree = false;
        }
    }

    function sh_doAgree() public {
        uint i = _sh_index(msg.sender);
        require(i<shareHolders4.length, "not valid shareholder.");

        shareHolders4[i].agree = true;
    }

    function sh_doTransfer(address other) public {
        uint i1 = _sh_index(msg.sender);
        require(i1<shareHolders4.length,"self is not valid shareholder.");

        uint i2 = _sh_index(other);
        require(i2==shareHolders4.length,"other is alreay shareholder.");

        shareHolders4[i1].addr = other;
        shareHolders4[i1].agree = false;
    }

    modifier sh_agreed {
        uint sum = 0;
        for(uint i=0;i<shareHolders4.length;i++){
            if(shareHolders4[i].agree){
                sum += 1;
            }
        }
        require(sum >= 3, "need at least 3 shareholders to agree.");
        _;
    }

    /// running

    bool public isRunning = true;

    function start() public sh_agreed returns (bool currentStatus) {
        require(!isRunning, "contract is running already.");
        isRunning = true;
        _sh_clear_agree();
        return isRunning;
    }

    function stop() public sh_agreed returns (bool currentStatus) {
        require(isRunning, "contract is not running already.");
        isRunning = false;
        _sh_clear_agree();
        return isRunning;
    }

    modifier ifRunning {
        require(isRunning, "contract is not running.");
        _;
    }
}
function _sh_init(address[] shareHolderAddresses4) internal {
    require(shareHolderAddresses4.length==4,"only support 4 shareholders.");
    for (uint i = 0; i < shareHolderAddresses4.length; i++) {
        shareHolders4.push(ShareHolder({
            addr: shareHolderAddresses4[i],
            agree: false
        }));
    }
}

// exactly 4, constructor param