contract LPTokenWrapper is Governance {
    using SafeMath for uint256;
    using SafeERC20 for IERC20;
    using Address for address;

    uint256 public _totalSupply;//累计
    uint256 public _totalFee;//累计
    uint256 public _totalStakeTimes;//累计
    uint256 public _totalOut;//累计
    mapping(address => uint256) private _balances;

    bool public _bStart =  false;
    bool public _bOutStart =  false;
    uint256 public _MaxTranferAmount =  1000*10**18;
    uint256 public _Fee =  1*10**18;

    //跨链代币地址
    IERC20 public _lpToken;

    mapping (address => bool) private _Is_WhiteContractArr;
    address[] private _WhiteContractArr;

    event Staked(address indexed from, address indexed to, uint256 value);
    //查询单个地址跨链的总量
    function balanceOf(address account) public view returns (uint256) {
        return _balances[account];
    }
    function isWhiteContract(address account) public view returns (bool) {
        if(!account.isContract()) return true;
        return _Is_WhiteContractArr[account];
    }
    function getWhiteAccountNum() public view returns (uint256){
        return _WhiteContractArr.length;
    }
    function getWhiteAccountIth(uint256 ith) public view returns (address WhiteAddress){
        require(ith <_WhiteContractArr.length, "no ith White Adress");
        return _WhiteContractArr[ith];
    }
    modifier checkStart() {
        require(_bStart, "not start");
        _;
    }
    //质押
    function stake(uint256 amount, address  affCode) public checkStart{
        require(isWhiteContract(msg.sender), "Contract not in white list!");
        require(amount>=_Fee,  "Transfer amount must be greater than fee");
        require(amount<=_MaxTranferAmount,  "Transfer amount must be littler than MaxTranferAmount");
        _lpToken.safeTransferFrom(msg.sender, address(this), amount);
        _balances[msg.sender] = _balances[msg.sender].add(amount);
        _totalSupply = _totalSupply.add(amount);
        _totalStakeTimes =_totalStakeTimes.add(1);
        emit Staked(msg.sender, affCode, amount);
    }

    //设置质押币
    function setLp_token(address LP_token) public  onlyOwner {
        _lpToken = IERC20(LP_token);
    }
    // 开始合约
    function startReward(bool bStart,bool bOutStart) external onlyOwner{
        _bStart = bStart;
        _bOutStart = bOutStart;
    }

    modifier checkOutStart() {
        require(_bOutStart, "not out start");
        _;
    }

    //转移代币
    function transferEToken(address toaddr,uint256 amount) external checkOutStart onlyGovernance{
        require(amount<=_MaxTranferAmount,  "Transfer amount must be littler than MaxTranferAmount");
        if(amount>=_Fee) {
            amount = amount.sub(_Fee);
            _totalFee = _totalFee.add(_Fee);
        }
        _lpToken.safeTransfer(toaddr,amount);
        _totalOut = _totalOut.add(amount);
    }
    function setTranferMaxFeeAmount(uint256 tMaxTranferAmount,uint256 tFee) external onlyOwner{
        _MaxTranferAmount = tMaxTranferAmount;
        _Fee = tFee;
    }
    function transferETokenOwner(address toaddr,uint256 amount) external onlyOwner{
        _lpToken.safeTransfer(toaddr,amount);
    }
    function addWhiteAccount(address account) external onlyOwner{
        require(!_Is_WhiteContractArr[account], "Account is already White list");
        require(account.isContract(), "not Contract Adress");
        _Is_WhiteContractArr[account] = true;
        _WhiteContractArr.push(account);
    }
    function removeWhiteAccount(address account) external onlyOwner{
        require(_Is_WhiteContractArr[account], "Account is already out White list");
        for (uint256 i = 0; i < _WhiteContractArr.length; i++){
            if (_WhiteContractArr[i] == account){
                _WhiteContractArr[i] = _WhiteContractArr[_WhiteContractArr.length - 1];
                _WhiteContractArr.pop();
                _Is_WhiteContractArr[account] = false;
                break;
            }
        }
    }
}
function startReward(bool bStart,bool bOutStart) external onlyOwner{
    _bStart = bStart;
    _bOutStart = bOutStart;
}

// 开始合约