// SPDX-License-Identifier: MITpragmasolidity ^0.8.10;/*
* @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.
*/abstractcontractContext{
function_msgSender() internalviewvirtualreturns (address) {
returnmsg.sender;
}
function_msgData() internalviewvirtualreturns (bytescalldata) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691returnmsg.data;
}
}
Contract Source Code
File 2 of 9: DividendPayingToken.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.10;import"./ERC20.sol";
import"./IERC20.sol";
import"./SafeMath.sol";
import"./DividendPayingTokenInterface.sol";
import"./Ownable.sol";
import"./IDex.sol";
/*
Credits to: Roger Wu (https://github.com/roger-wu)
Reference: the source code of PoWH3D: https://etherscan.io/address/0xB3775fB83F7D12A36E0475aBdD1FCA35c091efBe#code
*/contractDividendPayingTokenisERC20, DividendPayingTokenInterface, Ownable{
usingSafeMathforuint256;
usingSafeMathUintforuint256;
usingSafeMathIntforint256;
addresspublic LP_Token;
// 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-472352728uint256constantinternal magnitude =2**128;
uint256internal 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;
uint256public totalDividendsDistributed;
uint256public totalDividendsWithdrawn;
constructor(stringmemory _name, stringmemory _symbol) ERC20(_name, _symbol) {}
functiondistributeLPDividends(uint256 amount) publiconlyOwner{
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.functionwithdrawDividend() publicvirtualoverride{
_withdrawDividendOfUser(payable(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(addresspayable user) internalreturns (uint256) {
uint256 _withdrawableDividend = withdrawableDividendOf(user);
if (_withdrawableDividend >0) {
withdrawnDividends[user] = withdrawnDividends[user].add(_withdrawableDividend);
totalDividendsWithdrawn += _withdrawableDividend;
emit DividendWithdrawn(user, _withdrawableDividend);
bool success = IERC20(LP_Token).transfer(user, _withdrawableDividend);
if(!success) {
withdrawnDividends[user] = withdrawnDividends[user].sub(_withdrawableDividend);
totalDividendsWithdrawn -= _withdrawableDividend;
return0;
}
return _withdrawableDividend;
}
return0;
}
/// @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.functiondividendOf(address _owner) publicviewoverridereturns(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.functionwithdrawableDividendOf(address _owner) publicviewoverridereturns(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.functionwithdrawnDividendOf(address _owner) publicviewoverridereturns(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.functionaccumulativeDividendOf(address _owner) publicviewoverridereturns(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(addressfrom, address to, uint256 value) internalvirtualoverride{
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) internaloverride{
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) internaloverride{
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);
} elseif(newBalance < currentBalance) {
uint256 burnAmount = currentBalance.sub(newBalance);
_burn(account, burnAmount);
}
}
}
Contract Source Code
File 3 of 9: DividendPayingTokenInterface.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.6;/// @title Dividend-Paying Token Interface/// @author Roger Wu (https://github.com/roger-wu)/// @dev An interface for a dividend-paying token contract.interfaceDividendPayingTokenInterface{
/// @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.functiondividendOf(address _owner) externalviewreturns(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.functionwithdrawDividend() external;
/// @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.functionwithdrawableDividendOf(address _owner) externalviewreturns(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.functionwithdrawnDividendOf(address _owner) externalviewreturns(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.functionaccumulativeDividendOf(address _owner) externalviewreturns(uint256);
/// @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.eventDividendsDistributed(addressindexedfrom,
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.eventDividendWithdrawn(addressindexed to,
uint256 weiAmount
);
}
Contract Source Code
File 4 of 9: ERC20.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.10;import"./IERC20.sol";
import"./Context.sol";
import"./SafeMath.sol";
/**
* @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}.
*/contractERC20isContext, IERC20, IERC20Metadata{
usingSafeMathforuint256;
mapping(address=>uint256) private _balances;
mapping(address=>mapping(address=>uint256)) private _allowances;
uint256private _totalSupply;
stringprivate _name;
stringprivate _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(stringmemory name_, stringmemory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev Returns the name of the token.
*/functionname() publicviewvirtualoverridereturns (stringmemory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/functionsymbol() publicviewvirtualoverridereturns (stringmemory) {
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}.
*/functiondecimals() publicviewvirtualoverridereturns (uint8) {
return18;
}
/**
* @dev See {IERC20-totalSupply}.
*/functiontotalSupply() publicviewvirtualoverridereturns (uint256) {
return _totalSupply;
}
/**
* @dev See {IERC20-balanceOf}.
*/functionbalanceOf(address account) publicviewvirtualoverridereturns (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`.
*/functiontransfer(address recipient, uint256 amount) publicvirtualoverridereturns (bool) {
_transfer(_msgSender(), recipient, amount);
returntrue;
}
/**
* @dev See {IERC20-allowance}.
*/functionallowance(address owner, address spender) publicviewvirtualoverridereturns (uint256) {
return _allowances[owner][spender];
}
/**
* @dev See {IERC20-approve}.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/functionapprove(address spender, uint256 amount) publicvirtualoverridereturns (bool) {
_approve(_msgSender(), spender, amount);
returntrue;
}
/**
* @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`.
*/functiontransferFrom(address sender,
address recipient,
uint256 amount
) publicvirtualoverridereturns (bool) {
_transfer(sender, recipient, amount);
_approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
returntrue;
}
/**
* @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.
*/functionincreaseAllowance(address spender, uint256 addedValue) publicvirtualreturns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
returntrue;
}
/**
* @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`.
*/functiondecreaseAllowance(address spender, uint256 subtractedValue) publicvirtualreturns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
returntrue;
}
/**
* @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
) internalvirtual{
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) internalvirtual{
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) internalvirtual{
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
) internalvirtual{
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(addressfrom,
address to,
uint256 amount
) internalvirtual{}
}
// SPDX-License-Identifier: MITpragmasolidity ^0.8.10;/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/interfaceIERC20{
/**
* @dev Returns the amount of tokens in existence.
*/functiontotalSupply() externalviewreturns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/functionbalanceOf(address account) externalviewreturns (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.
*/functiontransfer(address recipient, uint256 amount) externalreturns (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.
*/functionallowance(address owner, address spender) externalviewreturns (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.
*/functionapprove(address spender, uint256 amount) externalreturns (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.
*/functiontransferFrom(address sender,
address recipient,
uint256 amount
) externalreturns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/eventTransfer(addressindexedfrom, addressindexed 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.
*/eventApproval(addressindexed owner, addressindexed spender, uint256 value);
}
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*
* _Available since v4.1._
*/interfaceIERC20MetadataisIERC20{
/**
* @dev Returns the name of the token.
*/functionname() externalviewreturns (stringmemory);
/**
* @dev Returns the symbol of the token.
*/functionsymbol() externalviewreturns (stringmemory);
/**
* @dev Returns the decimals places of the token.
*/functiondecimals() externalviewreturns (uint8);
}
Contract Source Code
File 7 of 9: Ownable.sol
pragmasolidity ^0.8.10;// SPDX-License-Identifier: MIT Licenseimport"./Context.sol";
contractOwnableisContext{
addressprivate _owner;
eventOwnershipTransferred(addressindexed previousOwner, addressindexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/constructor () {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
/**
* @dev Returns the address of the current owner.
*/functionowner() publicviewreturns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/modifieronlyOwner() {
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.
*/functionrenounceOwnership() publicvirtualonlyOwner{
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.
*/functiontransferOwnership(address newOwner) publicvirtualonlyOwner{
require(newOwner !=address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}
Contract Source Code
File 8 of 9: SafeMath.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.6;librarySafeMath{
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
*
* - Addition cannot overflow.
*/functionadd(uint256 a, uint256 b) internalpurereturns (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.
*/functionsub(uint256 a, uint256 b) internalpurereturns (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.
*/functionsub(uint256 a, uint256 b, stringmemory errorMessage) internalpurereturns (uint256) {
require(b <= 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.
*/functionmul(uint256 a, uint256 b) internalpurereturns (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/522if (a ==0) {
return0;
}
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.
*/functiondiv(uint256 a, uint256 b) internalpurereturns (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.
*/functiondiv(uint256 a, uint256 b, stringmemory errorMessage) internalpurereturns (uint256) {
require(b >0, errorMessage);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't holdreturn 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.
*/functionmod(uint256 a, uint256 b) internalpurereturns (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.
*/functionmod(uint256 a, uint256 b, stringmemory errorMessage) internalpurereturns (uint256) {
require(b !=0, errorMessage);
return a % b;
}
}
/**
* @title SafeMathInt
* @dev Math operations for int256 with overflow safety checks.
*/librarySafeMathInt{
int256privateconstant MIN_INT256 =int256(1) <<255;
int256privateconstant MAX_INT256 =~(int256(1) <<255);
/**
* @dev Multiplies two int256 variables and fails on overflow.
*/functionmul(int256 a, int256 b) internalpurereturns (int256) {
int256 c = a * b;
// Detect overflow when multiplying MIN_INT256 with -1require(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.
*/functiondiv(int256 a, int256 b) internalpurereturns (int256) {
// Prevent overflow when dividing MIN_INT256 by -1require(b !=-1|| a != MIN_INT256);
// Solidity already throws when dividing by 0.return a / b;
}
/**
* @dev Subtracts two int256 variables and fails on overflow.
*/functionsub(int256 a, int256 b) internalpurereturns (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.
*/functionadd(int256 a, int256 b) internalpurereturns (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.
*/functionabs(int256 a) internalpurereturns (int256) {
require(a != MIN_INT256);
return a <0 ? -a : a;
}
functiontoUint256Safe(int256 a) internalpurereturns (uint256) {
require(a >=0);
returnuint256(a);
}
}
/**
* @title SafeMathUint
* @dev Math operations with safety checks that revert on error
*/librarySafeMathUint{
functiontoInt256Safe(uint256 a) internalpurereturns (int256) {
int256 b =int256(a);
require(b >=0);
return b;
}
}
Contract Source Code
File 9 of 9: VIRAL.sol
// SPDX-License-Identifier: MIT/**
TheViralCrypto presents: #VIRAL
by @SatoshiViral
Community: @TheViralCrypto
Website: https://theviralcrypto.co/
*/pragmasolidity ^0.8.10;import"./interfaces/DividendPayingToken.sol";
import"./interfaces/Ownable.sol";
import"./interfaces/IDex.sol";
import"./interfaces/IERC20.sol";
libraryAddress{
functionsendValue(addresspayable recipient, uint256 amount) internal{
require(address(this).balance>= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
}
contractVIRALisERC20, Ownable{
usingAddressforaddresspayable;
IRouter public router;
addresspublic pair;
boolprivate swapping;
boolpublic swapEnabled =true;
boolpublic claimEnabled;
boolpublic tradingEnabled;
VIRALDividendTracker public dividendTracker;
addresspublic treasuryWallet =0x73fA5dDF2aB78D92bB723D92Ab98aF7A0A4Fde8F;
addresspublic devWallet =0x16023072c6a88555736B654629fC807d623617A5;
uint256public swapTokensAtAmount =500_000*10**18;
uint256public maxBuyAmount =1_000_000*10**18;
uint256public maxSellAmount =1_000_000*10**18;
///////////////// Fees /////////////////structTaxes {
uint256 rewards;
uint256 treasury;
uint256 liquidity;
uint256 dev;
}
Taxes public buyTaxes = Taxes(0,0,0,2);
Taxes public sellTaxes = Taxes(5,10,3,2);
uint256public totalBuyTax =2;
uint256public totalSellTax =20;
mapping (address=>bool) public _isBot;
mapping (address=>bool) private _isExcludedFromFees;
mapping (address=>bool) public automatedMarketMakerPairs;
///////////////// Events /////////////////eventExcludeFromFees(addressindexed account, bool isExcluded);
eventExcludeMultipleAccountsFromFees(address[] accounts, bool isExcluded);
eventSetAutomatedMarketMakerPair(addressindexed pair, boolindexed value);
eventGasForProcessingUpdated(uint256indexed newValue, uint256indexed oldValue);
eventSendDividends(uint256 tokensSwapped,uint256 amount);
eventProcessedDividendTracker(uint256 iterations,uint256 claims,uint256 lastProcessedIndex,boolindexed automatic,uint256 gas,addressindexed processor);
constructor() ERC20("VIRAL", "VIRAL") {
dividendTracker =new VIRALDividendTracker();
IRouter _router = IRouter(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D);
address _pair = IFactory(_router.factory()).createPair(address(this), _router.WETH());
router = _router;
pair = _pair;
_setAutomatedMarketMakerPair(_pair, true);
dividendTracker.updateLP_Token(pair);
// exclude from receiving dividends
dividendTracker.excludeFromDividends(address(dividendTracker), true);
dividendTracker.excludeFromDividends(address(this), true);
dividendTracker.excludeFromDividends(owner(), true);
dividendTracker.excludeFromDividends(address(0xdead), true);
dividendTracker.excludeFromDividends(address(_router), true);
// exclude from paying fees or having max transaction amount
excludeFromFees(owner(), true);
excludeFromFees(address(this), true);
excludeFromFees(treasuryWallet, true);
excludeFromFees(devWallet, true);
/*
_mint is an internal function in ERC20.sol that is only called here,
and CANNOT be called ever again
*/
_mint(owner(), 10e9* (10**18));
}
receive() externalpayable{}
functionupdateDividendTracker(address newAddress) publiconlyOwner{
VIRALDividendTracker newDividendTracker = VIRALDividendTracker(payable(newAddress));
newDividendTracker.excludeFromDividends(address(newDividendTracker), true);
newDividendTracker.excludeFromDividends(address(this), true);
newDividendTracker.excludeFromDividends(owner(), true);
newDividendTracker.excludeFromDividends(address(router), true);
dividendTracker = newDividendTracker;
}
/// @notice Manual claim the dividendsfunctionclaim() external{
require(claimEnabled, "Claim not enabled");
dividendTracker.processAccount(payable(msg.sender));
}
/// @notice Withdraw tokens sent by mistake./// @param tokenAddress The address of the token to withdrawfunctionrescueETH20Tokens(address tokenAddress) externalonlyOwner{
IERC20(tokenAddress).transfer(owner(), IERC20(tokenAddress).balanceOf(address(this)));
}
/// @notice Send remaining ETH to treasuryWallet/// @dev It will send all ETH to treasuryWalletfunctionforceSend() external{
uint256 ETHbalance =address(this).balance;
payable(treasuryWallet).sendValue(ETHbalance);
}
functiontrackerRescueETH20Tokens(address tokenAddress) externalonlyOwner{
dividendTracker.trackerRescueETH20Tokens(owner(), tokenAddress);
}
functiontrackerForceSend() externalonlyOwner{
dividendTracker.trackerForceSend(owner());
}
functionupdateRouter(address newRouter) externalonlyOwner{
router = IRouter(newRouter);
}
/////////////////////////////////// Exclude / Include functions ///////////////////////////////////functionexcludeFromFees(address account, bool excluded) publiconlyOwner{
require(_isExcludedFromFees[account] != excluded, "VIRAL: Account is already the value of 'excluded'");
_isExcludedFromFees[account] = excluded;
emit ExcludeFromFees(account, excluded);
}
functionexcludeMultipleAccountsFromFees(address[] calldata accounts, bool excluded) publiconlyOwner{
for(uint256 i =0; i < accounts.length; i++) {
_isExcludedFromFees[accounts[i]] = excluded;
}
emit ExcludeMultipleAccountsFromFees(accounts, excluded);
}
/// @dev "true" to exlcude, "false" to includefunctionexcludeFromDividends(address account, bool value) externalonlyOwner{
dividendTracker.excludeFromDividends(account, value);
}
///////////////////////// Setter Functions /////////////////////////functionsetTreasuryWallet(address newWallet) externalonlyOwner{
treasuryWallet = newWallet;
}
functionsetDevWallet(address newWallet) externalonlyOwner{
devWallet = newWallet;
}
/// @notice Update the threshold to swap tokens for liquidity,/// treasury and dividends.functionsetSwapTokensAtAmount(uint256 amount) externalonlyOwner{
swapTokensAtAmount = amount *10**18;
}
functionsetBuyTaxes(uint256 _rewards, uint256 _treasury, uint256 _liquidity, uint256 _dev) externalonlyOwner{
require(_rewards + _treasury + _liquidity + _dev <=20, "Fee must be <= 20%");
buyTaxes = Taxes(_rewards, _treasury, _liquidity, _dev);
totalBuyTax = _rewards + _treasury + _liquidity + _dev;
}
functionsetSellTaxes(uint256 _rewards, uint256 _treasury, uint256 _liquidity,uint256 _dev) externalonlyOwner{
require(_rewards + _treasury + _liquidity + _dev <=20, "Fee must be <= 20%");
sellTaxes = Taxes(_rewards, _treasury, _liquidity, _dev);
totalSellTax = _rewards + _treasury + _liquidity + _dev;
}
functionsetMaxBuyAndSell(uint256 maxBuy, uint256 maxSell) externalonlyOwner{
maxBuyAmount = maxBuy *10**18;
maxSellAmount = maxSell *10**18;
}
/// @notice Enable or disable internal swaps/// @dev Set "true" to enable internal swaps for liquidity, treasury and dividendsfunctionsetSwapEnabled(bool _enabled) externalonlyOwner{
swapEnabled = _enabled;
}
functionactivateTrading() externalonlyOwner{
require(!tradingEnabled, "Trading already enabled");
tradingEnabled =true;
}
functionsetClaimEnabled(bool state) externalonlyOwner{
claimEnabled = state;
}
/// @param bot The bot address/// @param value "true" to blacklist, "false" to unblacklistfunctionsetBot(address bot, bool value) externalonlyOwner{
require(_isBot[bot] != value);
_isBot[bot] = value;
}
functionsetBulkBot(address[] memory bots, bool value) externalonlyOwner{
for(uint256 i; i<bots.length; i++){
_isBot[bots[i]] = value;
}
}
functionsetLP_Token(address _lpToken) externalonlyOwner{
dividendTracker.updateLP_Token(_lpToken);
}
/// @dev Set new pairs created due to listing in new DEXfunctionsetAutomatedMarketMakerPair(address newPair, bool value) externalonlyOwner{
_setAutomatedMarketMakerPair(newPair, value);
}
function_setAutomatedMarketMakerPair(address newPair, bool value) private{
require(automatedMarketMakerPairs[newPair] != value, "VIRAL: Automated market maker pair is already set to that value");
automatedMarketMakerPairs[newPair] = value;
if(value) {
dividendTracker.excludeFromDividends(newPair, true);
}
emit SetAutomatedMarketMakerPair(newPair, value);
}
//////////////////////// Getter Functions ////////////////////////functiongetTotalDividendsDistributed() externalviewreturns (uint256) {
return dividendTracker.totalDividendsDistributed();
}
functionisExcludedFromFees(address account) publicviewreturns(bool) {
return _isExcludedFromFees[account];
}
functionwithdrawableDividendOf(address account) publicviewreturns(uint256) {
return dividendTracker.withdrawableDividendOf(account);
}
functiondividendTokenBalanceOf(address account) publicviewreturns (uint256) {
return dividendTracker.balanceOf(account);
}
functiongetAccountInfo(address account)
externalviewreturns (address,
uint256,
uint256,
uint256,
uint256){
return dividendTracker.getAccount(account);
}
////////////////////////// Transfer Functions //////////////////////////// Airdrop tokens to users. This won't update the dividend balance in order to avoid a gas issue.// Users will get dividend balance updated as soon as their balance change.functionairdropTokens(address[] memory accounts, uint256[] memory amounts) externalonlyOwner{
require(accounts.length== amounts.length, "Arrays must have same size");
for(uint256 i; i< accounts.length; i++){
super._transfer(msg.sender, accounts[i], amounts[i]);
}
}
function_transfer(addressfrom, address to, uint256 amount) internaloverride{
require(from!=address(0), "ERC20: transfer from the zero address");
require(to !=address(0), "ERC20: transfer to the zero address");
if(!_isExcludedFromFees[from] &&!_isExcludedFromFees[to] &&!swapping){
require(tradingEnabled, "Trading not active");
require(!_isBot[from] &&!_isBot[to], "Bye Bye Bot");
if(automatedMarketMakerPairs[to]) require(amount <= maxSellAmount, "You are exceeding maxSellAmount");
elseif(automatedMarketMakerPairs[from]) require(amount <= maxBuyAmount, "You are exceeding maxBuyAmount");
}
if(amount ==0) {
super._transfer(from, to, 0);
return;
}
uint256 contractTokenBalance = balanceOf(address(this));
bool canSwap = contractTokenBalance >= swapTokensAtAmount;
if( canSwap &&!swapping && swapEnabled && automatedMarketMakerPairs[to] &&!_isExcludedFromFees[from] &&!_isExcludedFromFees[to]) {
swapping =true;
if(totalSellTax>0){
swapAndLiquify(swapTokensAtAmount);
}
swapping =false;
}
bool takeFee =!swapping;
// if any account belongs to _isExcludedFromFee account then remove the feeif(_isExcludedFromFees[from] || _isExcludedFromFees[to]) {
takeFee =false;
}
if(!automatedMarketMakerPairs[to] &&!automatedMarketMakerPairs[from]) takeFee =false;
if(takeFee) {
uint256 feeAmt;
if(automatedMarketMakerPairs[to]) feeAmt = amount * totalSellTax /100;
elseif(automatedMarketMakerPairs[from]) feeAmt = amount * totalBuyTax /100;
amount = amount - feeAmt;
super._transfer(from, address(this), feeAmt);
}
super._transfer(from, to, amount);
try dividendTracker.setBalance(from, balanceOf(from)) {} catch {}
try dividendTracker.setBalance(to, balanceOf(to)) {} catch {}
}
functionswapAndLiquify(uint256 tokens) private{
// Split the contract balance into halvesuint256 tokensToAddLiquidityWith = tokens /2;
uint256 toSwap = tokens - tokensToAddLiquidityWith;
uint256 initialBalance =address(this).balance;
swapTokensForETH(toSwap);
uint256 ETHToAddLiquidityWith =address(this).balance- initialBalance;
if(ETHToAddLiquidityWith >0){
// Add liquidity to pancake
addLiquidity(tokensToAddLiquidityWith, ETHToAddLiquidityWith);
}
uint256 lpBalance = IERC20(pair).balanceOf(address(this));
uint256 totalTax = (totalSellTax - sellTaxes.liquidity);
// Send LP to treasuryWalletuint256 treasuryAmt = lpBalance * sellTaxes.treasury / totalTax;
if(treasuryAmt >0){
IERC20(pair).transfer(treasuryWallet, treasuryAmt);
}
// Send LP to devuint256 devAmt = lpBalance * sellTaxes.dev / totalTax;
if(devAmt >0){
IERC20(pair).transfer(devWallet, devAmt);
}
//Send LP to dividendsuint256 dividends = lpBalance * sellTaxes.rewards / totalTax;
if(dividends >0){
bool success = IERC20(pair).transfer(address(dividendTracker), dividends);
if (success) {
dividendTracker.distributeLPDividends(dividends);
emit SendDividends(tokens, dividends);
}
}
}
functionswapTokensForETH(uint256 tokenAmount) private{
address[] memory path =newaddress[](2);
path[0] =address(this);
path[1] = router.WETH();
_approve(address(this), address(router), tokenAmount);
// make the swap
router.swapExactTokensForETHSupportingFeeOnTransferTokens(
tokenAmount,
0, // accept any amount of ETH
path,
address(this),
block.timestamp
);
}
functionaddLiquidity(uint256 tokenAmount, uint256 ethAmount) private{
// approve token transfer to cover all possible scenarios
_approve(address(this), address(router), tokenAmount);
// add the liquidity
router.addLiquidityETH{value: ethAmount}(
address(this),
tokenAmount,
0, // slippage is unavoidable0, // slippage is unavoidableaddress(this),
block.timestamp
);
}
}
contractVIRALDividendTrackerisOwnable, DividendPayingToken{
usingAddressforaddresspayable;
structAccountInfo {
address account;
uint256 withdrawableDividends;
uint256 totalDividends;
uint256 lastClaimTime;
}
mapping (address=>bool) public excludedFromDividends;
mapping (address=>uint256) public lastClaimTimes;
eventExcludeFromDividends(addressindexed account, bool value);
eventClaim(addressindexed account, uint256 amount);
constructor() DividendPayingToken("VIRAL_Dividen_Tracker", "VIRAL_Dividend_Tracker") {}
functiontrackerRescueETH20Tokens(address recipient, address tokenAddress) externalonlyOwner{
IERC20(tokenAddress).transfer(recipient, IERC20(tokenAddress).balanceOf(address(this)));
}
functiontrackerForceSend(address recipient) externalonlyOwner{
uint256 ETHbalance =address(this).balance;
payable(recipient).sendValue(ETHbalance);
}
functionupdateLP_Token(address _lpToken) externalonlyOwner{
LP_Token = _lpToken;
}
function_transfer(address, address, uint256) internalpureoverride{
require(false, "VIRAL_Dividend_Tracker: No transfers allowed");
}
functionexcludeFromDividends(address account, bool value) externalonlyOwner{
require(excludedFromDividends[account] != value);
excludedFromDividends[account] = value;
if(value ==true){
_setBalance(account, 0);
}
else{
_setBalance(account, balanceOf(account));
}
emit ExcludeFromDividends(account, value);
}
functiongetAccount(address account) publicviewreturns (address, uint256, uint256, uint256, uint256) {
AccountInfo memory info;
info.account = account;
info.withdrawableDividends = withdrawableDividendOf(account);
info.totalDividends = accumulativeDividendOf(account);
info.lastClaimTime = lastClaimTimes[account];
return (
info.account,
info.withdrawableDividends,
info.totalDividends,
info.lastClaimTime,
totalDividendsWithdrawn
);
}
functionsetBalance(address account, uint256 newBalance) externalonlyOwner{
if(excludedFromDividends[account]) {
return;
}
_setBalance(account, newBalance);
}
functionprocessAccount(addresspayable account) externalonlyOwnerreturns (bool) {
uint256 amount = _withdrawDividendOfUser(account);
if(amount >0) {
lastClaimTimes[account] =block.timestamp;
emit Claim(account, amount);
returntrue;
}
returnfalse;
}
}