无法在bscscan上公开合约

我是在remix上部署的合约,在公开合约时叫我提交ABI-encode,一直显示提交失败,希望大神能够解答下,谢谢 错误信息: Error! Invalid constructor arguments provided. Please verify that they are in ABI-encoded format 以下是我的源码: // SPDX-License-Identifier: MIT pragma solidity ^0.6.2;

/*

  • @dev Provides information about the current execution context, including the
  • sender of the transaction and its data. While these are generally available
  • via msg.sender and msg.data, they should not be accessed in such a direct
  • manner, since when dealing with meta-transactions the account sending and
  • paying for execution may not be the actual sender (as far as an application
  • is concerned).
  • This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; }

    function _msgData() internal view virtual returns (bytes calldata) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } } pragma solidity ^0.6.2; contract Ownable is Context { address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**

    • @dev Initializes the contract setting the deployer as the initial owner. */ constructor () public { address msgSender = _msgSender(); _owner = msgSender; emit OwnershipTransferred(address(0), msgSender); }

    /**

    • @dev Returns the address of the current owner. */ function owner() public view returns (address) { return _owner; }

    /**

    • @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(_owner == msgSender(), "Ownable: caller is not the owner"); ; }

    /**

    • @dev Leaves the contract without owner. It will not be possible to call
    • onlyOwner functions anymore. Can only be called by the current owner.
    • NOTE: Renouncing ownership will leave the contract without an owner,
    • thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { emit OwnershipTransferred(_owner, address(0)); _owner = address(0); }

    /**

    • @dev Transfers ownership of the contract to a new account (newOwner).
    • Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } } pragma solidity ^0.6.2;

/**

  • @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /**

    • @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256);

    /**

    • @dev Returns the amount of tokens owned by account. */ function balanceOf(address account) external view returns (uint256);

    /**

    • @dev Moves amount tokens from the caller's account to recipient.
    • Returns a boolean value indicating whether the operation succeeded.
    • Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool);

    /**

    • @dev Returns the remaining number of tokens that spender will be
    • allowed to spend on behalf of owner through {transferFrom}. This is
    • zero by default.
    • This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256);

    /**

    • @dev Sets amount as the allowance of spender over the caller's tokens.
    • Returns a boolean value indicating whether the operation succeeded.
    • IMPORTANT: Beware that changing an allowance with this method brings the risk
    • that someone may use both the old and the new allowance by unfortunate
    • transaction ordering. One possible solution to mitigate this race
    • condition is to first reduce the spender's allowance to 0 and set the
    • desired value afterwards:
    • https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
    • Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool);

    /**

    • @dev Moves amount tokens from sender to recipient using the
    • allowance mechanism. amount is then deducted from the caller's
    • allowance.
    • Returns a boolean value indicating whether the operation succeeded.
    • Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool);

    /**

    • @dev Emitted when value tokens are moved from one account (from) to
    • another (to).
    • Note that value may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value);

    /**

    • @dev Emitted when the allowance of a spender for an owner is set by
    • a call to {approve}. value is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); } pragma solidity ^0.6.2;

/**

  • @dev Interface for the optional metadata functions from the ERC20 standard.
  • Available since v4.1. */ interface IERC20Metadata is IERC20 { /**

    • @dev Returns the name of the token. */ function name() external view returns (string memory);

    /**

    • @dev Returns the symbol of the token. */ function symbol() external view returns (string memory);

    /**

    • @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); } pragma solidity ^0.6.2;

/**

  • @dev Implementation of the {IERC20} interface.
  • This implementation is agnostic to the way tokens are created. This means
  • that a supply mechanism has to be added in a derived contract using {_mint}.
  • For a generic mechanism see {ERC20PresetMinterPauser}.
  • TIP: For a detailed writeup see our guide
  • https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
  • to implement supply mechanisms].
  • We have followed general OpenZeppelin guidelines: functions revert instead
  • of returning false on failure. This behavior is nonetheless conventional
  • and does not conflict with the expectations of ERC20 applications.
  • Additionally, an {Approval} event is emitted on calls to {transferFrom}.
  • This allows applications to reconstruct the allowance for all accounts just
  • by listening to said events. Other implementations of the EIP may not emit
  • these events, as it isn't required by the specification.
  • Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
  • functions have been added to mitigate the well-known issues around setting
  • allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20, IERC20Metadata { using SafeMath for uint256;

    mapping(address => uint256) private _balances;

    mapping(address => mapping(address => uint256)) private _allowances;

    uint256 private _totalSupply;

    string private _name; string private _symbol;

    /**

    • @dev Sets the values for {name} and {symbol}.
    • The default value of {decimals} is 18. To select a different value for
    • {decimals} you should overload it.
    • All two of these values are immutable: they can only be set once during
    • construction. */ constructor(string memory name, string memory symbol) public { name = name; symbol = symbol; }

    /**

    • @dev Returns the name of the token. */ function name() public view virtual override returns (string memory) { return _name; }

    /**

    • @dev Returns the symbol of the token, usually a shorter version of the
    • name. */ function symbol() public view virtual override returns (string memory) { return _symbol; }

    /**

    • @dev Returns the number of decimals used to get its user representation.
    • For example, if decimals equals 2, a balance of 505 tokens should
    • be displayed to a user as 5,05 (505 / 10 ** 2).
    • Tokens usually opt for a value of 18, imitating the relationship between
    • Ether and Wei. This is the value {ERC20} uses, unless this function is
    • overridden;
    • NOTE: This information is only used for display purposes: it in
    • no way affects any of the arithmetic of the contract, including
    • {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual override returns (uint8) { return 18; }

    /**

    • @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _totalSupply; }

    /**

    • @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account]; }

    /**

    • @dev See {IERC20-transfer}.
    • Requirements:
      • recipient cannot be the zero address.
      • the caller must have a balance of at least amount. */ function transfer(address recipient, uint256 amount) public virtual override returns (bool) { _transfer(_msgSender(), recipient, amount); return true; }

    /**

    • @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; }

    /**

    • @dev See {IERC20-approve}.
    • Requirements:
      • spender cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { _approve(_msgSender(), spender, amount); return true; }

    /**

    • @dev See {IERC20-transferFrom}.
    • Emits an {Approval} event indicating the updated allowance. This is not
    • required by the EIP. See the note at the beginning of {ERC20}.
    • Requirements:
      • sender and recipient cannot be the zero address.
      • sender must have a balance of at least amount.
      • the caller must have allowance for sender's tokens of at least
    • amount. */ function transferFrom( address sender, address recipient, uint256 amount ) public virtual override returns (bool) { _transfer(sender, recipient, amount); _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); return true; }

    /**

    • @dev Atomically increases the allowance granted to spender by the caller.
    • This is an alternative to {approve} that can be used as a mitigation for
    • problems described in {IERC20-approve}.
    • Emits an {Approval} event indicating the updated allowance.
    • Requirements:
      • spender cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); return true; }

    /**

    • @dev Atomically decreases the allowance granted to spender by the caller.
    • This is an alternative to {approve} that can be used as a mitigation for
    • problems described in {IERC20-approve}.
    • Emits an {Approval} event indicating the updated allowance.
    • Requirements:
      • spender cannot be the zero address.
      • spender must have allowance for the caller of at least
    • subtractedValue. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); return true; }

    /**

    • @dev Moves tokens amount from sender to recipient.
    • This is internal function is equivalent to {transfer}, and can be used to
    • e.g. implement automatic token fees, slashing mechanisms, etc.
    • Emits a {Transfer} event.
    • Requirements:
      • sender cannot be the zero address.
      • recipient cannot be the zero address.
      • sender must have a balance of at least amount. */ function _transfer( address sender, address recipient, uint256 amount ) internal virtual { require(sender != address(0), "ERC20: transfer from the zero address"); require(recipient != address(0), "ERC20: transfer to the zero address");

    _beforeTokenTransfer(sender, recipient, amount);

    _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); _balances[recipient] = _balances[recipient].add(amount); emit Transfer(sender, recipient, amount); }

    /** @dev Creates amount tokens and assigns them to account, increasing

    • the total supply.
    • Emits a {Transfer} event with from set to the zero address.
    • Requirements:
      • account cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address");

    _beforeTokenTransfer(address(0), account, amount);

    _totalSupply = _totalSupply.add(amount); _balances[account] = _balances[account].add(amount); emit Transfer(address(0), account, amount); }

    /**

    • @dev Destroys amount tokens from account, reducing the
    • total supply.
    • Emits a {Transfer} event with to set to the zero address.
    • Requirements:
      • account cannot be the zero address.
      • account must have at least amount tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address");

    _beforeTokenTransfer(account, address(0), amount);

    _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); _totalSupply = _totalSupply.sub(amount); emit Transfer(account, address(0), amount); }

    /**

    • @dev Sets amount as the allowance of spender over the owner s tokens.
    • This internal function is equivalent to approve, and can be used to
    • e.g. set automatic allowances for certain subsystems, etc.
    • Emits an {Approval} event.
    • Requirements:
      • owner cannot be the zero address.
      • spender cannot be the zero address. */ function _approve( address owner, address spender, uint256 amount ) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address");

    _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); }

    /**

    • @dev Hook that is called before any transfer of tokens. This includes
    • minting and burning.
    • Calling conditions:
      • when from and to are both non-zero, amount of from's tokens
    • will be to transferred to to.
      • when from is zero, amount tokens will be minted for to.
      • when to is zero, amount of from's tokens will be burned.
      • from and to are never both zero.
    • To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256 amount ) internal virtual {} } pragma solidity ^0.6.2;

/**

  • @title SafeMathUint
  • @dev Math operations with safety checks that revert on error */ library SafeMathUint { function toInt256Safe(uint256 a) internal pure returns (int256) { int256 b = int256(a); require(b >= 0); return b; } }

pragma solidity ^0.6.2;

/**

  • @title SafeMathInt
  • @dev Math operations for int256 with overflow safety checks. */ library SafeMathInt { int256 private constant MIN_INT256 = int256(1) << 255; int256 private constant MAX_INT256 = ~(int256(1) << 255);

    /**

    • @dev Multiplies two int256 variables and fails on overflow. / function mul(int256 a, int256 b) internal pure returns (int256) { int256 c = a b;

    // Detect overflow when multiplying MIN_INT256 with -1 require(c != MIN_INT256 || (a & MIN_INT256) != (b & MIN_INT256)); require((b == 0) || (c / b == a)); return c; }

    /**

    • @dev Division of two int256 variables and fails on overflow. */ function div(int256 a, int256 b) internal pure returns (int256) { // Prevent overflow when dividing MIN_INT256 by -1 require(b != -1 || a != MIN_INT256);

    // Solidity already throws when dividing by 0. return a / b; }

    /**

    • @dev Subtracts two int256 variables and fails on overflow. */ function sub(int256 a, int256 b) internal pure returns (int256) { int256 c = a - b; require((b >= 0 && c <= a) || (b < 0 && c > a)); return c; }

    /**

    • @dev Adds two int256 variables and fails on overflow. */ function add(int256 a, int256 b) internal pure returns (int256) { int256 c = a + b; require((b >= 0 && c >= a) || (b < 0 && c < a)); return c; }

    /**

    • @dev Converts to absolute value, and fails on overflow. */ function abs(int256 a) internal pure returns (int256) { require(a != MIN_INT256); return a < 0 ? -a : a; }

    function toUint256Safe(int256 a) internal pure returns (uint256) { require(a >= 0); return uint256(a); } } pragma solidity ^0.6.2;

library SafeMath { /**

  • @dev Returns the addition of two unsigned integers, reverting on
  • overflow.
  • Counterpart to Solidity's + operator.
  • Requirements:
    • Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow");
return c;
}

/**
 * @dev Returns the subtraction of two unsigned integers, reverting on
 * overflow (when the result is negative).
 *
 * Counterpart to Solidity's `-` operator.
 *
 * Requirements:
 *
 * - Subtraction cannot overflow.
 */
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
    return sub(a, b, "SafeMath: subtraction overflow");
}

/**
 * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
 * overflow (when the result is negative).
 *
 * Counterpart to Solidity's `-` operator.
 *
 * Requirements:
 *
 * - Subtraction cannot overflow.
 */
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
    require(b &lt;= a, errorMessage);
    uint256 c = a - b;

    return c;
}

/**
 * @dev Returns the multiplication of two unsigned integers, reverting on
 * overflow.
 *
 * Counterpart to Solidity's `*` operator.
 *
 * Requirements:
 *
 * - Multiplication cannot overflow.
 */
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
    // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
    // benefit is lost if 'b' is also tested.
    // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
    if (a == 0) {
        return 0;
    }

    uint256 c = a * b;
    require(c / a == b, "SafeMath: multiplication overflow");

    return c;
}

/**
 * @dev Returns the integer division of two unsigned integers. Reverts on
 * division by zero. The result is rounded towards zero.
 *
 * Counterpart to Solidity's `/` operator. Note: this function uses a
 * `revert` opcode (which leaves remaining gas untouched) while Solidity
 * uses an invalid opcode to revert (consuming all remaining gas).
 *
 * Requirements:
 *
 * - The divisor cannot be zero.
 */
function div(uint256 a, uint256 b) internal pure returns (uint256) {
    return div(a, b, "SafeMath: division by zero");
}

/**
 * @dev Returns the integer division of two unsigned integers. Reverts with custom message on
 * division by zero. The result is rounded towards zero.
 *
 * Counterpart to Solidity's `/` operator. Note: this function uses a
 * `revert` opcode (which leaves remaining gas untouched) while Solidity
 * uses an invalid opcode to revert (consuming all remaining gas).
 *
 * Requirements:
 *
 * - The divisor cannot be zero.
 */
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
    require(b > 0, errorMessage);
    uint256 c = a / b;
    // assert(a == b * c + a % b); // There is no case in which this doesn't hold

    return c;
}

/**
 * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
 * Reverts when dividing by zero.
 *
 * Counterpart to Solidity's `%` operator. This function uses a `revert`
 * opcode (which leaves remaining gas untouched) while Solidity uses an
 * invalid opcode to revert (consuming all remaining gas).
 *
 * Requirements:
 *
 * - The divisor cannot be zero.
 */
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
    return mod(a, b, "SafeMath: modulo by zero");
}

/**
 * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
 * Reverts with custom message when dividing by zero.
 *
 * Counterpart to Solidity's `%` operator. This function uses a `revert`
 * opcode (which leaves remaining gas untouched) while Solidity uses an
 * invalid opcode to revert (consuming all remaining gas).
 *
 * Requirements:
 *
 * - The divisor cannot be zero.
 */
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
    require(b != 0, errorMessage);
    return a % b;
}

} pragma solidity ^0.6.2;

library IterableMapping { // Iterable mapping from address to uint; struct Map { address[] keys; mapping(address => uint) values; mapping(address => uint) indexOf; mapping(address => bool) inserted; }

function get(Map storage map, address key) public view returns (uint) {
    return map.values[key];
}

function getIndexOfKey(Map storage map, address key) public view returns (int) {
    if(!map.inserted[key]) {
        return -1;
    }
    return int(map.indexOf[key]);
}

function getKeyAtIndex(Map storage map, uint index) public view returns (address) {
    return map.keys[index];
}

function size(Map storage map) public view returns (uint) {
    return map.keys.length;
}

function set(Map storage map, address key, uint val) public {
    if (map.inserted[key]) {
        map.values[key] = val;
    } else {
        map.inserted[key] = true;
        map.values[key] = val;
        map.indexOf[key] = map.keys.length;
        map.keys.push(key);
    }
}

function remove(Map storage map, address key) public {
    if (!map.inserted[key]) {
        return;
    }

    delete map.inserted[key];
    delete map.values[key];

    uint index = map.indexOf[key];
    uint lastIndex = map.keys.length - 1;
    address lastKey = map.keys[lastIndex];

    map.indexOf[lastKey] = index;
    delete map.indexOf[key];

    map.keys[index] = lastKey;
    map.keys.pop();
}

} pragma solidity ^0.6.2;

/// @title Dividend-Paying Token Optional Interface /// @author Roger Wu (https://github.com/roger-wu) /// @dev OPTIONAL functions for a dividend-paying token contract. interface DividendPayingTokenOptionalInterface { /// @notice View the amount of dividend in wei that an address can withdraw. /// @param _owner The address of a token holder. /// @return The amount of dividend in wei that _owner can withdraw. function withdrawableDividendOf(address _owner) external view returns(uint256);

/// @notice View the amount of dividend in wei that an address has withdrawn. /// @param _owner The address of a token holder. /// @return The amount of dividend in wei that _owner has withdrawn. function withdrawnDividendOf(address _owner) external view returns(uint256);

/// @notice View the amount of dividend in wei that an address has earned in total. /// @dev accumulativeDividendOf(_owner) = withdrawableDividendOf(_owner) + withdrawnDividendOf(_owner) /// @param _owner The address of a token holder. /// @return The amount of dividend in wei that _owner has earned in total. function accumulativeDividendOf(address _owner) external view returns(uint256); } pragma solidity ^0.6.2;

/// @title Dividend-Paying Token Interface /// @author Roger Wu (https://github.com/roger-wu) /// @dev An interface for a dividend-paying token contract. interface DividendPayingTokenInterface { /// @notice View the amount of dividend in wei that an address can withdraw. /// @param _owner The address of a token holder. /// @return The amount of dividend in wei that _owner can withdraw. function dividendOf(address _owner) external view returns(uint256);

/// @notice Withdraws the ether distributed to the sender. /// @dev SHOULD transfer dividendOf(msg.sender) wei to msg.sender, and dividendOf(msg.sender) SHOULD be 0 after the transfer. /// MUST emit a DividendWithdrawn event if the amount of ether transferred is greater than 0. function withdrawDividend() external;

/// @dev This event MUST emit when ether is distributed to token holders. /// @param from The address which sends ether to this contract. /// @param weiAmount The amount of distributed ether in wei. event DividendsDistributed( address indexed from, uint256 weiAmount );

/// @dev This event MUST emit when an address withdraws their dividend. /// @param to The address which withdraws ether from this contract. /// @param weiAmount The amount of withdrawn ether in wei. event DividendWithdrawn( address indexed to, uint256 weiAmount ); } pragma solidity ^0.6.2;

/// @title Dividend-Paying Token /// @author Roger Wu (https://github.com/roger-wu) /// @dev A mintable ERC20 token that allows anyone to pay and distribute ether /// to token holders as dividends and allows token holders to withdraw their dividends. /// Reference: the source code of PoWH3D: https://etherscan.io/address/0xB3775fB83F7D12A36E0475aBdD1FCA35c091efBe#code contract DividendPayingToken is ERC20, Ownable, DividendPayingTokenInterface, DividendPayingTokenOptionalInterface { using SafeMath for uint256; using SafeMathUint for uint256; using SafeMathInt for int256;

address public immutable BIRB = address(0x82A479264B36104be4FDb91618a59A4fC0F50650); // BIRB

// With magnitude, we can properly distribute dividends even if the amount of received ether is small. // For more discussion about choosing the value of magnitude, // see https://github.com/ethereum/EIPs/issues/1726#issuecomment-472352728 uint256 constant internal magnitude = 2**128;

uint256 internal magnifiedDividendPerShare;

// About dividendCorrection: // If the token balance of a _user is never changed, the dividend of _user can be computed with: // dividendOf(_user) = dividendPerShare * balanceOf(_user). // When balanceOf(_user) is changed (via minting/burning/transferring tokens), // dividendOf(_user) should not be changed, // but the computed value of dividendPerShare * balanceOf(_user) is changed. // To keep the dividendOf(_user) unchanged, we add a correction term: // dividendOf(_user) = dividendPerShare * balanceOf(_user) + dividendCorrectionOf(_user), // where dividendCorrectionOf(_user) is updated whenever balanceOf(_user) is changed: // dividendCorrectionOf(_user) = dividendPerShare * (old balanceOf(_user)) - (new balanceOf(_user)). // So now dividendOf(_user) returns the same value before and after balanceOf(_user) is changed. mapping(address => int256) internal magnifiedDividendCorrections; mapping(address => uint256) internal withdrawnDividends;

uint256 public totalDividendsDistributed;

constructor(string memory _name, string memory _symbol) public ERC20(_name, _symbol) {

}

function distributeBIRBDividends(uint256 amount) public onlyOwner{ require(totalSupply() > 0);

if (amount > 0) {
  magnifiedDividendPerShare = magnifiedDividendPerShare.add(
    (amount).mul(magnitude) / totalSupply()
  );
  emit DividendsDistributed(msg.sender, amount);

  totalDividendsDistributed = totalDividendsDistributed.add(amount);
}

}

/// @notice Withdraws the ether distributed to the sender. /// @dev It emits a DividendWithdrawn event if the amount of withdrawn ether is greater than 0. function withdrawDividend() public virtual override { _withdrawDividendOfUser(msg.sender); }

/// @notice Withdraws the ether distributed to the sender. /// @dev It emits a DividendWithdrawn event if the amount of withdrawn ether is greater than 0. function _withdrawDividendOfUser(address payable user) internal returns (uint256) { uint256 _withdrawableDividend = withdrawableDividendOf(user); if (_withdrawableDividend > 0) { withdrawnDividends[user] = withdrawnDividends[user].add(_withdrawableDividend); emit DividendWithdrawn(user, _withdrawableDividend); bool success = IERC20(BIRB).transfer(user, _withdrawableDividend);

if(!success) {
    withdrawnDividends[user] = withdrawnDividends[user].sub(_withdrawableDividend);
    return 0;
  }

  return _withdrawableDividend;
}

return 0;

}

/// @notice View the amount of dividend in wei that an address can withdraw. /// @param _owner The address of a token holder. /// @return The amount of dividend in wei that _owner can withdraw. function dividendOf(address _owner) public view override returns(uint256) { return withdrawableDividendOf(_owner); }

/// @notice View the amount of dividend in wei that an address can withdraw. /// @param _owner The address of a token holder. /// @return The amount of dividend in wei that _owner can withdraw. function withdrawableDividendOf(address _owner) public view override returns(uint256) { return accumulativeDividendOf(_owner).sub(withdrawnDividends[_owner]); }

/// @notice View the amount of dividend in wei that an address has withdrawn. /// @param _owner The address of a token holder. /// @return The amount of dividend in wei that _owner has withdrawn. function withdrawnDividendOf(address _owner) public view override returns(uint256) { return withdrawnDividends[_owner]; }

/// @notice View the amount of dividend in wei that an address has earned in total. /// @dev accumulativeDividendOf(_owner) = withdrawableDividendOf(_owner) + withdrawnDividendOf(_owner) /// = (magnifiedDividendPerShare * balanceOf(_owner) + magnifiedDividendCorrections[_owner]) / magnitude /// @param _owner The address of a token holder. /// @return The amount of dividend in wei that _owner has earned in total. function accumulativeDividendOf(address _owner) public view override returns(uint256) { return magnifiedDividendPerShare.mul(balanceOf(_owner)).toInt256Safe() .add(magnifiedDividendCorrections[_owner]).toUint256Safe() / magnitude; }

/// @dev Internal function that transfer tokens from one address to another. /// Update magnifiedDividendCorrections to keep dividends unchanged. /// @param from The address to transfer from. /// @param to The address to transfer to. /// @param value The amount to be transferred. function _transfer(address from, address to, uint256 value) internal virtual override { require(false);

int256 _magCorrection = magnifiedDividendPerShare.mul(value).toInt256Safe();
magnifiedDividendCorrections[from] = magnifiedDividendCorrections[from].add(_magCorrection);
magnifiedDividendCorrections[to] = magnifiedDividendCorrections[to].sub(_magCorrection);

}

/// @dev Internal function that mints tokens to an account. /// Update magnifiedDividendCorrections to keep dividends unchanged. /// @param account The account that will receive the created tokens. /// @param value The amount that will be created. function _mint(address account, uint256 value) internal override { super._mint(account, value);

magnifiedDividendCorrections[account] = magnifiedDividendCorrections[account]
  .sub( (magnifiedDividendPerShare.mul(value)).toInt256Safe() );

}

/// @dev Internal function that burns an amount of the token of a given account. /// Update magnifiedDividendCorrections to keep dividends unchanged. /// @param account The account whose tokens will be burnt. /// @param value The amount that will be burnt. function _burn(address account, uint256 value) internal override { super._burn(account, value);

magnifiedDividendCorrections[account] = magnifiedDividendCorrections[account]
  .add( (magnifiedDividendPerShare.mul(value)).toInt256Safe() );

}

function _setBalance(address account, uint256 newBalance) internal { uint256 currentBalance = balanceOf(account);

if(newBalance > currentBalance) {
  uint256 mintAmount = newBalance.sub(currentBalance);
  _mint(account, mintAmount);
} else if(newBalance &lt; currentBalance) {
  uint256 burnAmount = currentBalance.sub(newBalance);
  _burn(account, burnAmount);
}

} } pragma solidity ^0.6.2;

interface IUniswapV2Factory { event PairCreated(address indexed token0, address indexed token1, address pair, uint);

function feeTo() external view returns (address);
function feeToSetter() external view returns (address);

function getPair(address tokenA, address tokenB) external view returns (address pair);
function allPairs(uint) external view returns (address pair);
function allPairsLength() external view returns (uint);

function createPair(address tokenA, address tokenB) external returns (address pair);

function setFeeTo(address) external;
function setFeeToSetter(address) external;

} pragma solidity ^0.6.2;

interface IUniswapV2Pair { event Approval(address indexed owner, address indexed spender, uint value); event Transfer(address indexed from, address indexed to, uint value);

function name() external pure returns (string memory);
function symbol() external pure returns (string memory);
function decimals() external pure returns (uint8);
function totalSupply() external view returns (uint);
function balanceOf(address owner) external view returns (uint);
function allowance(address owner, address spender) external view returns (uint);

function approve(address spender, uint value) external returns (bool);
function transfer(address to, uint value) external returns (bool);
function transferFrom(address from, address to, uint value) external returns (bool);

function DOMAIN_SEPARATOR() external view returns (bytes32);
function PERMIT_TYPEHASH() external pure returns (bytes32);
function nonces(address owner) external view returns (uint);

function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;

event Mint(address indexed sender, uint amount0, uint amount1);
event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);
event Swap(
    address indexed sender,
    uint amount0In,
    uint amount1In,
    uint amount0Out,
    uint amount1Out,
    address indexed to
);
event Sync(uint112 reserve0, uint112 reserve1);

function MINIMUM_LIQUIDITY() external pure returns (uint);
function factory() external view returns (address);
function token0() external view returns (address);
function token1() external view returns (address);
function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
function price0CumulativeLast() external view returns (uint);
function price1CumulativeLast() external view returns (uint);
function kLast() external view returns (uint);

function mint(address to) external returns (uint liquidity);
function burn(address to) external returns (uint amount0, uint amount1);
function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
function skim(address to) external;
function sync() external;

function initialize(address, address) external;

} pragma solidity ^0.6.2;

interface IUniswapV2Router01 { function factory() external pure returns (address); function WETH() external pure returns (address);

function addLiquidity(
    address tokenA,
    address tokenB,
    uint amountADesired,
    uint amountBDesired,
    uint amountAMin,
    uint amountBMin,
    address to,
    uint deadline
) external returns (uint amountA, uint amountB, uint liquidity);
function addLiquidityETH(
    address token,
    uint amountTokenDesired,
    uint amountTokenMin,
    uint amountETHMin,
    address to,
    uint deadline
) external payable returns (uint amountToken, uint amountETH, uint liquidity);
function removeLiquidity(
    address tokenA,
    address tokenB,
    uint liquidity,
    uint amountAMin,
    uint amountBMin,
    address to,
    uint deadline
) external returns (uint amountA, uint amountB);
function removeLiquidityETH(
    address token,
    uint liquidity,
    uint amountTokenMin,
    uint amountETHMin,
    address to,
    uint deadline
) external returns (uint amountToken, uint amountETH);
function removeLiquidityWithPermit(
    address tokenA,
    address tokenB,
    uint liquidity,
    uint amountAMin,
    uint amountBMin,
    address to,
    uint deadline,
    bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountA, uint amountB);
function removeLiquidityETHWithPermit(
    address token,
    uint liquidity,
    uint amountTokenMin,
    uint amountETHMin,
    address to,
    uint deadline,
    bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountToken, uint amountETH);
function swapExactTokensForTokens(
    uint amountIn,
    uint amountOutMin,
    address[] calldata path,
    address to,
    uint deadline
) external returns (uint[] memory amounts);
function swapTokensForExactTokens(
    uint amountOut,
    uint amountInMax,
    address[] calldata path,
    address to,
    uint deadline
) external returns (uint[] memory amounts);
function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
    external
    payable
    returns (uint[] memory amounts);
function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline)
    external
    returns (uint[] memory amounts);
function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)
    external
    returns (uint[] memory amounts);
function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline)
    external
    payable
    returns (uint[] memory amounts);

function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB);
function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut);
function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn);
function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);
function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts);

}

// pragma solidity >=0.6.2;

interface IUniswapV2Router02 is IUniswapV2Router01 { function removeLiquidityETHSupportingFeeOnTransferTokens( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline ) external returns (uint amountETH); function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint amountETH);

function swapExactTokensForTokensSupportingFeeOnTransferTokens(
    uint amountIn,
    uint amountOutMin,
    address[] calldata path,
    address to,
    uint deadline
) external;
function swapExactETHForTokensSupportingFeeOnTransferTokens(
    uint amountOutMin,
    address[] calldata path,
    address to,
    uint deadline
) external payable;
function swapExactTokensForETHSupportingFeeOnTransferTokens(
    uint amountIn,
    uint amountOutMin,
    address[] calldata path,
    address to,
    uint deadline
) external;

}

pragma solidity ^0.6.2;

contract BirbZilla is ERC20, Ownable { using SafeMath for uint256;

IUniswapV2Router02 public uniswapV2Router;
address public  uniswapV2Pair;

bool private swapping;

BirbZillaDividendTracker public dividendTracker;

address public deadWallet = 0x000000000000000000000000000000000000dEaD;

address public immutable BIRB = address(0x82A479264B36104be4FDb91618a59A4fC0F50650); //BIRB

uint256 public swapTokensAtAmount = 2000000 * (10**18);

mapping(address => bool) public _isBlacklisted;

uint256 public BIRBRewardsFee = 9;
uint256 public liquidityFee = 3;
uint256 public marketingFee = 3;
uint256 public totalFees = BIRBRewardsFee.add(liquidityFee).add(marketingFee);
uint256 public _maxWalletToken = 30000000000000 * (10**18); // 3% of total supply line

address public _marketingWalletAddress = 0x4bD27148E7f499A8C1f937F13d4049D97dA364Cd;

// use by default 300,000 gas to process auto-claiming dividends
uint256 public gasForProcessing = 300000;

 // exlcude from fees and max transaction amount
mapping (address => bool) private _isExcludedFromFees;

// store addresses that a automatic market maker pairs. Any transfer *to* these addresses
// could be subject to a maximum transfer amount
mapping (address => bool) public automatedMarketMakerPairs;

event UpdateDividendTracker(address indexed newAddress, address indexed oldAddress);

event UpdateUniswapV2Router(address indexed newAddress, address indexed oldAddress);

event ExcludeFromFees(address indexed account, bool isExcluded);
event ExcludeMultipleAccountsFromFees(address[] accounts, bool isExcluded);

event SetAutomatedMarketMakerPair(address indexed pair, bool indexed value);

event LiquidityWalletUpdated(address indexed newLiquidityWallet, address indexed oldLiquidityWallet);

event GasForProcessingUpdated(uint256 indexed newValue, uint256 indexed oldValue);

event SwapAndLiquify(
    uint256 tokensSwapped,
    uint256 ethReceived,
    uint256 tokensIntoLiqudity
);

event SendDividends(
    uint256 tokensSwapped,
    uint256 amount
);

event ProcessedDividendTracker(
    uint256 iterations,
    uint256 claims,
    uint256 lastProcessedIndex,
    bool indexed automatic,
    uint256 gas,
    address indexed processor
);

constructor() public ERC20("Captain Shiba", "BirbZilla") {

    dividendTracker = new BirbZillaDividendTracker();

    IUniswapV2Router02 _uniswapV2Router = IUniswapV2Router02(0x10ED43C718714eb63d5aA57B78B54704E256024E);
     // Create a uniswap pair for this new token
    address _uniswapV2Pair = IUniswapV2Factory(_uniswapV2Router.factory())
        .createPair(address(this), _uniswapV2Router.WETH());

    uniswapV2Router = _uniswapV2Router;
    uniswapV2Pair = _uniswapV2Pair;

    _setAutomatedMarketMakerPair(_uniswapV2Pair, true);

    // exclude from receiving dividends
    dividendTracker.excludeFromDividends(address(dividendTracker));
    dividendTracker.excludeFromDividends(address(this));
    dividendTracker.excludeFromDividends(owner());
    dividendTracker.excludeFromDividends(deadWallet);
    dividendTracker.excludeFromDividends(address(_uniswapV2Router));

    // exclude from paying fees or having max transaction amount
    excludeFromFees(owner(), true);
    excludeFromFees(_marketingWalletAddress, true);
    excludeFromFees(address(this), true);

    /*【
        _mint is an internal function in ERC20.sol that is only called here,
        and CANNOT be called ever again
    */
    _mint(owner(), 1000000000000000 * (10**18));
}

receive() external payable {

}

function updateDividendTracker(address newAddress) public onlyOwner {
    require(newAddress != address(dividendTracker), "BirbZilla: The dividend tracker already has that address");

    BirbZillaDividendTracker newDividendTracker = BirbZillaDividendTracker(payable(newAddress));

    require(newDividendTracker.owner() == address(this), "BirbZilla: The new dividend tracker must be owned by the BirbZilla token contract");

    newDividendTracker.excludeFromDividends(address(newDividendTracker));
    newDividendTracker.excludeFromDividends(address(this));
    newDividendTracker.excludeFromDividends(owner());
    newDividendTracker.excludeFromDividends(address(uniswapV2Router));

    emit UpdateDividendTracker(newAddress, address(dividendTracker));

    dividendTracker = newDividendTracker;
}

function updateUniswapV2Router(address newAddress) public onlyOwner {
    require(newAddress != address(uniswapV2Router), "BirbZilla: The router already has that address");
    emit UpdateUniswapV2Router(newAddress, address(uniswapV2Router));
    uniswapV2Router = IUniswapV2Router02(newAddress);
    address _uniswapV2Pair = IUniswapV2Factory(uniswapV2Router.factory())
        .createPair(address(this), uniswapV2Router.WETH());
    uniswapV2Pair = _uniswapV2Pair;
}

function updateMaxWallet(uint256 maxWallet) public onlyOwner {
    _maxWalletToken = maxWallet * (10**18);
} 

function excludeFromFees(address account, bool excluded) public onlyOwner {
    require(_isExcludedFromFees[account] != excluded, "BirbZilla: Account is already the value of 'excluded'");
    _isExcludedFromFees[account] = excluded;

    emit ExcludeFromFees(account, excluded);
}

function excludeMultipleAccountsFromFees(address[] calldata accounts, bool excluded) public onlyOwner {
    for(uint256 i = 0; i &lt; accounts.length; i++) {
        _isExcludedFromFees[accounts[i]] = excluded;
    }

    emit ExcludeMultipleAccountsFromFees(accounts, excluded);
}

function setMarketingWallet(address payable wallet) external onlyOwner{
    _marketingWalletAddress = wallet;
}

function setBIRBRewardsFee(uint256 value) external onlyOwner{
    BIRBRewardsFee = value;
    totalFees = BIRBRewardsFee.add(liquidityFee).add(marketingFee);
}

function setLiquiditFee(uint256 value) external onlyOwner{
    liquidityFee = value;
    totalFees = BIRBRewardsFee.add(liquidityFee).add(marketingFee);
}

function setMarketingFee(uint256 value) external onlyOwner{
    marketingFee = value;
    totalFees = BIRBRewardsFee.add(liquidityFee).add(marketingFee);

}

function setAutomatedMarketMakerPair(address pair, bool value) public onlyOwner {
    require(pair != uniswapV2Pair, "BirbZilla: The PancakeSwap pair cannot be removed from automatedMarketMakerPairs");

    _setAutomatedMarketMakerPair(pair, value);
}

function blacklistAddress(address account, bool value) external onlyOwner{
    _isBlacklisted[account] = value;
}

function _setAutomatedMarketMakerPair(address pair, bool value) private {
    require(automatedMarketMakerPairs[pair] != value, "BirbZilla: Automated market maker pair is already set to that value");
    automatedMarketMakerPairs[pair] = value;

    if(value) {
        dividendTracker.excludeFromDividends(pair);
    }

    emit SetAutomatedMarketMakerPair(pair, value);
}

function updateGasForProcessing(uint256 newValue) public onlyOwner {
    require(newValue >= 200000 && newValue &lt;= 500000, "BirbZilla: gasForProcessing must be between 200,000 and 500,000");
    require(newValue != gasForProcessing, "BirbZilla: Cannot update gasForProcessing to same value");
    emit GasForProcessingUpdated(newValue, gasForProcessing);
    gasForProcessing = newValue;
}

function updateClaimWait(uint256 claimWait) external onlyOwner {
    dividendTracker.updateClaimWait(claimWait);
}

function getClaimWait() external view returns(uint256) {
    return dividendTracker.claimWait();
}

function getTotalDividendsDistributed() external view returns (uint256) {
    return dividendTracker.totalDividendsDistributed();
}

function isExcludedFromFees(address account) public view returns(bool) {
    return _isExcludedFromFees[account];
}

function withdrawableDividendOf(address account) public view returns(uint256) {
    return dividendTracker.withdrawableDividendOf(account);
}

function dividendTokenBalanceOf(address account) public view returns (uint256) {
    return dividendTracker.balanceOf(account);
}

function excludeFromDividends(address account) external onlyOwner{
    dividendTracker.excludeFromDividends(account);
}

function getAccountDividendsInfo(address account)
    external view returns (
        address,
        int256,
        int256,
        uint256,
        uint256,
        uint256,
        uint256,
        uint256) {
    return dividendTracker.getAccount(account);
}

function getAccountDividendsInfoAtIndex(uint256 index)
    external view returns (
        address,
        int256,
        int256,
        uint256,
        uint256,
        uint256,
        uint256,
        uint256) {
    return dividendTracker.getAccountAtIndex(index);
}

function processDividendTracker(uint256 gas) external {
    (uint256 iterations, uint256 claims, uint256 lastProcessedIndex) = dividendTracker.process(gas);
    emit ProcessedDividendTracker(iterations, claims, lastProcessedIndex, false, gas, tx.origin);
}

function claim() external {
    dividendTracker.processAccount(msg.sender, false);
}

function getLastProcessedIndex() external view returns(uint256) {
    return dividendTracker.getLastProcessedIndex();
}

function getNumberOfDividendTokenHolders() external view returns(uint256) {
    return dividendTracker.getNumberOfTokenHolders();
}

function _transfer(
    address from,
    address to,
    uint256 amount
) internal override {
    require(from != address(0), "ERC20: transfer from the zero address");
    require(to != address(0), "ERC20: transfer to the zero address");
    require(!_isBlacklisted[from] && !_isBlacklisted[to], 'Blacklisted address');

    if(amount == 0) {
        super._transfer(from, to, 0);
        return;
    }

    uint256 contractTokenBalance = balanceOf(address(this));

    bool canSwap = contractTokenBalance >= swapTokensAtAmount;

    if( canSwap &&
        !swapping &&
        !automatedMarketMakerPairs[from] &&
        from != owner() &&
        to != owner()
    ) {
        swapping = true;

        uint256 marketingTokens = contractTokenBalance.mul(marketingFee).div(totalFees);
        swapAndSendToFee(marketingTokens);

        uint256 swapTokens = contractTokenBalance.mul(liquidityFee).div(totalFees);
        swapAndLiquify(swapTokens);

        uint256 sellTokens = balanceOf(address(this));
        swapAndSendDividends(sellTokens);

        swapping = false;
    }

    bool takeFee = !swapping;

    // if any account belongs to _isExcludedFromFee account then remove the fee
    if(_isExcludedFromFees[from] || _isExcludedFromFees[to]) {
        takeFee = false;
    }

    if(takeFee) {
        uint256 fees = amount.mul(totalFees).div(100);
        if(automatedMarketMakerPairs[to]){
            fees += amount.mul(1).div(100);
        }
        amount = amount.sub(fees);

        super._transfer(from, address(this), fees);
    }

    super._transfer(from, to, amount);

    try dividendTracker.setBalance(payable(from), balanceOf(from)) {} catch {}
    try dividendTracker.setBalance(payable(to), balanceOf(to)) {} catch {}

    if(!swapping) {
        uint256 gas = gasForProcessing;

        try dividendTracker.process(gas) returns (uint256 iterations, uint256 claims, uint256 lastProcessedIndex) {
            emit ProcessedDividendTracker(iterations, claims, lastProcessedIndex, true, gas, tx.origin);
        }
        catch {

        }
    }
}

function swapAndSendToFee(uint256 tokens) private  {

    uint256 initialBIRBBalance = IERC20(BIRB).balanceOf(address(this));

    swapTokensForBIRB(tokens);
    uint256 newBalance = (IERC20(BIRB).balanceOf(address(this))).sub(initialBIRBBalance);
    IERC20(BIRB).transfer(_marketingWalletAddress, newBalance);
}

function swapAndLiquify(uint256 tokens) private {
   // split the contract balance into halves
    uint256 half = tokens.div(2);
    uint256 otherHalf = tokens.sub(half);

    // capture the contract's current ETH balance.
    // this is so that we can capture exactly the amount of ETH that the
    // swap creates, and not make the liquidity event include any ETH that
    // has been manually sent to the contract
    uint256 initialBalance = address(this).balance;

    // swap tokens for ETH
    swapTokensForEth(half); // &lt;- this breaks the ETH -> HATE swap when swap+liquify is triggered

    // how much ETH did we just swap into?
    uint256 newBalance = address(this).balance.sub(initialBalance);

    // add liquidity to uniswap
    addLiquidity(otherHalf, newBalance);

    emit SwapAndLiquify(half, newBalance, otherHalf);
}

function swapTokensForEth(uint256 tokenAmount) private {

    // generate the uniswap pair path of token -> weth
    address[] memory path = new address[](2);
    path[0] = address(this);
    path[1] = uniswapV2Router.WETH();

    _approve(address(this), address(uniswapV2Router), tokenAmount);

    // make the swap
    uniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens(
        tokenAmount,
        0, // accept any amount of ETH
        path,
        address(this),
        block.timestamp
    );

}

function swapTokensForBIRB(uint256 tokenAmount) private {

    address[] memory path = new address[](3);
    path[0] = address(this);
    path[1] = uniswapV2Router.WETH();
    path[2] = BIRB;

    _approve(address(this), address(uniswapV2Router), tokenAmount);

    // make the swap
    uniswapV2Router.swapExactTokensForTokensSupportingFeeOnTransferTokens(
        tokenAmount,
        0,
        path,
        address(this),
        block.timestamp
    );
}

function addLiquidity(uint256 tokenAmount, uint256 ethAmount) private {

    // approve token transfer to cover all possible scenarios
    _approve(address(this), address(uniswapV2Router), tokenAmount);

    // add the liquidity
    uniswapV2Router.addLiquidityETH{value: ethAmount}(
        address(this),
        tokenAmount,
        0, // slippage is unavoidable
        0, // slippage is unavoidable
        address(0),
        block.timestamp
    );

}

function swapAndSendDividends(uint256 tokens) private{
    swapTokensForBIRB(tokens);
    uint256 dividends = IERC20(BIRB).balanceOf(address(this));
    bool success = IERC20(BIRB).transfer(address(dividendTracker), dividends);

    if (success) {
        dividendTracker.distributeBIRBDividends(dividends);
        emit SendDividends(tokens, dividends);
    }
}

}

contract BirbZillaDividendTracker is Ownable, DividendPayingToken { using SafeMath for uint256; using SafeMathInt for int256; using IterableMapping for IterableMapping.Map;

IterableMapping.Map private tokenHoldersMap;
uint256 public lastProcessedIndex;

mapping (address => bool) public excludedFromDividends;

mapping (address => uint256) public lastClaimTimes;

uint256 public claimWait;
uint256 public immutable minimumTokenBalanceForDividends;
uint256 public _maxWalletToken = 10000000000000 * (10**18); // 1.0% of total supply

event ExcludeFromDividends(address indexed account);
event ClaimWaitUpdated(uint256 indexed newValue, uint256 indexed oldValue);

event Claim(address indexed account, uint256 amount, bool indexed automatic);

constructor() public DividendPayingToken("BirbZilla_Dividen_Tracker", "BirbZilla_Dividend_Tracker") {
    claimWait = 1200;
    minimumTokenBalanceForDividends = 200000 * (10**18); //must hold 200000+ tokens
}

function _transfer(address, address, uint256) internal override {
    require(false, "BirbZilla_Dividend_Tracker: No transfers allowed");
}

function withdrawDividend() public override {
    require(false, "BirbZilla_Dividend_Tracker: withdrawDividend disabled. Use the 'claim' function on the main BirbZilla contract.");
}

function excludeFromDividends(address account) external onlyOwner {
    require(!excludedFromDividends[account]);
    excludedFromDividends[account] = true;

    _setBalance(account, 0);
    tokenHoldersMap.remove(account);

    emit ExcludeFromDividends(account);
}

function updateClaimWait(uint256 newClaimWait) external onlyOwner {
    require(newClaimWait >= 1200 && newClaimWait &lt;= 86400, "BirbZilla_Dividend_Tracker: claimWait must be updated to between 1 and 24 hours");
    require(newClaimWait != claimWait, "BirbZilla_Dividend_Tracker: Cannot update claimWait to same value");
    emit ClaimWaitUpdated(newClaimWait, claimWait);
    claimWait = newClaimWait;
}

function getLastProcessedIndex() external view returns(uint256) {
    return lastProcessedIndex;
}

function getNumberOfTokenHolders() external view returns(uint256) {
    return tokenHoldersMap.keys.length;
}

function getAccount(address _account)
    public view returns (
        address account,
        int256 index,
        int256 iterationsUntilProcessed,
        uint256 withdrawableDividends,
        uint256 totalDividends,
        uint256 lastClaimTime,
        uint256 nextClaimTime,
        uint256 secondsUntilAutoClaimAvailable) {
    account = _account;

    index = tokenHoldersMap.getIndexOfKey(account);

    iterationsUntilProcessed = -1;

    if(index >= 0) {
        if(uint256(index) > lastProcessedIndex) {
            iterationsUntilProcessed = index.sub(int256(lastProcessedIndex));
        }
        else {
            uint256 processesUntilEndOfArray = tokenHoldersMap.keys.length > lastProcessedIndex ?
                                                    tokenHoldersMap.keys.length.sub(lastProcessedIndex) :
                                                    0;

            iterationsUntilProcessed = index.add(int256(processesUntilEndOfArray));
        }
    }

    withdrawableDividends = withdrawableDividendOf(account);
    totalDividends = accumulativeDividendOf(account);

    lastClaimTime = lastClaimTimes[account];

    nextClaimTime = lastClaimTime > 0 ?
                                lastClaimTime.add(claimWait) :
                                0;

    secondsUntilAutoClaimAvailable = nextClaimTime > block.timestamp ?
                                                nextClaimTime.sub(block.timestamp) :
                                                0;
}

function getAccountAtIndex(uint256 index)
    public view returns (
        address,
        int256,
        int256,
        uint256,
        uint256,
        uint256,
        uint256,
        uint256) {
    if(index >= tokenHoldersMap.size()) {
        return (0x0000000000000000000000000000000000000000, -1, -1, 0, 0, 0, 0, 0);
    }

    address account = tokenHoldersMap.getKeyAtIndex(index);

    return getAccount(account);
}

function canAutoClaim(uint256 lastClaimTime) private view returns (bool) {
    if(lastClaimTime > block.timestamp)  {
        return false;
    }

    return block.timestamp.sub(lastClaimTime) >= claimWait;
}

function setBalance(address payable account, uint256 newBalance) external onlyOwner {
    if(excludedFromDividends[account]) {
        return;
    }

    if(newBalance >= minimumTokenBalanceForDividends) {
        _setBalance(account, newBalance);
        tokenHoldersMap.set(account, newBalance);
    }
    else {
        _setBalance(account, 0);
        tokenHoldersMap.remove(account);
    }

    processAccount(account, true);
}

function process(uint256 gas) public returns (uint256, uint256, uint256) {
    uint256 numberOfTokenHolders = tokenHoldersMap.keys.length;

    if(numberOfTokenHolders == 0) {
        return (0, 0, lastProcessedIndex);
    }

    uint256 _lastProcessedIndex = lastProcessedIndex;

    uint256 gasUsed = 0;

    uint256 gasLeft = gasleft();

    uint256 iterations = 0;
    uint256 claims = 0;

    while(gasUsed &lt; gas && iterations &lt; numberOfTokenHolders) {
        _lastProcessedIndex++;

        if(_lastProcessedIndex >= tokenHoldersMap.keys.length) {
            _lastProcessedIndex = 0;
        }

        address account = tokenHoldersMap.keys[_lastProcessedIndex];

        if(canAutoClaim(lastClaimTimes[account])) {
            if(processAccount(payable(account), true)) {
                claims++;
            }
        }

        iterations++;

        uint256 newGasLeft = gasleft();

        if(gasLeft > newGasLeft) {
            gasUsed = gasUsed.add(gasLeft.sub(newGasLeft));
        }

        gasLeft = newGasLeft;
    }

    lastProcessedIndex = _lastProcessedIndex;

    return (iterations, claims, lastProcessedIndex);
}

function processAccount(address payable account, bool automatic) public onlyOwner returns (bool) {
    uint256 amount = _withdrawDividendOfUser(account);

    if(amount > 0) {
        lastClaimTimes[account] = block.timestamp;
        emit Claim(account, amount, automatic);
        return true;
    }

    return false;
}

}

请先 登录 后评论

2 个回答

Tiny熊 - 布道者
  擅长:智能合约,以太坊
请先 登录 后评论
pan
请先 登录 后评论