Created
July 9, 2021 13:29
-
-
Save sharp2448/8b0f445c78c8d7489230f553af10abc4 to your computer and use it in GitHub Desktop.
Created using remix-ide: Realtime Ethereum Contract Compiler and Runtime. Load this file by pasting this gists URL or ID at https://remix.ethereum.org/#version=soljson-v0.8.6+commit.11564f7e.js&optimize=false&runs=200&gist=
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // SPDX-License-Identifier: MIT | |
| pragma solidity ^0.8.0; | |
| import "./IERC20.sol"; | |
| import "./extensions/IERC20Metadata.sol"; | |
| import "../../utils/Context.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}. | |
| */ | |
| contract ERC20 is Context, IERC20, IERC20Metadata { | |
| 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_) { | |
| _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); | |
| uint256 currentAllowance = _allowances[sender][_msgSender()]; | |
| require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); | |
| unchecked { | |
| _approve(sender, _msgSender(), currentAllowance - amount); | |
| } | |
| 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] + 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) { | |
| uint256 currentAllowance = _allowances[_msgSender()][spender]; | |
| require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); | |
| unchecked { | |
| _approve(_msgSender(), spender, currentAllowance - subtractedValue); | |
| } | |
| 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); | |
| uint256 senderBalance = _balances[sender]; | |
| require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); | |
| unchecked { | |
| _balances[sender] = senderBalance - amount; | |
| } | |
| _balances[recipient] += 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 += amount; | |
| _balances[account] += 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); | |
| uint256 accountBalance = _balances[account]; | |
| require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); | |
| unchecked { | |
| _balances[account] = accountBalance - amount; | |
| } | |
| _totalSupply -= 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 {} | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // SPDX-License-Identifier: MIT | |
| pragma solidity ^0.8.0; | |
| import "../IERC20.sol"; | |
| /** | |
| * @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); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // SPDX-License-Identifier: MIT | |
| pragma solidity ^0.8.0; | |
| /** | |
| * @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); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // SPDX-License-Identifier: MIT | |
| pragma solidity ^0.8.0; | |
| /* | |
| * @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; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // SPDX-License-Identifier: MIT | |
| pragma solidity ^0.8.0; | |
| // CAUTION | |
| // This version of SafeMath should only be used with Solidity 0.8 or later, | |
| // because it relies on the compiler's built in overflow checks. | |
| /** | |
| * @dev Wrappers over Solidity's arithmetic operations. | |
| * | |
| * NOTE: `SafeMath` is no longer needed starting with Solidity 0.8. The compiler | |
| * now has built in overflow checking. | |
| */ | |
| library SafeMath { | |
| /** | |
| * @dev Returns the addition of two unsigned integers, with an overflow flag. | |
| * | |
| * _Available since v3.4._ | |
| */ | |
| function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { | |
| unchecked { | |
| uint256 c = a + b; | |
| if (c < a) return (false, 0); | |
| return (true, c); | |
| } | |
| } | |
| /** | |
| * @dev Returns the substraction of two unsigned integers, with an overflow flag. | |
| * | |
| * _Available since v3.4._ | |
| */ | |
| function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { | |
| unchecked { | |
| if (b > a) return (false, 0); | |
| return (true, a - b); | |
| } | |
| } | |
| /** | |
| * @dev Returns the multiplication of two unsigned integers, with an overflow flag. | |
| * | |
| * _Available since v3.4._ | |
| */ | |
| function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { | |
| unchecked { | |
| // 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 (true, 0); | |
| uint256 c = a * b; | |
| if (c / a != b) return (false, 0); | |
| return (true, c); | |
| } | |
| } | |
| /** | |
| * @dev Returns the division of two unsigned integers, with a division by zero flag. | |
| * | |
| * _Available since v3.4._ | |
| */ | |
| function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { | |
| unchecked { | |
| if (b == 0) return (false, 0); | |
| return (true, a / b); | |
| } | |
| } | |
| /** | |
| * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. | |
| * | |
| * _Available since v3.4._ | |
| */ | |
| function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { | |
| unchecked { | |
| if (b == 0) return (false, 0); | |
| return (true, a % b); | |
| } | |
| } | |
| /** | |
| * @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) { | |
| return a + b; | |
| } | |
| /** | |
| * @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 a - b; | |
| } | |
| /** | |
| * @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) { | |
| return a * b; | |
| } | |
| /** | |
| * @dev Returns the integer division of two unsigned integers, reverting on | |
| * division by zero. The result is rounded towards zero. | |
| * | |
| * Counterpart to Solidity's `/` operator. | |
| * | |
| * Requirements: | |
| * | |
| * - The divisor cannot be zero. | |
| */ | |
| function div(uint256 a, uint256 b) internal pure returns (uint256) { | |
| return a / b; | |
| } | |
| /** | |
| * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), | |
| * reverting 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 a % b; | |
| } | |
| /** | |
| * @dev Returns the subtraction of two unsigned integers, reverting with custom message on | |
| * overflow (when the result is negative). | |
| * | |
| * CAUTION: This function is deprecated because it requires allocating memory for the error | |
| * message unnecessarily. For custom revert reasons use {trySub}. | |
| * | |
| * Counterpart to Solidity's `-` operator. | |
| * | |
| * Requirements: | |
| * | |
| * - Subtraction cannot overflow. | |
| */ | |
| function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
| unchecked { | |
| require(b <= a, errorMessage); | |
| return a - b; | |
| } | |
| } | |
| /** | |
| * @dev Returns the integer division of two unsigned integers, reverting 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) { | |
| unchecked { | |
| require(b > 0, errorMessage); | |
| return a / b; | |
| } | |
| } | |
| /** | |
| * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), | |
| * reverting with custom message when dividing by zero. | |
| * | |
| * CAUTION: This function is deprecated because it requires allocating memory for the error | |
| * message unnecessarily. For custom revert reasons use {tryMod}. | |
| * | |
| * 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) { | |
| unchecked { | |
| require(b > 0, errorMessage); | |
| return a % b; | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // SPDX-License-Identifier: MIT | |
| pragma solidity ^0.8.0; | |
| import "./IERC20.sol"; | |
| import "./extensions/IERC20Metadata.sol"; | |
| import "../../utils/Context.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}. | |
| */ | |
| contract ERC20 is Context, IERC20, IERC20Metadata { | |
| 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 defaut 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_) { | |
| _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); | |
| uint256 currentAllowance = _allowances[sender][_msgSender()]; | |
| require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); | |
| _approve(sender, _msgSender(), currentAllowance - amount); | |
| 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] + 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) { | |
| uint256 currentAllowance = _allowances[_msgSender()][spender]; | |
| require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); | |
| _approve(_msgSender(), spender, currentAllowance - subtractedValue); | |
| 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); | |
| uint256 senderBalance = _balances[sender]; | |
| require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); | |
| _balances[sender] = senderBalance - amount; | |
| _balances[recipient] += 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: | |
| * | |
| * - `to` 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 += amount; | |
| _balances[account] += 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); | |
| uint256 accountBalance = _balances[account]; | |
| require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); | |
| _balances[account] = accountBalance - amount; | |
| _totalSupply -= 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 { } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // SPDX-License-Identifier: MIT | |
| pragma solidity ^0.8.0; | |
| import "../IERC20.sol"; | |
| /** | |
| * @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); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // SPDX-License-Identifier: MIT | |
| pragma solidity ^0.8.0; | |
| /** | |
| * @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); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // SPDX-License-Identifier: MIT | |
| pragma solidity ^0.8.0; | |
| /* | |
| * @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; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| REMIX EXAMPLE PROJECT | |
| Remix example project is present when Remix loads very first time or there are no files existing in the File Explorer. | |
| It contains 3 directories: | |
| 1. 'contracts': Holds three contracts with different complexity level, denoted with number prefix in file name. | |
| 2. 'scripts': Holds two scripts to deploy a contract. It is explained below. | |
| 3. 'tests': Contains one test file for 'Ballot' contract with unit tests in Solidity. | |
| SCRIPTS | |
| The 'scripts' folder contains example async/await scripts for deploying the 'Storage' contract. | |
| For the deployment of any other contract, 'contractName' and 'constructorArgs' should be updated (along with other code if required). | |
| Scripts have full access to the web3.js and ethers.js libraries. | |
| To run a script, right click on file name in the file explorer and click 'Run'. Remember, Solidity file must already be compiled. | |
| Output from script will appear in remix terminal. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| pragma solidity ^0.8.6; | |
| contract MappingStructExample{ | |
| mapping(address => uint) public balanceRecieved; | |
| function getBalance() public view returns(uint){ | |
| return address(this).balance; | |
| } | |
| // send money to contract | |
| function sendMoney() public payable { | |
| balanceRecieved[msg.sender] += msg.value; | |
| } | |
| //withdraw all ETH to caller account | |
| function withdrawAllMoney()public { | |
| require(balanceRecieved[msg.sender] > 0, "your balance is ZERO BROU"); | |
| uint amountToSend = balanceRecieved[msg.sender]; | |
| balanceRecieved[msg.sender] = 0; | |
| payable (msg.sender).transfer(amountToSend); | |
| } | |
| // withdraw specific amount to chosen account | |
| function customPartialWithdraw(uint _sum, address payable _to) public { | |
| require(balanceRecieved[msg.sender] > 0, "your balance is ZERO"); | |
| require(_sum <= balanceRecieved[msg.sender], "your balance is insufficient BROU"); | |
| uint amountToSend = _sum; | |
| balanceRecieved[msg.sender] -= _sum; | |
| _to.transfer(amountToSend); | |
| } | |
| // withdraw specific amount to caller address | |
| function senderPartialWithdraw(uint _sum) public { | |
| require(balanceRecieved[msg.sender] > 0, "your balance is ZERO"); | |
| require(_sum <= balanceRecieved[msg.sender], "your balance is insufficient BROU"); | |
| uint amountToSend = _sum; | |
| balanceRecieved[msg.sender] -= _sum; | |
| payable(msg.sender).transfer(amountToSend); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // SPDX-License-Identifier: GPL-3.0 | |
| pragma solidity ^0.8.1; | |
| contract MyContract { | |
| string public myString = 'hello world'; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| pragma solidity ^0.8.6; | |
| contract SendMoneyExample3{ | |
| uint public balanceRecieved; | |
| uint public timeLock; | |
| function recieveMoney() public payable{ | |
| balanceRecieved += msg.value; | |
| timeLock = block.timestamp + 1 minutes; | |
| } | |
| function getBalance() public view returns(uint){ | |
| return address(this).balance; | |
| } | |
| function withdrawMoney() public returns(string memory) { | |
| if(timeLock <= block.timestamp){ | |
| address payable owner = payable(msg.sender); | |
| address payable to = owner; | |
| to.transfer(this.getBalance()); | |
| }else{ | |
| string memory fuck = "FUCK OFF"; | |
| return fuck; | |
| } | |
| } | |
| function withdrawMoneyTO(address payable _recipient) public{ | |
| _recipient.transfer(this.getBalance()); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| pragma solidity ^0.8.6; | |
| contract SimpleMappingExample{ | |
| mapping(address => bool) public myMapping; | |
| function setValueMapping(bool _value) public{ | |
| myMapping[msg.sender] = _value; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| pragma solidity ^0.7.6; | |
| contract StartStopUpdateExample{ | |
| address public owner; | |
| bool public pause; | |
| constructor() { | |
| owner = msg.sender; | |
| } | |
| // address payable public owner = payable(msg.sender); | |
| function setPause(bool _pause)public{ | |
| pause = _pause; | |
| require(msg.sender == owner, "u not ownaaa!!!"); | |
| } | |
| function sendMoney() payable public { | |
| } | |
| function withdrawAllMoney(address payable _to) public{ | |
| require(!pause, "withdraw is paused"); | |
| require(msg.sender == owner, "u not ownaaa!!!"); | |
| _to.transfer(address(this).balance); | |
| } | |
| function destroySmartContract(address payable _to) public{ | |
| selfdestruct(_to); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // SPDX-License-Identifier: GPL-3.0 | |
| pragma solidity ^0.8.6; | |
| contract WorkingWithVariables{ | |
| uint public myUint; | |
| function satMyUint(uint _myUint) public{ | |
| myUint = _myUint; | |
| } | |
| bool public myBool; | |
| function setMyBool(bool _myBool) public{ | |
| myBool = _myBool; | |
| } | |
| uint256 public MAX = ~uint256(0); | |
| function incrementUint() public{ //"unchecked{}" allow uint to wrap around after 0.7.0 solidity version | |
| unchecked{ | |
| MAX++; | |
| }} | |
| function decrementUint() public{ | |
| unchecked{ | |
| MAX--; | |
| }} | |
| address public myAddress; | |
| // address public myAddress = address(this); | |
| function setAddress(address _myAddress) public { | |
| myAddress = _myAddress; | |
| } | |
| function getBalanceOfAddress() public view returns(uint){ | |
| return myAddress.balance; | |
| } | |
| string public myString = 'hello world'; | |
| function setMyString (string calldata _myString) public { | |
| myString = _myString; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // SPDX-License-Identifier: GPL-3.0 | |
| pragma solidity >=0.7.0 <0.9.0; | |
| /** | |
| * @title Storage | |
| * @dev Store & retrieve value in a variable | |
| */ | |
| contract Storage { | |
| uint256 number; | |
| /** | |
| * @dev Store value in variable | |
| * @param num value to store | |
| */ | |
| function store(uint256 num) public { | |
| number = num; | |
| } | |
| /** | |
| * @dev Return value | |
| * @return value of 'number' | |
| */ | |
| function retrieve() public view returns (uint256){ | |
| return number; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // SPDX-License-Identifier: GPL-3.0 | |
| pragma solidity >=0.7.0 <0.9.0; | |
| /** | |
| * @title Owner | |
| * @dev Set & change owner | |
| */ | |
| contract Owner { | |
| address private owner; | |
| // event for EVM logging | |
| event OwnerSet(address indexed oldOwner, address indexed newOwner); | |
| // modifier to check if caller is owner | |
| modifier isOwner() { | |
| // If the first argument of 'require' evaluates to 'false', execution terminates and all | |
| // changes to the state and to Ether balances are reverted. | |
| // This used to consume all gas in old EVM versions, but not anymore. | |
| // It is often a good idea to use 'require' to check if functions are called correctly. | |
| // As a second argument, you can also provide an explanation about what went wrong. | |
| require(msg.sender == owner, "Caller is not owner"); | |
| _; | |
| } | |
| /** | |
| * @dev Set contract deployer as owner | |
| */ | |
| constructor() { | |
| owner = msg.sender; // 'msg.sender' is sender of current call, contract deployer for a constructor | |
| emit OwnerSet(address(0), owner); | |
| } | |
| /** | |
| * @dev Change owner | |
| * @param newOwner address of new owner | |
| */ | |
| function changeOwner(address newOwner) public isOwner { | |
| emit OwnerSet(owner, newOwner); | |
| owner = newOwner; | |
| } | |
| /** | |
| * @dev Return owner address | |
| * @return address of owner | |
| */ | |
| function getOwner() external view returns (address) { | |
| return owner; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // SPDX-License-Identifier: GPL-3.0 | |
| pragma solidity >=0.7.0 <0.9.0; | |
| /** | |
| * @title Ballot | |
| * @dev Implements voting process along with vote delegation | |
| */ | |
| contract Ballot { | |
| struct Voter { | |
| uint weight; // weight is accumulated by delegation | |
| bool voted; // if true, that person already voted | |
| address delegate; // person delegated to | |
| uint vote; // index of the voted proposal | |
| } | |
| struct Proposal { | |
| // If you can limit the length to a certain number of bytes, | |
| // always use one of bytes1 to bytes32 because they are much cheaper | |
| bytes32 name; // short name (up to 32 bytes) | |
| uint voteCount; // number of accumulated votes | |
| } | |
| address public chairperson; | |
| mapping(address => Voter) public voters; | |
| Proposal[] public proposals; | |
| /** | |
| * @dev Create a new ballot to choose one of 'proposalNames'. | |
| * @param proposalNames names of proposals | |
| */ | |
| constructor(bytes32[] memory proposalNames) { | |
| chairperson = msg.sender; | |
| voters[chairperson].weight = 1; | |
| for (uint i = 0; i < proposalNames.length; i++) { | |
| // 'Proposal({...})' creates a temporary | |
| // Proposal object and 'proposals.push(...)' | |
| // appends it to the end of 'proposals'. | |
| proposals.push(Proposal({ | |
| name: proposalNames[i], | |
| voteCount: 0 | |
| })); | |
| } | |
| } | |
| /** | |
| * @dev Give 'voter' the right to vote on this ballot. May only be called by 'chairperson'. | |
| * @param voter address of voter | |
| */ | |
| function giveRightToVote(address voter) public { | |
| require( | |
| msg.sender == chairperson, | |
| "Only chairperson can give right to vote." | |
| ); | |
| require( | |
| !voters[voter].voted, | |
| "The voter already voted." | |
| ); | |
| require(voters[voter].weight == 0); | |
| voters[voter].weight = 1; | |
| } | |
| /** | |
| * @dev Delegate your vote to the voter 'to'. | |
| * @param to address to which vote is delegated | |
| */ | |
| function delegate(address to) public { | |
| Voter storage sender = voters[msg.sender]; | |
| require(!sender.voted, "You already voted."); | |
| require(to != msg.sender, "Self-delegation is disallowed."); | |
| while (voters[to].delegate != address(0)) { | |
| to = voters[to].delegate; | |
| // We found a loop in the delegation, not allowed. | |
| require(to != msg.sender, "Found loop in delegation."); | |
| } | |
| sender.voted = true; | |
| sender.delegate = to; | |
| Voter storage delegate_ = voters[to]; | |
| if (delegate_.voted) { | |
| // If the delegate already voted, | |
| // directly add to the number of votes | |
| proposals[delegate_.vote].voteCount += sender.weight; | |
| } else { | |
| // If the delegate did not vote yet, | |
| // add to her weight. | |
| delegate_.weight += sender.weight; | |
| } | |
| } | |
| /** | |
| * @dev Give your vote (including votes delegated to you) to proposal 'proposals[proposal].name'. | |
| * @param proposal index of proposal in the proposals array | |
| */ | |
| function vote(uint proposal) public { | |
| Voter storage sender = voters[msg.sender]; | |
| require(sender.weight != 0, "Has no right to vote"); | |
| require(!sender.voted, "Already voted."); | |
| sender.voted = true; | |
| sender.vote = proposal; | |
| // If 'proposal' is out of the range of the array, | |
| // this will throw automatically and revert all | |
| // changes. | |
| proposals[proposal].voteCount += sender.weight; | |
| } | |
| /** | |
| * @dev Computes the winning proposal taking all previous votes into account. | |
| * @return winningProposal_ index of winning proposal in the proposals array | |
| */ | |
| function winningProposal() public view | |
| returns (uint winningProposal_) | |
| { | |
| uint winningVoteCount = 0; | |
| for (uint p = 0; p < proposals.length; p++) { | |
| if (proposals[p].voteCount > winningVoteCount) { | |
| winningVoteCount = proposals[p].voteCount; | |
| winningProposal_ = p; | |
| } | |
| } | |
| } | |
| /** | |
| * @dev Calls winningProposal() function to get the index of the winner contained in the proposals array and then | |
| * @return winnerName_ the name of the winner | |
| */ | |
| function winnerName() public view | |
| returns (bytes32 winnerName_) | |
| { | |
| winnerName_ = proposals[winningProposal()].name; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| *Submitted for verification at BscScan.com on 2021-05-31 | |
| */ | |
| //SPDX-License-Identifier: MIT | |
| pragma solidity ^0.7.4; | |
| /** | |
| * $$$$$$$\ $$$$$$$$\ $$\ | |
| * $$ __$$\ \__$$ __| $$ | | |
| * $$ | $$ | $$$$$$\ $$$$$$\ $$ | $$$$$$\ $$$$$$\ $$ | $$$$$$$\ | |
| * $$$$$$$\ |$$ __$$\ $$ __$$\ $$ |$$ __$$\ $$ __$$\ $$ |$$ _____| | |
| * $$ __$$\ $$ / $$ |$$ / $$ |$$ |$$ / $$ |$$ / $$ |$$ |\$$$$$$\ | |
| * $$ | $$ |$$ | $$ |$$ | $$ |$$ |$$ | $$ |$$ | $$ |$$ | \____$$\ | |
| * $$$$$$$ |\$$$$$$ |\$$$$$$$ |$$ |\$$$$$$ |\$$$$$$ |$$ |$$$$$$$ | | |
| * \_______/ \______/ \____$$ |\__| \______/ \______/ \__|\_______/ | |
| * $$\ $$ | | |
| * \$$$$$$ | | |
| * \______/ | |
| * | |
| * BogTools / Bogged Finance | |
| * https://bogtools.io/ | |
| * https://bogged.finance/ | |
| * https://t.me/bogtools | |
| */ | |
| /** | |
| * Standard SafeMath, stripped down to just add/sub/mul/div | |
| */ | |
| library SafeMath { | |
| function add(uint256 a, uint256 b) internal pure returns (uint256) { | |
| uint256 c = a + b; | |
| require(c >= a, "SafeMath: addition overflow"); | |
| return c; | |
| } | |
| function sub(uint256 a, uint256 b) internal pure returns (uint256) { | |
| return sub(a, b, "SafeMath: subtraction overflow"); | |
| } | |
| function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
| require(b <= a, errorMessage); | |
| uint256 c = a - b; | |
| return c; | |
| } | |
| function mul(uint256 a, uint256 b) internal pure returns (uint256) { | |
| if (a == 0) { | |
| return 0; | |
| } | |
| uint256 c = a * b; | |
| require(c / a == b, "SafeMath: multiplication overflow"); | |
| return c; | |
| } | |
| function div(uint256 a, uint256 b) internal pure returns (uint256) { | |
| return div(a, b, "SafeMath: division by zero"); | |
| } | |
| function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
| // Solidity only automatically asserts when dividing by 0 | |
| 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; | |
| } | |
| } | |
| /** | |
| * BEP20 standard interface. | |
| */ | |
| interface IBEP20 { | |
| function totalSupply() external view returns (uint256); | |
| function decimals() external view returns (uint8); | |
| function symbol() external view returns (string memory); | |
| function name() external view returns (string memory); | |
| function getOwner() external view returns (address); | |
| function balanceOf(address account) external view returns (uint256); | |
| function transfer(address recipient, uint256 amount) external returns (bool); | |
| function allowance(address _owner, address spender) external view returns (uint256); | |
| function approve(address spender, uint256 amount) external returns (bool); | |
| function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); | |
| event Transfer(address indexed from, address indexed to, uint256 value); | |
| event Approval(address indexed owner, address indexed spender, uint256 value); | |
| } | |
| /** | |
| * Allows for contract ownership along with multi-address authorization | |
| */ | |
| abstract contract BOGAuth { | |
| address owner; | |
| mapping (address => bool) private authorizations; | |
| constructor(address _owner) { | |
| owner = _owner; | |
| authorizations[_owner] = true; | |
| } | |
| /** | |
| * Function modifier to require caller to be contract owner | |
| */ | |
| modifier onlyOwner() { | |
| require(isOwner(msg.sender), "!OWNER"); _; | |
| } | |
| /** | |
| * Function modifier to require caller to be authorized | |
| */ | |
| modifier authorized() { | |
| require(isAuthorized(msg.sender), "!AUTHORIZED"); _; | |
| } | |
| /** | |
| * Authorize address. Any authorized address | |
| */ | |
| function authorize(address adr) public authorized { | |
| authorizations[adr] = true; | |
| emit Authorized(adr); | |
| } | |
| /** | |
| * Remove address' authorization. Owner only | |
| */ | |
| function unauthorize(address adr) public onlyOwner { | |
| authorizations[adr] = false; | |
| emit Unauthorized(adr); | |
| } | |
| /** | |
| * Check if address is owner | |
| */ | |
| function isOwner(address account) public view returns (bool) { | |
| return account == owner; | |
| } | |
| /** | |
| * Return address' authorization status | |
| */ | |
| function isAuthorized(address adr) public view returns (bool) { | |
| return authorizations[adr]; | |
| } | |
| /** | |
| * Transfer ownership to new address. Caller must be owner. | |
| */ | |
| function transferOwnership(address payable adr) public onlyOwner { | |
| owner = adr; | |
| authorizations[adr] = true; | |
| emit OwnershipTransferred(adr); | |
| } | |
| event OwnershipTransferred(address owner); | |
| event Authorized(address adr); | |
| event Unauthorized(address adr); | |
| } | |
| /** | |
| * Pause and unpause certain functions using modifiers | |
| */ | |
| abstract contract BOGPausable is BOGAuth { | |
| bool public paused; | |
| constructor (bool _paused) { paused = _paused; } | |
| modifier whenPaused() { | |
| require(paused || isAuthorized(msg.sender), "!PAUSED"); _; | |
| } | |
| modifier notPaused() { | |
| require(!paused || isAuthorized(msg.sender), "PAUSED"); _; | |
| } | |
| function pause() external notPaused authorized { | |
| paused = true; | |
| emit Paused(); | |
| } | |
| function unpause() public whenPaused authorized { | |
| _unpause(); | |
| } | |
| function _unpause() internal { | |
| paused = false; | |
| emit Unpaused(); | |
| } | |
| event Paused(); | |
| event Unpaused(); | |
| } | |
| interface IDEXFactory { | |
| function createPair(address tokenA, address tokenB) external returns (address pair); | |
| } | |
| interface IDEXRouter { | |
| function factory() external pure returns (address); | |
| function WETH() external pure returns (address); | |
| function addLiquidityETH( | |
| address token, | |
| uint amountTokenDesired, | |
| uint amountTokenMin, | |
| uint amountETHMin, | |
| address to, | |
| uint deadline | |
| ) external payable returns (uint amountToken, uint amountETH, uint liquidity); | |
| 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; | |
| } | |
| contract BOG is IBEP20, BOGAuth, BOGPausable { | |
| using SafeMath for uint256; | |
| string constant _name = "Bogged Finance"; | |
| string constant _symbol = "BOG"; | |
| uint8 constant _decimals = 18; | |
| uint256 private _totalSupply = 15000000 * (10 ** _decimals); | |
| uint256 public _maxTxAmount = 50000 * (10 ** _decimals); | |
| mapping (address => uint256) private _balances; | |
| mapping (address => mapping (address => uint256)) private _allowances; | |
| mapping (address => bool) public hasFee; | |
| mapping (address => bool) public isExempt; | |
| uint256 public autoLiquidityFee = 2; | |
| uint256 public stakingFee = 3; | |
| uint256 public feeDenominator = 100; | |
| address public autoLiquidityReceiver; | |
| address public stakingFeeReceiver; | |
| IDEXRouter public router; | |
| address private WBNB; | |
| address public liquifyPair; | |
| uint256 launchedAt; | |
| bool public liquifyEnabled = true; | |
| uint256 public liquifyAmount = 250 * (10 ** _decimals); | |
| bool private inLiquify; | |
| modifier liquifying() { inLiquify = true; _; inLiquify = false; } | |
| constructor (address _owner, address _router) BOGAuth(_owner) BOGPausable(true) { | |
| router = IDEXRouter(_router); | |
| WBNB = router.WETH(); | |
| liquifyPair = IDEXFactory(router.factory()).createPair(WBNB, address(this)); | |
| _allowances[address(this)][_router] = uint256(-1); | |
| hasFee[liquifyPair] = true; | |
| isExempt[_owner] = true; | |
| isExempt[address(this)] = true; | |
| _balances[_owner] = _totalSupply; | |
| emit Transfer(address(0), _owner, _totalSupply); | |
| payable(_owner).transfer(address(this).balance); | |
| } | |
| receive() external payable { | |
| assert(msg.sender == WBNB || msg.sender == address(router)); | |
| } | |
| modifier migrationProtection(address sender) { | |
| require(!paused || isAuthorized(sender) || isAuthorized(msg.sender), "PROTECTED"); _; | |
| } | |
| function totalSupply() external view override returns (uint256) { return _totalSupply; } | |
| function decimals() external pure override returns (uint8) { return _decimals; } | |
| function symbol() external pure override returns (string memory) { return _symbol; } | |
| function name() external pure override returns (string memory) { return _name; } | |
| function getOwner() external view override returns (address) { return owner; } | |
| function balanceOf(address account) external view override returns (uint256) { return _balances[account]; } | |
| function allowance(address holder, address spender) external view override returns (uint256) { return _allowances[holder][spender]; } | |
| function approve(address spender, uint256 amount) public override returns (bool) { | |
| _allowances[msg.sender][spender] = amount; | |
| emit Approval(msg.sender, spender, amount); | |
| return true; | |
| } | |
| function approveMax(address spender) external returns (bool) { | |
| return approve(spender, uint256(-1)); | |
| } | |
| function transfer(address recipient, uint256 amount) external override returns (bool) { | |
| return _transferFrom(msg.sender, recipient, amount); | |
| } | |
| function transferFrom(address sender, address recipient, uint256 amount) external override returns (bool) { | |
| return _transferFrom(sender, recipient, amount); | |
| } | |
| function _transferFrom(address sender, address recipient, uint256 amount) internal migrationProtection(sender) returns (bool) { | |
| checkTxLimit(sender, recipient, amount); | |
| if(sender != msg.sender && _allowances[sender][msg.sender] != uint256(-1)){ | |
| _allowances[sender][msg.sender] = _allowances[sender][msg.sender].sub(amount, "Insufficient Allowance"); | |
| } | |
| if(launchedAt == 0 && recipient == liquifyPair){ launch(); } | |
| bool shouldLiquify = shouldAutoLiquify() && !(isExempt[sender] || isExempt[recipient]); | |
| if(shouldLiquify){ autoLiquify(); } | |
| _balances[sender] = _balances[sender].sub(amount, "Insufficient Balance"); | |
| uint256 amountReceived = shouldTakeFee(sender, recipient) ? takeFee(sender, amount) : amount; | |
| _balances[recipient] = _balances[recipient].add(amountReceived); | |
| emit Transfer(sender, recipient, amountReceived); | |
| return true; | |
| } | |
| function checkTxLimit(address sender, address recipient, uint256 amount) internal view { | |
| require(amount <= _maxTxAmount || isExempt[sender] || isExempt[recipient], "TX Limit Exceeded"); | |
| } | |
| function takeFee(address sender, uint256 amount) internal returns (uint256) { | |
| uint256 liquidityFeeAmount = amount.mul(getLiquidityFee()).div(feeDenominator); | |
| uint256 stakingFeeAmount = amount.mul(stakingFee).div(feeDenominator); | |
| _balances[address(this)] = _balances[address(this)].add(liquidityFeeAmount); | |
| _balances[stakingFeeReceiver] = _balances[stakingFeeReceiver].add(stakingFeeAmount); | |
| emit Transfer(sender, address(this), liquidityFeeAmount); | |
| emit Transfer(sender, stakingFeeReceiver, stakingFeeAmount); | |
| return amount.sub(liquidityFeeAmount).sub(stakingFeeAmount); | |
| } | |
| function getLiquidityFee() internal view returns (uint256) { | |
| if(launchedAt + 1 >= block.number){ return feeDenominator.sub(stakingFee).sub(1); } | |
| return autoLiquidityFee; | |
| } | |
| function shouldAutoLiquify() internal view returns (bool) { | |
| return msg.sender != liquifyPair | |
| && !inLiquify | |
| && liquifyEnabled | |
| && _balances[address(this)] >= liquifyAmount; | |
| } | |
| function autoLiquify() internal liquifying { | |
| uint256 amountToSwap = liquifyAmount.div(2); | |
| address[] memory path = new address[](2); | |
| path[0] = address(this); | |
| path[1] = WBNB; | |
| uint256 balanceBefore = address(this).balance; | |
| try router.swapExactTokensForETHSupportingFeeOnTransferTokens( | |
| amountToSwap, | |
| 0, | |
| path, | |
| address(this), | |
| block.timestamp | |
| ) {} catch {} | |
| uint256 amountBNB = address(this).balance.sub(balanceBefore); | |
| try router.addLiquidityETH{value: amountBNB}( | |
| address(this), | |
| amountToSwap, | |
| 0, | |
| 0, | |
| autoLiquidityReceiver, | |
| block.timestamp | |
| ) { | |
| emit AutoLiquify(amountBNB, amountToSwap); | |
| } catch {} | |
| } | |
| function launch() internal { | |
| launchedAt = block.number; | |
| _unpause(); | |
| } | |
| function setTxLimit(uint256 amount) external authorized { | |
| require(amount >= _totalSupply / 1000, "Limit too low"); | |
| _maxTxAmount = amount; | |
| } | |
| function setLiquify(bool enabled, uint256 amount) external authorized { | |
| require(amount <= 1000 * (10 ** _decimals)); | |
| liquifyEnabled = enabled; | |
| liquifyAmount = amount; | |
| } | |
| function migrateAutoLiquidityDEX(address _router, address _liquifyPair) external authorized { | |
| _allowances[address(this)][address(router)] = 0; | |
| router = IDEXRouter(_router); | |
| liquifyPair = _liquifyPair; | |
| hasFee[liquifyPair] = true; | |
| _allowances[address(this)][_router] = uint256(-1); | |
| } | |
| function shouldTakeFee(address sender, address recipient) internal view returns (bool) { | |
| if(isExempt[sender] || isExempt[recipient] || inLiquify){ return false; } | |
| return hasFee[sender] || hasFee[recipient]; | |
| } | |
| function setHasFee(address adr, bool state) external authorized { | |
| require(!isExempt[adr], "Is Exempt"); | |
| hasFee[adr] = state; | |
| } | |
| function setIsExempt(address adr, bool state) external authorized { | |
| require(!hasFee[adr], "Has Fee"); | |
| isExempt[adr] = state; | |
| } | |
| function setFees(uint256 _liquidityFee, uint256 _stakingFee, uint256 _feeDenominator) external authorized { | |
| autoLiquidityFee = _liquidityFee; | |
| stakingFee = _stakingFee; | |
| feeDenominator = _feeDenominator; | |
| require(autoLiquidityFee.add(stakingFee).mul(100).div(feeDenominator) <= 10, "Fee Limit Exceeded"); | |
| } | |
| function setFeeReceivers(address _autoLiquidityReceiver, address _stakingFeeReceiver) external authorized { | |
| autoLiquidityReceiver = _autoLiquidityReceiver; | |
| stakingFeeReceiver = _stakingFeeReceiver; | |
| } | |
| function rescueBNB() external authorized { | |
| payable(msg.sender).transfer(address(this).balance); | |
| } | |
| event AutoLiquify(uint256 amountBNB, uint256 amountBOG); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| pragma solidity ^0.6.0; | |
| contract Counter { | |
| uint public count = 0; | |
| function incrementCount() public{ | |
| count ++; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // SPDX-License-Identifier: MIT | |
| pragma solidity 0.8.0; | |
| import "./Token.sol"; | |
| contract dBank { | |
| //Token contract to variable | |
| Token private token; | |
| //mappings | |
| mapping(address => uint256) public etherBalanceOf; | |
| mapping(address => uint256) public depositStart; | |
| mapping(address => bool) public isDeposited; | |
| //events | |
| event Deposit(address indexed user, uint256 etherAmount, uint256 timeStart); | |
| event Withdraw(address indexed user, uint256 etherAmount, uint256 depositTime, uint256 interest); | |
| //pass as constructor argument deployed Token contract | |
| constructor(Token _token) public { | |
| //deployed token contract to variable | |
| token = _token; | |
| } | |
| function deposit() public payable { | |
| //check if msg.sender didn't already deposited funds | |
| require(isDeposited[msg.sender] == false, "Error, deposit already active"); | |
| //check if msg.value is >= than 0.01 ETH=(1e16 or 10**16) | |
| require(msg.value >= 10**16, "Error, deposti must be >= 0.01 ETH"); | |
| //increase msg.sender ether deposit balance | |
| etherBalanceOf[msg.sender] = etherBalanceOf[msg.sender] + msg.value; | |
| //start msg.sender hodling time | |
| depositStart[msg.sender] = depositStart[msg.sender] + block.timestamp; | |
| //set msg.sender deposit status to true | |
| isDeposited[msg.sender] = true; | |
| //emit Deposit event | |
| emit Deposit(msg.sender, msg.value, block.timestamp); | |
| } | |
| function withdraw() public payable { | |
| //check if msg.sender deposit status is true | |
| require(isDeposited[msg.sender] == true, "Error, no previous deposit"); | |
| //msg.sender ether deposit balance to variable for event | |
| uint256 userBalance = etherBalanceOf[msg.sender]; | |
| //check user's hodl time | |
| uint256 depositTime = block.timestamp - depositStart[msg.sender]; | |
| //calc interest per second and calc accrued interest | |
| //31668017 - interest(10% APY) per second for min. deposit amount (0.01 ETH), cuz: | |
| //1e15(10% of 0.01 ETH) / 31577600 (seconds in 365.25 days) | |
| //(etherBalanceOf[msg.sender] / 1e16) - calc. how much higher interest will be (based on deposit), e.g.: | |
| //for min. deposit (0.01 ETH), (etherBalanceOf[msg.sender] / 1e16) = 1 (the same, 31668017/s) | |
| //for deposit 0.02 ETH, (etherBalanceOf[msg.sender] / 1e16) = 2 (doubled, (2*31668017)/s) | |
| uint256 interestPerSecond = 31668017 * (etherBalanceOf[msg.sender] / 1e16); | |
| uint256 interest = interestPerSecond * depositTime; | |
| //send eth to user | |
| msg.sender.transfer(userBalance); | |
| //send interest in tokens to user | |
| token.mint(msg.sender, interest); | |
| //reset depositer data | |
| depositStart[msg.sender] = 0; | |
| etherBalanceOf[msg.sender] = 0; | |
| isDeposited[msg.sender] = false; | |
| //emit event | |
| emit Withdraw(msg.sender, userBalance, depositTime, interest); | |
| } | |
| function borrow() public payable { | |
| //check if collateral is >= than 0.01 ETH | |
| //check if user doesn't have active loan | |
| //add msg.value to ether collateral | |
| //calc tokens amount to mint, 50% of msg.value | |
| //mint&send tokens to user | |
| //activate borrower's loan status | |
| //emit event | |
| } | |
| function payOff() public { | |
| //check if loan is active | |
| //transfer tokens from user back to the contract | |
| //calc fee | |
| //send user's collateral minus fee | |
| //reset borrower's data | |
| //emit event | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| *Submitted for verification at BscScan.com on 2021-04-28 | |
| */ | |
| /** | |
| The Dogefather | |
| SNL May 8 | |
| https://twitter.com/elonmusk/status/1387290679794089986 | |
| 5% distributed to token holders | |
| 5% added to liquidity pool | |
| t.me/dogefatherBSC | |
| */ | |
| pragma solidity ^0.6.12; | |
| // SPDX-License-Identifier: Unlicensed | |
| interface IERC20 { | |
| 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); | |
| } | |
| /** | |
| * @dev Wrappers over Solidity's arithmetic operations with added overflow | |
| * checks. | |
| * | |
| * Arithmetic operations in Solidity wrap on overflow. This can easily result | |
| * in bugs, because programmers usually assume that an overflow raises an | |
| * error, which is the standard behavior in high level programming languages. | |
| * `SafeMath` restores this intuition by reverting the transaction when an | |
| * operation overflows. | |
| * | |
| * Using this library instead of the unchecked operations eliminates an entire | |
| * class of bugs, so it's recommended to use it always. | |
| */ | |
| 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 <= 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; | |
| } | |
| } | |
| abstract contract Context { | |
| function _msgSender() internal view virtual returns (address payable) { | |
| return msg.sender; | |
| } | |
| function _msgData() internal view virtual returns (bytes memory) { | |
| this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 | |
| return msg.data; | |
| } | |
| } | |
| /** | |
| * @dev Collection of functions related to the address type | |
| */ | |
| library Address { | |
| /** | |
| * @dev Returns true if `account` is a contract. | |
| * | |
| * [IMPORTANT] | |
| * ==== | |
| * It is unsafe to assume that an address for which this function returns | |
| * false is an externally-owned account (EOA) and not a contract. | |
| * | |
| * Among others, `isContract` will return false for the following | |
| * types of addresses: | |
| * | |
| * - an externally-owned account | |
| * - a contract in construction | |
| * - an address where a contract will be created | |
| * - an address where a contract lived, but was destroyed | |
| * ==== | |
| */ | |
| function isContract(address account) internal view returns (bool) { | |
| // According to EIP-1052, 0x0 is the value returned for not-yet created accounts | |
| // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned | |
| // for accounts without code, i.e. `keccak256('')` | |
| bytes32 codehash; | |
| bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; | |
| // solhint-disable-next-line no-inline-assembly | |
| assembly { codehash := extcodehash(account) } | |
| return (codehash != accountHash && codehash != 0x0); | |
| } | |
| /** | |
| * @dev Replacement for Solidity's `transfer`: sends `amount` wei to | |
| * `recipient`, forwarding all available gas and reverting on errors. | |
| * | |
| * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost | |
| * of certain opcodes, possibly making contracts go over the 2300 gas limit | |
| * imposed by `transfer`, making them unable to receive funds via | |
| * `transfer`. {sendValue} removes this limitation. | |
| * | |
| * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. | |
| * | |
| * IMPORTANT: because control is transferred to `recipient`, care must be | |
| * taken to not create reentrancy vulnerabilities. Consider using | |
| * {ReentrancyGuard} or the | |
| * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. | |
| */ | |
| function sendValue(address payable recipient, uint256 amount) internal { | |
| require(address(this).balance >= amount, "Address: insufficient balance"); | |
| // solhint-disable-next-line avoid-low-level-calls, avoid-call-value | |
| (bool success, ) = recipient.call{ value: amount }(""); | |
| require(success, "Address: unable to send value, recipient may have reverted"); | |
| } | |
| /** | |
| * @dev Performs a Solidity function call using a low level `call`. A | |
| * plain`call` is an unsafe replacement for a function call: use this | |
| * function instead. | |
| * | |
| * If `target` reverts with a revert reason, it is bubbled up by this | |
| * function (like regular Solidity function calls). | |
| * | |
| * Returns the raw returned data. To convert to the expected return value, | |
| * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. | |
| * | |
| * Requirements: | |
| * | |
| * - `target` must be a contract. | |
| * - calling `target` with `data` must not revert. | |
| * | |
| * _Available since v3.1._ | |
| */ | |
| function functionCall(address target, bytes memory data) internal returns (bytes memory) { | |
| return functionCall(target, data, "Address: low-level call failed"); | |
| } | |
| /** | |
| * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with | |
| * `errorMessage` as a fallback revert reason when `target` reverts. | |
| * | |
| * _Available since v3.1._ | |
| */ | |
| function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { | |
| return _functionCallWithValue(target, data, 0, errorMessage); | |
| } | |
| /** | |
| * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], | |
| * but also transferring `value` wei to `target`. | |
| * | |
| * Requirements: | |
| * | |
| * - the calling contract must have an ETH balance of at least `value`. | |
| * - the called Solidity function must be `payable`. | |
| * | |
| * _Available since v3.1._ | |
| */ | |
| function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { | |
| return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); | |
| } | |
| /** | |
| * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but | |
| * with `errorMessage` as a fallback revert reason when `target` reverts. | |
| * | |
| * _Available since v3.1._ | |
| */ | |
| function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { | |
| require(address(this).balance >= value, "Address: insufficient balance for call"); | |
| return _functionCallWithValue(target, data, value, errorMessage); | |
| } | |
| function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) { | |
| require(isContract(target), "Address: call to non-contract"); | |
| // solhint-disable-next-line avoid-low-level-calls | |
| (bool success, bytes memory returndata) = target.call{ value: weiValue }(data); | |
| if (success) { | |
| return returndata; | |
| } else { | |
| // Look for revert reason and bubble it up if present | |
| if (returndata.length > 0) { | |
| // The easiest way to bubble the revert reason is using memory via assembly | |
| // solhint-disable-next-line no-inline-assembly | |
| assembly { | |
| let returndata_size := mload(returndata) | |
| revert(add(32, returndata), returndata_size) | |
| } | |
| } else { | |
| revert(errorMessage); | |
| } | |
| } | |
| } | |
| } | |
| /** | |
| * @dev Contract module which provides a basic access control mechanism, where | |
| * there is an account (an owner) that can be granted exclusive access to | |
| * specific functions. | |
| * | |
| * By default, the owner account will be the one that deploys the contract. This | |
| * can later be changed with {transferOwnership}. | |
| * | |
| * This module is used through inheritance. It will make available the modifier | |
| * `onlyOwner`, which can be applied to your functions to restrict their use to | |
| * the owner. | |
| */ | |
| contract Ownable is Context { | |
| address private _owner; | |
| address private _previousOwner; | |
| uint256 private _lockTime; | |
| event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); | |
| /** | |
| * @dev Initializes the contract setting the deployer as the initial owner. | |
| */ | |
| constructor () internal { | |
| 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; | |
| } | |
| function geUnlockTime() public view returns (uint256) { | |
| return _lockTime; | |
| } | |
| //Locks the contract for owner for the amount of time provided | |
| function lock(uint256 time) public virtual onlyOwner { | |
| _previousOwner = _owner; | |
| _owner = address(0); | |
| _lockTime = now + time; | |
| emit OwnershipTransferred(_owner, address(0)); | |
| } | |
| //Unlocks the contract for owner when _lockTime is exceeds | |
| function unlock() public virtual { | |
| require(_previousOwner == msg.sender, "You don't have permission to unlock"); | |
| require(now > _lockTime , "Contract is locked until 7 days"); | |
| emit OwnershipTransferred(_owner, _previousOwner); | |
| _owner = _previousOwner; | |
| } | |
| } | |
| // pragma solidity >=0.5.0; | |
| 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.5.0; | |
| 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; | |
| } | |
| contract Dogefather is Context, IERC20, Ownable { | |
| using SafeMath for uint256; | |
| using Address for address; | |
| mapping (address => uint256) private _rOwned; | |
| mapping (address => uint256) private _tOwned; | |
| mapping (address => mapping (address => uint256)) private _allowances; | |
| mapping (address => bool) private _isExcludedFromFee; | |
| mapping (address => bool) private _isExcluded; | |
| address[] private _excluded; | |
| uint256 private constant MAX = ~uint256(0); | |
| uint256 private _tTotal = 1000000000 * 10**6 * 10**9; | |
| uint256 private _rTotal = (MAX - (MAX % _tTotal)); | |
| uint256 private _tFeeTotal; | |
| string private _name = "Dogefather"; | |
| string private _symbol = "Dogefather"; | |
| uint8 private _decimals = 9; | |
| uint256 public _taxFee = 5; | |
| uint256 private _previousTaxFee = _taxFee; | |
| uint256 public _liquidityFee = 5; | |
| uint256 private _previousLiquidityFee = _liquidityFee; | |
| IUniswapV2Router02 public immutable uniswapV2Router; | |
| address public immutable uniswapV2Pair; | |
| bool inSwapAndLiquify; | |
| bool public swapAndLiquifyEnabled = true; | |
| uint256 public _maxTxAmount = 5000000 * 10**6 * 10**9; | |
| uint256 private numTokensSellToAddToLiquidity = 500000 * 10**6 * 10**9; | |
| event MinTokensBeforeSwapUpdated(uint256 minTokensBeforeSwap); | |
| event SwapAndLiquifyEnabledUpdated(bool enabled); | |
| event SwapAndLiquify( | |
| uint256 tokensSwapped, | |
| uint256 ethReceived, | |
| uint256 tokensIntoLiqudity | |
| ); | |
| modifier lockTheSwap { | |
| inSwapAndLiquify = true; | |
| _; | |
| inSwapAndLiquify = false; | |
| } | |
| constructor () public { | |
| _rOwned[_msgSender()] = _rTotal; | |
| IUniswapV2Router02 _uniswapV2Router = IUniswapV2Router02(0x05fF2B0DB69458A0750badebc4f9e13aDd608C7F); | |
| // Create a uniswap pair for this new token | |
| uniswapV2Pair = IUniswapV2Factory(_uniswapV2Router.factory()) | |
| .createPair(address(this), _uniswapV2Router.WETH()); | |
| // set the rest of the contract variables | |
| uniswapV2Router = _uniswapV2Router; | |
| //exclude owner and this contract from fee | |
| _isExcludedFromFee[owner()] = true; | |
| _isExcludedFromFee[address(this)] = true; | |
| emit Transfer(address(0), _msgSender(), _tTotal); | |
| } | |
| function name() public view returns (string memory) { | |
| return _name; | |
| } | |
| function symbol() public view returns (string memory) { | |
| return _symbol; | |
| } | |
| function decimals() public view returns (uint8) { | |
| return _decimals; | |
| } | |
| function totalSupply() public view override returns (uint256) { | |
| return _tTotal; | |
| } | |
| function balanceOf(address account) public view override returns (uint256) { | |
| if (_isExcluded[account]) return _tOwned[account]; | |
| return tokenFromReflection(_rOwned[account]); | |
| } | |
| function transfer(address recipient, uint256 amount) public override returns (bool) { | |
| _transfer(_msgSender(), recipient, amount); | |
| return true; | |
| } | |
| function allowance(address owner, address spender) public view override returns (uint256) { | |
| return _allowances[owner][spender]; | |
| } | |
| function approve(address spender, uint256 amount) public override returns (bool) { | |
| _approve(_msgSender(), spender, amount); | |
| return true; | |
| } | |
| function transferFrom(address sender, address recipient, uint256 amount) public override returns (bool) { | |
| _transfer(sender, recipient, amount); | |
| _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); | |
| return true; | |
| } | |
| function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { | |
| _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); | |
| return true; | |
| } | |
| 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; | |
| } | |
| function isExcludedFromReward(address account) public view returns (bool) { | |
| return _isExcluded[account]; | |
| } | |
| function totalFees() public view returns (uint256) { | |
| return _tFeeTotal; | |
| } | |
| function deliver(uint256 tAmount) public { | |
| address sender = _msgSender(); | |
| require(!_isExcluded[sender], "Excluded addresses cannot call this function"); | |
| (uint256 rAmount,,,,,) = _getValues(tAmount); | |
| _rOwned[sender] = _rOwned[sender].sub(rAmount); | |
| _rTotal = _rTotal.sub(rAmount); | |
| _tFeeTotal = _tFeeTotal.add(tAmount); | |
| } | |
| function reflectionFromToken(uint256 tAmount, bool deductTransferFee) public view returns(uint256) { | |
| require(tAmount <= _tTotal, "Amount must be less than supply"); | |
| if (!deductTransferFee) { | |
| (uint256 rAmount,,,,,) = _getValues(tAmount); | |
| return rAmount; | |
| } else { | |
| (,uint256 rTransferAmount,,,,) = _getValues(tAmount); | |
| return rTransferAmount; | |
| } | |
| } | |
| function tokenFromReflection(uint256 rAmount) public view returns(uint256) { | |
| require(rAmount <= _rTotal, "Amount must be less than total reflections"); | |
| uint256 currentRate = _getRate(); | |
| return rAmount.div(currentRate); | |
| } | |
| function excludeFromReward(address account) public onlyOwner() { | |
| // require(account != 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D, 'We can not exclude Uniswap router.'); | |
| require(!_isExcluded[account], "Account is already excluded"); | |
| if(_rOwned[account] > 0) { | |
| _tOwned[account] = tokenFromReflection(_rOwned[account]); | |
| } | |
| _isExcluded[account] = true; | |
| _excluded.push(account); | |
| } | |
| function includeInReward(address account) external onlyOwner() { | |
| require(_isExcluded[account], "Account is already excluded"); | |
| for (uint256 i = 0; i < _excluded.length; i++) { | |
| if (_excluded[i] == account) { | |
| _excluded[i] = _excluded[_excluded.length - 1]; | |
| _tOwned[account] = 0; | |
| _isExcluded[account] = false; | |
| _excluded.pop(); | |
| break; | |
| } | |
| } | |
| } | |
| function _transferBothExcluded(address sender, address recipient, uint256 tAmount) private { | |
| (uint256 rAmount, uint256 rTransferAmount, uint256 rFee, uint256 tTransferAmount, uint256 tFee, uint256 tLiquidity) = _getValues(tAmount); | |
| _tOwned[sender] = _tOwned[sender].sub(tAmount); | |
| _rOwned[sender] = _rOwned[sender].sub(rAmount); | |
| _tOwned[recipient] = _tOwned[recipient].add(tTransferAmount); | |
| _rOwned[recipient] = _rOwned[recipient].add(rTransferAmount); | |
| _takeLiquidity(tLiquidity); | |
| _reflectFee(rFee, tFee); | |
| emit Transfer(sender, recipient, tTransferAmount); | |
| } | |
| function excludeFromFee(address account) public onlyOwner { | |
| _isExcludedFromFee[account] = true; | |
| } | |
| function includeInFee(address account) public onlyOwner { | |
| _isExcludedFromFee[account] = false; | |
| } | |
| function setTaxFeePercent(uint256 taxFee) external onlyOwner() { | |
| _taxFee = taxFee; | |
| } | |
| function setLiquidityFeePercent(uint256 liquidityFee) external onlyOwner() { | |
| _liquidityFee = liquidityFee; | |
| } | |
| function setMaxTxPercent(uint256 maxTxPercent) external onlyOwner() { | |
| _maxTxAmount = _tTotal.mul(maxTxPercent).div( | |
| 10**2 | |
| ); | |
| } | |
| function setSwapAndLiquifyEnabled(bool _enabled) public onlyOwner { | |
| swapAndLiquifyEnabled = _enabled; | |
| emit SwapAndLiquifyEnabledUpdated(_enabled); | |
| } | |
| //to recieve ETH from uniswapV2Router when swaping | |
| receive() external payable {} | |
| function _reflectFee(uint256 rFee, uint256 tFee) private { | |
| _rTotal = _rTotal.sub(rFee); | |
| _tFeeTotal = _tFeeTotal.add(tFee); | |
| } | |
| function _getValues(uint256 tAmount) private view returns (uint256, uint256, uint256, uint256, uint256, uint256) { | |
| (uint256 tTransferAmount, uint256 tFee, uint256 tLiquidity) = _getTValues(tAmount); | |
| (uint256 rAmount, uint256 rTransferAmount, uint256 rFee) = _getRValues(tAmount, tFee, tLiquidity, _getRate()); | |
| return (rAmount, rTransferAmount, rFee, tTransferAmount, tFee, tLiquidity); | |
| } | |
| function _getTValues(uint256 tAmount) private view returns (uint256, uint256, uint256) { | |
| uint256 tFee = calculateTaxFee(tAmount); | |
| uint256 tLiquidity = calculateLiquidityFee(tAmount); | |
| uint256 tTransferAmount = tAmount.sub(tFee).sub(tLiquidity); | |
| return (tTransferAmount, tFee, tLiquidity); | |
| } | |
| function _getRValues(uint256 tAmount, uint256 tFee, uint256 tLiquidity, uint256 currentRate) private pure returns (uint256, uint256, uint256) { | |
| uint256 rAmount = tAmount.mul(currentRate); | |
| uint256 rFee = tFee.mul(currentRate); | |
| uint256 rLiquidity = tLiquidity.mul(currentRate); | |
| uint256 rTransferAmount = rAmount.sub(rFee).sub(rLiquidity); | |
| return (rAmount, rTransferAmount, rFee); | |
| } | |
| function _getRate() private view returns(uint256) { | |
| (uint256 rSupply, uint256 tSupply) = _getCurrentSupply(); | |
| return rSupply.div(tSupply); | |
| } | |
| function _getCurrentSupply() private view returns(uint256, uint256) { | |
| uint256 rSupply = _rTotal; | |
| uint256 tSupply = _tTotal; | |
| for (uint256 i = 0; i < _excluded.length; i++) { | |
| if (_rOwned[_excluded[i]] > rSupply || _tOwned[_excluded[i]] > tSupply) return (_rTotal, _tTotal); | |
| rSupply = rSupply.sub(_rOwned[_excluded[i]]); | |
| tSupply = tSupply.sub(_tOwned[_excluded[i]]); | |
| } | |
| if (rSupply < _rTotal.div(_tTotal)) return (_rTotal, _tTotal); | |
| return (rSupply, tSupply); | |
| } | |
| function _takeLiquidity(uint256 tLiquidity) private { | |
| uint256 currentRate = _getRate(); | |
| uint256 rLiquidity = tLiquidity.mul(currentRate); | |
| _rOwned[address(this)] = _rOwned[address(this)].add(rLiquidity); | |
| if(_isExcluded[address(this)]) | |
| _tOwned[address(this)] = _tOwned[address(this)].add(tLiquidity); | |
| } | |
| function calculateTaxFee(uint256 _amount) private view returns (uint256) { | |
| return _amount.mul(_taxFee).div( | |
| 10**2 | |
| ); | |
| } | |
| function calculateLiquidityFee(uint256 _amount) private view returns (uint256) { | |
| return _amount.mul(_liquidityFee).div( | |
| 10**2 | |
| ); | |
| } | |
| function removeAllFee() private { | |
| if(_taxFee == 0 && _liquidityFee == 0) return; | |
| _previousTaxFee = _taxFee; | |
| _previousLiquidityFee = _liquidityFee; | |
| _taxFee = 0; | |
| _liquidityFee = 0; | |
| } | |
| function restoreAllFee() private { | |
| _taxFee = _previousTaxFee; | |
| _liquidityFee = _previousLiquidityFee; | |
| } | |
| function isExcludedFromFee(address account) public view returns(bool) { | |
| return _isExcludedFromFee[account]; | |
| } | |
| function _approve(address owner, address spender, uint256 amount) private { | |
| 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); | |
| } | |
| function _transfer( | |
| address from, | |
| address to, | |
| uint256 amount | |
| ) private { | |
| require(from != address(0), "ERC20: transfer from the zero address"); | |
| require(to != address(0), "ERC20: transfer to the zero address"); | |
| require(amount > 0, "Transfer amount must be greater than zero"); | |
| if(from != owner() && to != owner()) | |
| require(amount <= _maxTxAmount, "Transfer amount exceeds the maxTxAmount."); | |
| // is the token balance of this contract address over the min number of | |
| // tokens that we need to initiate a swap + liquidity lock? | |
| // also, don't get caught in a circular liquidity event. | |
| // also, don't swap & liquify if sender is uniswap pair. | |
| uint256 contractTokenBalance = balanceOf(address(this)); | |
| if(contractTokenBalance >= _maxTxAmount) | |
| { | |
| contractTokenBalance = _maxTxAmount; | |
| } | |
| bool overMinTokenBalance = contractTokenBalance >= numTokensSellToAddToLiquidity; | |
| if ( | |
| overMinTokenBalance && | |
| !inSwapAndLiquify && | |
| from != uniswapV2Pair && | |
| swapAndLiquifyEnabled | |
| ) { | |
| contractTokenBalance = numTokensSellToAddToLiquidity; | |
| //add liquidity | |
| swapAndLiquify(contractTokenBalance); | |
| } | |
| //indicates if fee should be deducted from transfer | |
| bool takeFee = true; | |
| //if any account belongs to _isExcludedFromFee account then remove the fee | |
| if(_isExcludedFromFee[from] || _isExcludedFromFee[to]){ | |
| takeFee = false; | |
| } | |
| //transfer amount, it will take tax, burn, liquidity fee | |
| _tokenTransfer(from,to,amount,takeFee); | |
| } | |
| function swapAndLiquify(uint256 contractTokenBalance) private lockTheSwap { | |
| // split the contract balance into halves | |
| uint256 half = contractTokenBalance.div(2); | |
| uint256 otherHalf = contractTokenBalance.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); // <- 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 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 | |
| owner(), | |
| block.timestamp | |
| ); | |
| } | |
| //this method is responsible for taking all fee, if takeFee is true | |
| function _tokenTransfer(address sender, address recipient, uint256 amount,bool takeFee) private { | |
| if(!takeFee) | |
| removeAllFee(); | |
| if (_isExcluded[sender] && !_isExcluded[recipient]) { | |
| _transferFromExcluded(sender, recipient, amount); | |
| } else if (!_isExcluded[sender] && _isExcluded[recipient]) { | |
| _transferToExcluded(sender, recipient, amount); | |
| } else if (!_isExcluded[sender] && !_isExcluded[recipient]) { | |
| _transferStandard(sender, recipient, amount); | |
| } else if (_isExcluded[sender] && _isExcluded[recipient]) { | |
| _transferBothExcluded(sender, recipient, amount); | |
| } else { | |
| _transferStandard(sender, recipient, amount); | |
| } | |
| if(!takeFee) | |
| restoreAllFee(); | |
| } | |
| function _transferStandard(address sender, address recipient, uint256 tAmount) private { | |
| (uint256 rAmount, uint256 rTransferAmount, uint256 rFee, uint256 tTransferAmount, uint256 tFee, uint256 tLiquidity) = _getValues(tAmount); | |
| _rOwned[sender] = _rOwned[sender].sub(rAmount); | |
| _rOwned[recipient] = _rOwned[recipient].add(rTransferAmount); | |
| _takeLiquidity(tLiquidity); | |
| _reflectFee(rFee, tFee); | |
| emit Transfer(sender, recipient, tTransferAmount); | |
| } | |
| function _transferToExcluded(address sender, address recipient, uint256 tAmount) private { | |
| (uint256 rAmount, uint256 rTransferAmount, uint256 rFee, uint256 tTransferAmount, uint256 tFee, uint256 tLiquidity) = _getValues(tAmount); | |
| _rOwned[sender] = _rOwned[sender].sub(rAmount); | |
| _tOwned[recipient] = _tOwned[recipient].add(tTransferAmount); | |
| _rOwned[recipient] = _rOwned[recipient].add(rTransferAmount); | |
| _takeLiquidity(tLiquidity); | |
| _reflectFee(rFee, tFee); | |
| emit Transfer(sender, recipient, tTransferAmount); | |
| } | |
| function _transferFromExcluded(address sender, address recipient, uint256 tAmount) private { | |
| (uint256 rAmount, uint256 rTransferAmount, uint256 rFee, uint256 tTransferAmount, uint256 tFee, uint256 tLiquidity) = _getValues(tAmount); | |
| _tOwned[sender] = _tOwned[sender].sub(tAmount); | |
| _rOwned[sender] = _rOwned[sender].sub(rAmount); | |
| _rOwned[recipient] = _rOwned[recipient].add(rTransferAmount); | |
| _takeLiquidity(tLiquidity); | |
| _reflectFee(rFee, tFee); | |
| emit Transfer(sender, recipient, tTransferAmount); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| pragma solidity ^0.6.0; | |
| contract Ownable { | |
| address owner; | |
| constructor () public { | |
| owner = msg.sender; | |
| } | |
| modifier onlyOwner(){ | |
| require(msg.sender == owner, "Must be owner"); | |
| _; | |
| } | |
| } | |
| contract SecretVault{ | |
| string secret; | |
| constructor(string memory _secret) public{ | |
| secret = _secret; | |
| } | |
| function getSecret() public view returns(string memory){ | |
| return secret; | |
| } | |
| } | |
| contract MyContract is Ownable{ | |
| address secretVault; | |
| constructor(string memory _secret) public{ | |
| SecretVault _secretVault = new SecretVault(_secret); | |
| secretVault = address(_secretVault); | |
| super; | |
| } | |
| function getSecret() public view onlyOwner returns(string memory){ | |
| SecretVault _secretVault = SecretVault(secretVault); | |
| return _secretVault.getSecret(); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * SourceUnit: /home/dave/blockchain/pokedx/pokedx-token/pokedx-token-v0.01/contracts/pokedx-token.sol | |
| */ | |
| /** | |
| * SPDX-License-Identifier: MIT | |
| */ | |
| pragma solidity ^0.8.4; | |
| interface IERC20 { | |
| function totalSupply() external view returns (uint256); | |
| function balanceOf(address account) external view returns (uint256); | |
| function transfer(address recipient, uint256 amount) external returns (bool); | |
| function allowance(address owner, address spender) external view returns (uint256); | |
| function approve(address spender, uint256 amount) external returns (bool); | |
| function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); | |
| event Transfer(address indexed from, address indexed to, uint256 value); | |
| event Approval(address indexed owner, address indexed spender, uint256 value); | |
| } | |
| interface IERC20Metadata is IERC20 { | |
| function name() external view returns (string memory); | |
| function symbol() external view returns (string memory); | |
| function decimals() external view returns (uint8); | |
| } | |
| abstract contract Context { | |
| function _msgSender() internal view virtual returns (address) {return msg.sender;} | |
| function _msgData() internal view virtual returns (bytes calldata) {this; return msg.data;} | |
| } | |
| library SafeMath { | |
| function add(uint256 a, uint256 b) internal pure returns (uint256) {return a + b;} | |
| function sub(uint256 a, uint256 b) internal pure returns (uint256) {return a - b;} | |
| function mul(uint256 a, uint256 b) internal pure returns (uint256) {return a * b;} | |
| function div(uint256 a, uint256 b) internal pure returns (uint256) {return a / b;} | |
| function mod(uint256 a, uint256 b) internal pure returns (uint256) {return a % b;} | |
| function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
| unchecked { require(b <= a, errorMessage); return a - b; } | |
| } | |
| } | |
| library Address { | |
| function isContract(address account) internal view returns (bool) { uint256 size; assembly { size := extcodesize(account) } return size > 0;} | |
| function sendValue(address payable 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"); | |
| } | |
| function functionCall(address target, bytes memory data) internal returns (bytes memory) {return functionCall(target, data, "Address: low-level call failed");} | |
| function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {return functionCallWithValue(target, data, 0, errorMessage);} | |
| function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {return functionCallWithValue(target, data, value, "Address: low-level call with value failed");} | |
| function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { | |
| require(address(this).balance >= value, "Address: insufficient balance for call"); | |
| require(isContract(target), "Address: call to non-contract"); | |
| (bool success, bytes memory returndata) = target.call{ value: value }(data); | |
| return _verifyCallResult(success, returndata, errorMessage); | |
| } | |
| function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { | |
| return functionStaticCall(target, data, "Address: low-level static call failed"); | |
| } | |
| function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) { | |
| require(isContract(target), "Address: static call to non-contract"); | |
| (bool success, bytes memory returndata) = target.staticcall(data); | |
| return _verifyCallResult(success, returndata, errorMessage); | |
| } | |
| function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { | |
| return functionDelegateCall(target, data, "Address: low-level delegate call failed"); | |
| } | |
| function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { | |
| require(isContract(target), "Address: delegate call to non-contract"); | |
| (bool success, bytes memory returndata) = target.delegatecall(data); | |
| return _verifyCallResult(success, returndata, errorMessage); | |
| } | |
| function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) { | |
| if (success) { return returndata; } else { | |
| if (returndata.length > 0) { | |
| assembly { | |
| let returndata_size := mload(returndata) | |
| revert(add(32, returndata), returndata_size) | |
| } | |
| } else {revert(errorMessage);} | |
| } | |
| } | |
| } | |
| abstract contract Ownable is Context { | |
| address private _owner; | |
| address private _previousOwner; | |
| uint256 private _lockTime; | |
| event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); | |
| constructor () { | |
| address msgSender = _msgSender(); | |
| _owner = msgSender; | |
| emit OwnershipTransferred(address(0), msgSender); | |
| } | |
| function owner() public view returns (address) { | |
| return _owner; | |
| } | |
| modifier onlyOwner() { | |
| require(_owner == _msgSender(), "Ownable: caller is not the owner"); | |
| _; | |
| } | |
| function renounceOwnership() public virtual onlyOwner { | |
| emit OwnershipTransferred(_owner, address(0)); | |
| _owner = address(0); | |
| } | |
| function transferOwnership(address newOwner) public virtual onlyOwner { | |
| require(newOwner != address(0), "Ownable: new owner is the zero address"); | |
| emit OwnershipTransferred(_owner, newOwner); | |
| _owner = newOwner; | |
| } | |
| function getUnlockTime() public view returns (uint256) { | |
| return _lockTime; | |
| } | |
| function lock(uint256 time) public virtual onlyOwner { | |
| _previousOwner = _owner; | |
| _owner = address(0); | |
| _lockTime = block.timestamp + time; | |
| emit OwnershipTransferred(_owner, address(0)); | |
| } | |
| function unlock() public virtual { | |
| require(_previousOwner == msg.sender, "Only the previous owner can unlock onwership"); | |
| require(block.timestamp > _lockTime , "The contract is still locked"); | |
| emit OwnershipTransferred(_owner, _previousOwner); | |
| _owner = _previousOwner; | |
| } | |
| } | |
| abstract contract Manageable is Context { | |
| address private _manager; | |
| event ManagementTransferred(address indexed previousManager, address indexed newManager); | |
| constructor(){ | |
| address msgSender = _msgSender(); | |
| _manager = msgSender; | |
| emit ManagementTransferred(address(0), msgSender); | |
| } | |
| function manager() public view returns(address){ return _manager; } | |
| modifier onlyManager(){ | |
| require(_manager == _msgSender(), "Manageable: caller is not the manager"); | |
| _; | |
| } | |
| function transferManagement(address newManager) external virtual onlyManager { | |
| emit ManagementTransferred(_manager, newManager); | |
| _manager = newManager; | |
| } | |
| } | |
| interface IPancakeV2Factory { | |
| event PairCreated(address indexed token0, address indexed token1, address pair, uint); | |
| function createPair(address tokenA, address tokenB) external returns (address pair); | |
| } | |
| interface IPancakeV2Router { | |
| function factory() external pure returns (address); | |
| function WETH() external pure returns (address); | |
| function addLiquidityETH( | |
| address token, | |
| uint amountTokenDesired, | |
| uint amountTokenMin, | |
| uint amountETHMin, | |
| address to, | |
| uint deadline | |
| ) external payable returns (uint amountToken, uint amountETH, uint liquidity); | |
| function swapExactTokensForETHSupportingFeeOnTransferTokens( | |
| uint amountIn, | |
| uint amountOutMin, | |
| address[] calldata path, | |
| address to, | |
| uint deadline | |
| ) external; | |
| } | |
| /** | |
| * SourceUnit: /home/dave/blockchain/pokedx/pokedx-token/pokedx-token-v0.01/contracts/pokedx-token.sol | |
| */ | |
| /** | |
| * author: | |
| * discord: | |
| * telegram: | |
| * website: | |
| * twitter: | |
| * PokeDX v0.01 | |
| * | |
| * This is a rewrite of Safeoon & S@fetoken in the hope to: | |
| * | |
| * - make it easier to change the tokenomics | |
| * - make it easier to maintain the code and develop it further | |
| * - remove redundant code | |
| * - fix some of the issues reported in the Safemoon audit (e.g. SSL-03) | |
| * https://www.certik.org/projects/safemoon | |
| * | |
| * | |
| * | |
| * __/\\\\\\\\\\\\\___ _______/\\\\\______ __/\\\________/\\\_ __/\\\\\\\\\\\\\\\_ __/\\\\\\\\\\\\____ __/\\\_______/\\\_ | |
| * _\/\\\/////////\\\_ _____/\\\///\\\____ _\/\\\_____/\\\//__ _\/\\\///////////__ _\/\\\////////\\\__ _\///\\\___/\\\/__ | |
| * _\/\\\_______\/\\\_ ___/\\\/__\///\\\__ _\/\\\__/\\\//_____ _\/\\\_____________ _\/\\\______\//\\\_ ___\///\\\\\\/____ | |
| * _\/\\\\\\\\\\\\\/__ __/\\\______\//\\\_ _\/\\\\\\//\\\_____ _\/\\\\\\\\\\\_____ _\/\\\_______\/\\\_ _____\//\\\\______ | |
| * _\/\\\/////////____ _\/\\\_______\/\\\_ _\/\\\//_\//\\\____ _\/\\\///////______ _\/\\\_______\/\\\_ ______\/\\\\______ | |
| * _\/\\\_____________ _\//\\\______/\\\__ _\/\\\____\//\\\___ _\/\\\_____________ _\/\\\_______\/\\\_ ______/\\\\\\_____ | |
| * _\/\\\_____________ __\///\\\__/\\\____ _\/\\\_____\//\\\__ _\/\\\_____________ _\/\\\_______/\\\__ ____/\\\////\\\___ | |
| * _\/\\\_____________ ____\///\\\\\/_____ _\/\\\______\//\\\_ _\/\\\\\\\\\\\\\\\_ _\/\\\\\\\\\\\\/___ __/\\\/___\///\\\_ | |
| * _\///______________ ______\/////_______ _\///________\///__ _\///////////////__ _\////////////_____ _\///_______\///__ | |
| */ | |
| ////// SPDX-License-Identifier-FLATTEN-SUPPRESS-WARNING: Unlicensed | |
| pragma solidity ^0.8.4; | |
| /** | |
| * Tokenomics: | |
| * | |
| * Liquidity 5% | |
| * Redistribution 4% | |
| * Burn 1% | |
| * Charity 2% | |
| * Marketing 3% | |
| * Tip to the Dev 0.1% | |
| */ | |
| ////import "./pokedx-token-imports.sol"; | |
| abstract contract Tokenomics { | |
| using SafeMath for uint256; | |
| // --------------------- Token Settings ------------------- // | |
| string internal constant NAME = "PokeDX.v0.01"; | |
| string internal constant SYMBOL = "PKDX.v0.01"; | |
| uint16 internal constant FEES_DIVISOR = 10**3; | |
| uint8 internal constant DECIMALS = 18; | |
| uint256 internal constant ZEROES = 10**DECIMALS; | |
| uint256 private constant MAX = ~uint256(0); | |
| uint256 internal constant TOTAL_SUPPLY = 23000000 * ZEROES; | |
| uint256 internal _reflectedSupply = (MAX - (MAX % TOTAL_SUPPLY)); | |
| /** | |
| * @dev Set the maximum transaction amount allowed in a transfer. | |
| * | |
| * The default value is 1% of the total supply. | |
| * | |
| * NOTE: set the value to `TOTAL_SUPPLY` to have an unlimited max, i.e. | |
| * `maxTransactionAmount = TOTAL_SUPPLY;` | |
| */ | |
| uint256 internal constant maxTransactionAmount = TOTAL_SUPPLY / 100; // 1% of the total supply | |
| /** | |
| * @dev Set the maximum allowed balance in a wallet. | |
| * | |
| * The default value is 2% of the total supply. | |
| * | |
| * NOTE: set the value to 0 to have an unlimited max. | |
| * | |
| * ////IMPORTANT: This value MUST be greater than `numberOfTokensToSwapToLiquidity` set below, | |
| * otherwise the liquidity swap will never be executed | |
| */ | |
| uint256 internal constant maxWalletBalance = TOTAL_SUPPLY / 50; // 2% of the total supply | |
| /** | |
| * @dev Set the number of tokens to swap and add to liquidity. | |
| * | |
| * Whenever the contract's balance reaches this number of tokens, swap & liquify will be | |
| * executed in the very next transfer (via the `_beforeTokenTransfer`) | |
| * | |
| * If the `FeeType.Liquidity` is enabled in `FeesSettings`, the given % of each transaction will be first | |
| * sent to the contract address. Once the contract's balance reaches `numberOfTokensToSwapToLiquidity` the | |
| * `swapAndLiquify` of `Liquifier` will be executed. Half of the tokens will be swapped for ETH | |
| * (or BNB on BSC) and together with the other half converted into a Token-ETH/Token-BNB LP Token. | |
| * | |
| * See: `Liquifier` | |
| */ | |
| uint256 internal constant numberOfTokensToSwapToLiquidity = | |
| TOTAL_SUPPLY / 1000; // 0.1% of the total supply | |
| // --------------------- Fees Settings ------------------- // | |
| /** | |
| * @dev To add/edit/remove fees scroll down to the `addFees` function below | |
| */ | |
| address internal charityAddress = | |
| 0x3De92b2308f4acBA823fA58A0C02633380d570eE; | |
| address internal marketingAddress = | |
| 0x65b4eF486971839517d6FF08Af90fD69F26FbB1B; | |
| /** | |
| * @dev You can change the value of the burn address to pretty much anything | |
| * that's (clearly) a non-random address, i.e. for which the probability of | |
| * someone having the private key is (virtually) 0. For example, 0x00.....1, | |
| * 0x111...111, 0x12345.....12345, etc. | |
| * | |
| * NOTE: This does NOT need to be the zero address, adress(0) = 0x000...000; | |
| * | |
| * Trasfering tokens to the burn address is good for optics/marketing. Nevertheless | |
| * if the burn address is excluded from rewards (unlike in Safemoon), sending tokens | |
| * to the burn address actually improves redistribution to holders (as they will | |
| * have a larger % of tokens in non-excluded accounts) | |
| * | |
| * p.s. the address below is the speed of light in vacuum in m/s (expressed in decimals), | |
| * the hex value is 0x0000000000000000000000000000000011dE784A; :) | |
| * | |
| * Here are the values of some other fundamental constants to use: | |
| * 0x0000000000000000000000000000000602214076 (Avogardo constant) | |
| * 0x0000000000000000000000000000000001380649 (Boltzmann constant) | |
| * 0x2718281828459045235360287471352662497757 (e) | |
| * 0x0000000000000000000000000000001602176634 (elementary charge) | |
| * 0x0000000000000000000000000200231930436256 (electron g-factor) | |
| * 0x0000000000000000000000000000091093837015 (electron mass) | |
| * 0x0000000000000000000000000000137035999084 (fine structure constant) | |
| * 0x0577215664901532860606512090082402431042 (Euler-Mascheroni constant) | |
| * 0x1618033988749894848204586834365638117720 (golden ratio) | |
| * 0x0000000000000000000000000000009192631770 (hyperfine transition fq) | |
| * 0x0000000000000000000000000000010011659208 (muom g-2) | |
| * 0x3141592653589793238462643383279502884197 (pi) | |
| * 0x0000000000000000000000000000000662607015 (Planck's constant) | |
| * 0x0000000000000000000000000000001054571817 (reduced Planck's constant) | |
| * 0x1414213562373095048801688724209698078569 (sqrt(2)) | |
| */ | |
| address internal burnAddress = 0x0000000000000000000000000000000299792458; | |
| enum FeeType {Antiwhale, Burn, Liquidity, Rfi, External, ExternalToETH} | |
| struct Fee { | |
| FeeType name; | |
| uint256 value; | |
| address recipient; | |
| uint256 total; | |
| } | |
| Fee[] internal fees; | |
| uint256 internal sumOfFees; | |
| constructor() { | |
| _addFees(); | |
| } | |
| function _addFee( | |
| FeeType name, | |
| uint256 value, | |
| address recipient | |
| ) private { | |
| fees.push(Fee(name, value, recipient, 0)); | |
| sumOfFees += value; | |
| } | |
| function _addFees() private { | |
| /** | |
| * The RFI recipient is ignored but we need to give a valid address value | |
| * | |
| * CAUTION: If you don't want to use RFI this implementation isn't really for you! | |
| * There are much more efficient and cleaner token contracts without RFI | |
| * so you should use one of those | |
| * | |
| * The value of fees is given in part per 1000 (based on the value of FEES_DIVISOR), | |
| * e.g. for 5% use 50, for 3.5% use 35, etc. | |
| */ | |
| _addFee(FeeType.Rfi, 50, address(this)); | |
| // _addFee(FeeType.Burn, 10, burnAddress); | |
| _addFee(FeeType.Liquidity, 50, address(this)); | |
| // _addFee(FeeType.External, 20, charityAddress); | |
| // _addFee(FeeType.External, 30, marketingAddress); | |
| } | |
| function _getFeesCount() internal view returns (uint256) { | |
| return fees.length; | |
| } | |
| function _getFeeStruct(uint256 index) private view returns (Fee storage) { | |
| require( | |
| index >= 0 && index < fees.length, | |
| "FeesSettings._getFeeStruct: Fee index out of bounds" | |
| ); | |
| return fees[index]; | |
| } | |
| function _getFee(uint256 index) | |
| internal | |
| view | |
| returns ( | |
| FeeType, | |
| uint256, | |
| address, | |
| uint256 | |
| ) | |
| { | |
| Fee memory fee = _getFeeStruct(index); | |
| return (fee.name, fee.value, fee.recipient, fee.total); | |
| } | |
| function _addFeeCollectedAmount(uint256 index, uint256 amount) internal { | |
| Fee storage fee = _getFeeStruct(index); | |
| fee.total = fee.total.add(amount); | |
| } | |
| // function getCollectedFeeTotal(uint256 index) external view returns (uint256){ | |
| function getCollectedFeeTotal(uint256 index) | |
| internal | |
| view | |
| returns (uint256) | |
| { | |
| Fee memory fee = _getFeeStruct(index); | |
| return fee.total; | |
| } | |
| } | |
| abstract contract Presaleable is Manageable { | |
| bool internal isInPresale; | |
| function setPreseableEnabled(bool value) external onlyManager { | |
| isInPresale = value; | |
| } | |
| } | |
| abstract contract BaseRfiToken is | |
| IERC20, | |
| IERC20Metadata, | |
| Ownable, | |
| Presaleable, | |
| Tokenomics | |
| { | |
| using SafeMath for uint256; | |
| using Address for address; | |
| mapping(address => uint256) internal _reflectedBalances; | |
| mapping(address => uint256) internal _balances; | |
| mapping(address => mapping(address => uint256)) internal _allowances; | |
| mapping(address => bool) internal _isExcludedFromFee; | |
| mapping(address => bool) internal _isExcludedFromRewards; | |
| address[] private _excluded; | |
| constructor() { | |
| _reflectedBalances[owner()] = _reflectedSupply; | |
| // exclude owner and this contract from fee | |
| _isExcludedFromFee[owner()] = true; | |
| _isExcludedFromFee[address(this)] = true; | |
| // exclude the owner and this contract from rewards | |
| _exclude(owner()); | |
| _exclude(address(this)); | |
| emit Transfer(address(0), owner(), TOTAL_SUPPLY); | |
| } | |
| /** Functions required by IERC20Metadat **/ | |
| function name() external pure override returns (string memory) { | |
| return NAME; | |
| } | |
| function symbol() external pure override returns (string memory) { | |
| return SYMBOL; | |
| } | |
| function decimals() external pure override returns (uint8) { | |
| return DECIMALS; | |
| } | |
| /** Functions required by IERC20Metadat - END **/ | |
| /** Functions required by IERC20 **/ | |
| function totalSupply() external pure override returns (uint256) { | |
| return TOTAL_SUPPLY; | |
| } | |
| function balanceOf(address account) public view override returns (uint256) { | |
| if (_isExcludedFromRewards[account]) return _balances[account]; | |
| return tokenFromReflection(_reflectedBalances[account]); | |
| } | |
| function transfer(address recipient, uint256 amount) | |
| external | |
| override | |
| returns (bool) | |
| { | |
| _transfer(_msgSender(), recipient, amount); | |
| return true; | |
| } | |
| function allowance(address owner, address spender) | |
| external | |
| view | |
| override | |
| returns (uint256) | |
| { | |
| return _allowances[owner][spender]; | |
| } | |
| function approve(address spender, uint256 amount) | |
| external | |
| override | |
| returns (bool) | |
| { | |
| _approve(_msgSender(), spender, amount); | |
| return true; | |
| } | |
| function transferFrom( | |
| address sender, | |
| address recipient, | |
| uint256 amount | |
| ) external override returns (bool) { | |
| _transfer(sender, recipient, amount); | |
| _approve( | |
| sender, | |
| _msgSender(), | |
| _allowances[sender][_msgSender()].sub( | |
| amount, | |
| "ERC20: transfer amount exceeds allowance" | |
| ) | |
| ); | |
| return true; | |
| } | |
| /** Functions required by IERC20 - END **/ | |
| /** | |
| * @dev this is really a "soft" burn (total supply is not reduced). RFI holders | |
| * get two benefits from burning tokens: | |
| * | |
| * 1) Tokens in the burn address increase the % of tokens held by holders not | |
| * excluded from rewards (assuming the burn address is excluded) | |
| * 2) Tokens in the burn address cannot be sold (which in turn draing the | |
| * liquidity pool) | |
| * | |
| * | |
| * In RFI holders already get % of each transaction so the value of their tokens | |
| * increases (in a way). Therefore there is really no need to do a "hard" burn | |
| * (reduce the total supply). What matters (in RFI) is to make sure that a large | |
| * amount of tokens cannot be sold = draining the liquidity pool = lowering the | |
| * value of tokens holders own. For this purpose, transfering tokens to a (vanity) | |
| * burn address is the most appropriate way to "burn". | |
| * | |
| * There is an extra check placed into the `transfer` function to make sure the | |
| * burn address cannot withdraw the tokens is has (although the chance of someone | |
| * having/finding the private key is virtually zero). | |
| */ | |
| function burn(uint256 amount) external { | |
| address sender = _msgSender(); | |
| require( | |
| sender != address(0), | |
| "BaseRfiToken: burn from the zero address" | |
| ); | |
| require( | |
| sender != address(burnAddress), | |
| "BaseRfiToken: burn from the burn address" | |
| ); | |
| uint256 balance = balanceOf(sender); | |
| require(balance >= amount, "BaseRfiToken: burn amount exceeds balance"); | |
| uint256 reflectedAmount = amount.mul(_getCurrentRate()); | |
| // remove the amount from the sender's balance first | |
| _reflectedBalances[sender] = _reflectedBalances[sender].sub( | |
| reflectedAmount | |
| ); | |
| if (_isExcludedFromRewards[sender]) | |
| _balances[sender] = _balances[sender].sub(amount); | |
| _burnTokens(sender, amount, reflectedAmount); | |
| } | |
| /** | |
| * @dev "Soft" burns the specified amount of tokens by sending them | |
| * to the burn address | |
| */ | |
| function _burnTokens( | |
| address sender, | |
| uint256 tBurn, | |
| uint256 rBurn | |
| ) internal { | |
| /** | |
| * @dev Do not reduce _totalSupply and/or _reflectedSupply. (soft) burning by sending | |
| * tokens to the burn address (which should be excluded from rewards) is sufficient | |
| * in RFI | |
| */ | |
| _reflectedBalances[burnAddress] = _reflectedBalances[burnAddress].add( | |
| rBurn | |
| ); | |
| if (_isExcludedFromRewards[burnAddress]) | |
| _balances[burnAddress] = _balances[burnAddress].add(tBurn); | |
| /** | |
| * @dev Emit the event so that the burn address balance is updated (on bscscan) | |
| */ | |
| emit Transfer(sender, burnAddress, tBurn); | |
| } | |
| function increaseAllowance(address spender, uint256 addedValue) | |
| public | |
| virtual | |
| returns (bool) | |
| { | |
| _approve( | |
| _msgSender(), | |
| spender, | |
| _allowances[_msgSender()][spender].add(addedValue) | |
| ); | |
| return true; | |
| } | |
| 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; | |
| } | |
| function isExcludedFromReward(address account) | |
| external | |
| view | |
| returns (bool) | |
| { | |
| return _isExcludedFromRewards[account]; | |
| } | |
| /** | |
| * @dev Calculates and returns the reflected amount for the given amount with or without | |
| * the transfer fees (deductTransferFee true/false) | |
| */ | |
| function reflectionFromToken(uint256 tAmount, bool deductTransferFee) | |
| external | |
| view | |
| returns (uint256) | |
| { | |
| require(tAmount <= TOTAL_SUPPLY, "Amount must be less than supply"); | |
| if (!deductTransferFee) { | |
| (uint256 rAmount, , , , ) = _getValues(tAmount, 0); | |
| return rAmount; | |
| } else { | |
| (, uint256 rTransferAmount, , , ) = | |
| _getValues(tAmount, _getSumOfFees(_msgSender(), tAmount)); | |
| return rTransferAmount; | |
| } | |
| } | |
| /** | |
| * @dev Calculates and returns the amount of tokens corresponding to the given reflected amount. | |
| */ | |
| function tokenFromReflection(uint256 rAmount) | |
| internal | |
| view | |
| returns (uint256) | |
| { | |
| require( | |
| rAmount <= _reflectedSupply, | |
| "Amount must be less than total reflections" | |
| ); | |
| uint256 currentRate = _getCurrentRate(); | |
| return rAmount.div(currentRate); | |
| } | |
| function excludeFromReward(address account) external onlyOwner() { | |
| require(!_isExcludedFromRewards[account], "Account is not included"); | |
| _exclude(account); | |
| } | |
| function _exclude(address account) internal { | |
| if (_reflectedBalances[account] > 0) { | |
| _balances[account] = tokenFromReflection( | |
| _reflectedBalances[account] | |
| ); | |
| } | |
| _isExcludedFromRewards[account] = true; | |
| _excluded.push(account); | |
| } | |
| function includeInReward(address account) external onlyOwner() { | |
| require(_isExcludedFromRewards[account], "Account is not excluded"); | |
| for (uint256 i = 0; i < _excluded.length; i++) { | |
| if (_excluded[i] == account) { | |
| _excluded[i] = _excluded[_excluded.length - 1]; | |
| _balances[account] = 0; | |
| _isExcludedFromRewards[account] = false; | |
| _excluded.pop(); | |
| break; | |
| } | |
| } | |
| } | |
| function setExcludedFromFee(address account, bool value) | |
| external | |
| onlyOwner | |
| { | |
| _isExcludedFromFee[account] = value; | |
| } | |
| function isExcludedFromFee(address account) public view returns (bool) { | |
| return _isExcludedFromFee[account]; | |
| } | |
| function _approve( | |
| address owner, | |
| address spender, | |
| uint256 amount | |
| ) internal { | |
| require( | |
| owner != address(0), | |
| "BaseRfiToken: approve from the zero address" | |
| ); | |
| require( | |
| spender != address(0), | |
| "BaseRfiToken: approve to the zero address" | |
| ); | |
| _allowances[owner][spender] = amount; | |
| emit Approval(owner, spender, amount); | |
| } | |
| /** | |
| */ | |
| function _isUnlimitedSender(address account) internal view returns (bool) { | |
| // the owner should be the only whitelisted sender | |
| return (account == owner()); | |
| } | |
| /** | |
| */ | |
| function _isUnlimitedRecipient(address account) | |
| internal | |
| view | |
| returns (bool) | |
| { | |
| // the owner should be a white-listed recipient | |
| // and anyone should be able to burn as many tokens as | |
| // he/she wants | |
| return (account == owner() || account == burnAddress); | |
| } | |
| function _transfer( | |
| address sender, | |
| address recipient, | |
| uint256 amount | |
| ) private { | |
| require( | |
| sender != address(0), | |
| "BaseRfiToken: transfer from the zero address" | |
| ); | |
| require( | |
| recipient != address(0), | |
| "BaseRfiToken: transfer to the zero address" | |
| ); | |
| require( | |
| sender != address(burnAddress), | |
| "BaseRfiToken: transfer from the burn address" | |
| ); | |
| require(amount > 0, "Transfer amount must be greater than zero"); | |
| // indicates whether or not feee should be deducted from the transfer | |
| bool takeFee = true; | |
| if (isInPresale) { | |
| takeFee = false; | |
| } else { | |
| /** | |
| * Check the amount is within the max allowed limit as long as a | |
| * unlimited sender/recepient is not involved in the transaction | |
| */ | |
| if ( | |
| amount > maxTransactionAmount && | |
| !_isUnlimitedSender(sender) && | |
| !_isUnlimitedRecipient(recipient) | |
| ) { | |
| revert("Transfer amount exceeds the maxTxAmount."); | |
| } | |
| /** | |
| * The pair needs to excluded from the max wallet balance check; | |
| * selling tokens is sending them back to the pair (without this | |
| * check, selling tokens would not work if the pair's balance | |
| * was over the allowed max) | |
| * | |
| * Note: This does NOT take into account the fees which will be deducted | |
| * from the amount. As such it could be a bit confusing | |
| */ | |
| if ( | |
| maxWalletBalance > 0 && | |
| !_isUnlimitedSender(sender) && | |
| !_isUnlimitedRecipient(recipient) && | |
| !_isV2Pair(recipient) | |
| ) { | |
| uint256 recipientBalance = balanceOf(recipient); | |
| require( | |
| recipientBalance + amount <= maxWalletBalance, | |
| "New balance would exceed the maxWalletBalance" | |
| ); | |
| } | |
| } | |
| // if any account belongs to _isExcludedFromFee account then remove the fee | |
| if (_isExcludedFromFee[sender] || _isExcludedFromFee[recipient]) { | |
| takeFee = false; | |
| } | |
| _beforeTokenTransfer(sender, recipient, amount, takeFee); | |
| _transferTokens(sender, recipient, amount, takeFee); | |
| } | |
| function _transferTokens( | |
| address sender, | |
| address recipient, | |
| uint256 amount, | |
| bool takeFee | |
| ) private { | |
| /** | |
| * We don't need to know anything about the individual fees here | |
| * (like Safemoon does with `_getValues`). All that is required | |
| * for the transfer is the sum of all fees to calculate the % of the total | |
| * transaction amount which should be transferred to the recipient. | |
| * | |
| * The `_takeFees` call will/should take care of the individual fees | |
| */ | |
| uint256 sumOfFees = _getSumOfFees(sender, amount); | |
| if (!takeFee) { | |
| sumOfFees = 0; | |
| } | |
| ( | |
| uint256 rAmount, | |
| uint256 rTransferAmount, | |
| uint256 tAmount, | |
| uint256 tTransferAmount, | |
| uint256 currentRate | |
| ) = _getValues(amount, sumOfFees); | |
| /** | |
| * Sender's and Recipient's reflected balances must be always updated regardless of | |
| * whether they are excluded from rewards or not. | |
| */ | |
| _reflectedBalances[sender] = _reflectedBalances[sender].sub(rAmount); | |
| _reflectedBalances[recipient] = _reflectedBalances[recipient].add( | |
| rTransferAmount | |
| ); | |
| /** | |
| * Update the true/nominal balances for excluded accounts | |
| */ | |
| if (_isExcludedFromRewards[sender]) { | |
| _balances[sender] = _balances[sender].sub(tAmount); | |
| } | |
| if (_isExcludedFromRewards[recipient]) { | |
| _balances[recipient] = _balances[recipient].add(tTransferAmount); | |
| } | |
| _takeFees(amount, currentRate, sumOfFees); | |
| emit Transfer(sender, recipient, tTransferAmount); | |
| } | |
| function _takeFees( | |
| uint256 amount, | |
| uint256 currentRate, | |
| uint256 sumOfFees | |
| ) private { | |
| if (sumOfFees > 0 && !isInPresale) { | |
| _takeTransactionFees(amount, currentRate); | |
| } | |
| } | |
| function _getValues(uint256 tAmount, uint256 feesSum) | |
| internal | |
| view | |
| returns ( | |
| uint256, | |
| uint256, | |
| uint256, | |
| uint256, | |
| uint256 | |
| ) | |
| { | |
| uint256 tTotalFees = tAmount.mul(feesSum).div(FEES_DIVISOR); | |
| uint256 tTransferAmount = tAmount.sub(tTotalFees); | |
| uint256 currentRate = _getCurrentRate(); | |
| uint256 rAmount = tAmount.mul(currentRate); | |
| uint256 rTotalFees = tTotalFees.mul(currentRate); | |
| uint256 rTransferAmount = rAmount.sub(rTotalFees); | |
| return ( | |
| rAmount, | |
| rTransferAmount, | |
| tAmount, | |
| tTransferAmount, | |
| currentRate | |
| ); | |
| } | |
| function _getCurrentRate() internal view returns (uint256) { | |
| (uint256 rSupply, uint256 tSupply) = _getCurrentSupply(); | |
| return rSupply.div(tSupply); | |
| } | |
| function _getCurrentSupply() internal view returns (uint256, uint256) { | |
| uint256 rSupply = _reflectedSupply; | |
| uint256 tSupply = TOTAL_SUPPLY; | |
| /** | |
| * The code below removes balances of addresses excluded from rewards from | |
| * rSupply and tSupply, which effectively increases the % of transaction fees | |
| * delivered to non-excluded holders | |
| */ | |
| for (uint256 i = 0; i < _excluded.length; i++) { | |
| if ( | |
| _reflectedBalances[_excluded[i]] > rSupply || | |
| _balances[_excluded[i]] > tSupply | |
| ) return (_reflectedSupply, TOTAL_SUPPLY); | |
| rSupply = rSupply.sub(_reflectedBalances[_excluded[i]]); | |
| tSupply = tSupply.sub(_balances[_excluded[i]]); | |
| } | |
| if (tSupply == 0 || rSupply < _reflectedSupply.div(TOTAL_SUPPLY)) | |
| return (_reflectedSupply, TOTAL_SUPPLY); | |
| return (rSupply, tSupply); | |
| } | |
| /** | |
| * @dev Hook that is called before any transfer of tokens. | |
| */ | |
| function _beforeTokenTransfer( | |
| address sender, | |
| address recipient, | |
| uint256 amount, | |
| bool takeFee | |
| ) internal virtual; | |
| /** | |
| * @dev Returns the total sum of fees to be processed in each transaction. | |
| * | |
| * To separate concerns this contract (class) will take care of ONLY handling RFI, i.e. | |
| * changing the rates and updating the holder's balance (via `_redistribute`). | |
| * It is the responsibility of the dev/user to handle all other fees and taxes | |
| * in the appropriate contracts (classes). | |
| */ | |
| function _getSumOfFees(address sender, uint256 amount) | |
| internal | |
| view | |
| virtual | |
| returns (uint256); | |
| /** | |
| * @dev A delegate which should return true if the given address is the V2 Pair and false otherwise | |
| */ | |
| function _isV2Pair(address account) internal view virtual returns (bool); | |
| /** | |
| * @dev Redistributes the specified amount among the current holders via the reflect.finance | |
| * algorithm, i.e. by updating the _reflectedSupply (_rSupply) which ultimately adjusts the | |
| * current rate used by `tokenFromReflection` and, in turn, the value returns from `balanceOf`. | |
| * This is the bit of clever math which allows rfi to redistribute the fee without | |
| * having to iterate through all holders. | |
| * | |
| * Visit our discord at https://discord.gg/dAmr6eUTpM | |
| */ | |
| function _redistribute( | |
| uint256 amount, | |
| uint256 currentRate, | |
| uint256 fee, | |
| uint256 index | |
| ) internal { | |
| uint256 tFee = amount.mul(fee).div(FEES_DIVISOR); | |
| uint256 rFee = tFee.mul(currentRate); | |
| _reflectedSupply = _reflectedSupply.sub(rFee); | |
| _addFeeCollectedAmount(index, tFee); | |
| } | |
| /** | |
| * @dev Hook that is called before the `Transfer` event is emitted if fees are enabled for the transfer | |
| */ | |
| function _takeTransactionFees(uint256 amount, uint256 currentRate) | |
| internal | |
| virtual; | |
| } | |
| abstract contract Liquifier is Ownable, Manageable { | |
| using SafeMath for uint256; | |
| uint256 private withdrawableBalance; | |
| enum Env {Testnet, MainnetV1, MainnetV2} | |
| Env private _env; | |
| // PancakeSwap V1 | |
| address private _mainnetRouterV1Address = | |
| 0x05fF2B0DB69458A0750badebc4f9e13aDd608C7F; | |
| // PancakeSwap V2 | |
| address private _mainnetRouterV2Address = | |
| 0x10ED43C718714eb63d5aA57B78B54704E256024E; | |
| // Testnet | |
| // address private _testnetRouterAddress = 0xD99D1c33F9fC3444f8101754aBC46c52416550D1; | |
| // PancakeSwap Testnet = https://pancake.kiemtienonline360.com/ | |
| address private _testnetRouterAddress = | |
| 0x9Ac64Cc6e4415144C455BD8E4837Fea55603e5c3; | |
| IPancakeV2Router internal _router; | |
| address internal _pair; | |
| bool private inSwapAndLiquify; | |
| bool private swapAndLiquifyEnabled = true; | |
| uint256 private maxTransactionAmount; | |
| uint256 private numberOfTokensToSwapToLiquidity; | |
| modifier lockTheSwap { | |
| inSwapAndLiquify = true; | |
| _; | |
| inSwapAndLiquify = false; | |
| } | |
| event RouterSet(address indexed router); | |
| event SwapAndLiquify( | |
| uint256 tokensSwapped, | |
| uint256 ethReceived, | |
| uint256 tokensIntoLiquidity | |
| ); | |
| event SwapAndLiquifyEnabledUpdated(bool enabled); | |
| event LiquidityAdded( | |
| uint256 tokenAmountSent, | |
| uint256 ethAmountSent, | |
| uint256 liquidity | |
| ); | |
| receive() external payable {} | |
| function initializeLiquiditySwapper( | |
| Env env, | |
| uint256 maxTx, | |
| uint256 liquifyAmount | |
| ) internal { | |
| _env = env; | |
| if (_env == Env.MainnetV1) { | |
| _setRouterAddress(_mainnetRouterV1Address); | |
| } else if (_env == Env.MainnetV2) { | |
| _setRouterAddress(_mainnetRouterV2Address); | |
| } | |
| /*(_env == Env.Testnet)*/ | |
| else { | |
| _setRouterAddress(_testnetRouterAddress); | |
| } | |
| maxTransactionAmount = maxTx; | |
| numberOfTokensToSwapToLiquidity = liquifyAmount; | |
| } | |
| /** | |
| * NOTE: passing the `contractTokenBalance` here is preferred to creating `balanceOfDelegate` | |
| */ | |
| function liquify(uint256 contractTokenBalance, address sender) internal { | |
| if (contractTokenBalance >= maxTransactionAmount) | |
| contractTokenBalance = maxTransactionAmount; | |
| bool isOverRequiredTokenBalance = | |
| (contractTokenBalance >= numberOfTokensToSwapToLiquidity); | |
| /** | |
| * - first check if the contract has collected enough tokens to swap and liquify | |
| * - then check swap and liquify is enabled | |
| * - then make sure not to get caught in a circular liquidity event | |
| * - finally, don't swap & liquify if the sender is the uniswap pair | |
| */ | |
| if ( | |
| isOverRequiredTokenBalance && | |
| swapAndLiquifyEnabled && | |
| !inSwapAndLiquify && | |
| (sender != _pair) | |
| ) { | |
| // TODO check if the `(sender != _pair)` is necessary because that basically | |
| // stops swap and liquify for all "buy" transactions | |
| _swapAndLiquify(contractTokenBalance); | |
| } | |
| } | |
| /** | |
| * @dev sets the router address and created the router, factory pair to enable | |
| * swapping and liquifying (contract) tokens | |
| */ | |
| function _setRouterAddress(address router) private { | |
| IPancakeV2Router _newPancakeRouter = IPancakeV2Router(router); | |
| _pair = IPancakeV2Factory(_newPancakeRouter.factory()).createPair( | |
| address(this), | |
| _newPancakeRouter.WETH() | |
| ); | |
| _router = _newPancakeRouter; | |
| emit RouterSet(router); | |
| } | |
| function _swapAndLiquify(uint256 amount) private lockTheSwap { | |
| // split the contract balance into halves | |
| uint256 half = amount.div(2); | |
| uint256 otherHalf = amount.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); // <- 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] = _router.WETH(); | |
| _approveDelegate(address(this), address(_router), tokenAmount); | |
| // make the swap | |
| _router.swapExactTokensForETHSupportingFeeOnTransferTokens( | |
| tokenAmount, | |
| // The minimum amount of output tokens that must be received for the transaction not to revert. | |
| // 0 = accept any amount (slippage is inevitable) | |
| 0, | |
| path, | |
| address(this), | |
| block.timestamp | |
| ); | |
| } | |
| function _addLiquidity(uint256 tokenAmount, uint256 ethAmount) private { | |
| // approve token transfer to cover all possible scenarios | |
| _approveDelegate(address(this), address(_router), tokenAmount); | |
| // add tahe liquidity | |
| (uint256 tokenAmountSent, uint256 ethAmountSent, uint256 liquidity) = | |
| _router.addLiquidityETH{value: ethAmount}( | |
| address(this), | |
| tokenAmount, | |
| // Bounds the extent to which the WETH/token price can go up before the transaction reverts. | |
| // Must be <= amountTokenDesired; 0 = accept any amount (slippage is inevitable) | |
| 0, | |
| // Bounds the extent to which the token/WETH price can go up before the transaction reverts. | |
| // 0 = accept any amount (slippage is inevitable) | |
| 0, | |
| // this is a centralized risk if the owner's account is ever compromised (see Certik SSL-04) | |
| owner(), | |
| block.timestamp | |
| ); | |
| // fix the forever locked BNBs as per the certik's audit | |
| /** | |
| * The swapAndLiquify function converts half of the contractTokenBalance SafeMoon tokens to BNB. | |
| * For every swapAndLiquify function call, a small amount of BNB remains in the contract. | |
| * This amount grows over time with the swapAndLiquify function being called throughout the life | |
| * of the contract. The Safemoon contract does not contain a method to withdraw these funds, | |
| * and the BNB will be locked in the Safemoon contract forever. | |
| */ | |
| withdrawableBalance = address(this).balance; | |
| emit LiquidityAdded(tokenAmountSent, ethAmountSent, liquidity); | |
| } | |
| /** | |
| * @dev Sets the uniswapV2 pair (router & factory) for swapping and liquifying tokens | |
| */ | |
| function setRouterAddress(address router) external onlyManager() { | |
| _setRouterAddress(router); | |
| } | |
| /** | |
| * @dev Sends the swap and liquify flag to the provided value. If set to `false` tokens collected in the contract will | |
| * NOT be converted into liquidity. | |
| */ | |
| function setSwapAndLiquifyEnabled(bool enabled) external onlyManager { | |
| swapAndLiquifyEnabled = enabled; | |
| emit SwapAndLiquifyEnabledUpdated(swapAndLiquifyEnabled); | |
| } | |
| /** | |
| * @dev The owner can withdraw ETH(BNB) collected in the contract from `swapAndLiquify` | |
| * or if someone (accidentally) sends ETH/BNB directly to the contract. | |
| * | |
| * Note: This addresses the contract flaw pointed out in the Certik Audit of Safemoon (SSL-03): | |
| * | |
| * The swapAndLiquify function converts half of the contractTokenBalance SafeMoon tokens to BNB. | |
| * For every swapAndLiquify function call, a small amount of BNB remains in the contract. | |
| * This amount grows over time with the swapAndLiquify function being called | |
| * throughout the life of the contract. The Safemoon contract does not contain a method | |
| * to withdraw these funds, and the BNB will be locked in the Safemoon contract forever. | |
| * https://www.certik.org/projects/safemoon | |
| */ | |
| function withdrawLockedEth(address payable recipient) | |
| external | |
| onlyManager() | |
| { | |
| require( | |
| recipient != address(0), | |
| "Cannot withdraw the ETH balance to the zero address" | |
| ); | |
| require( | |
| withdrawableBalance > 0, | |
| "The ETH balance must be greater than 0" | |
| ); | |
| // prevent re-entrancy attacks | |
| uint256 amount = withdrawableBalance; | |
| withdrawableBalance = 0; | |
| recipient.transfer(amount); | |
| } | |
| /** | |
| * @dev Use this delegate instead of having (unnecessarily) extend `BaseRfiToken` to gained access | |
| * to the `_approve` function. | |
| */ | |
| function _approveDelegate( | |
| address owner, | |
| address spender, | |
| uint256 amount | |
| ) internal virtual; | |
| } | |
| ////////////////////////////////////////////////////////////////////////// | |
| abstract contract Antiwhale is Tokenomics { | |
| /** | |
| * @dev Returns the total sum of fees (in percents / per-mille - this depends on the FEES_DIVISOR value) | |
| * | |
| * NOTE: Currently this is just a placeholder. The parameters passed to this function are the | |
| * sender's token balance and the transfer amount. An *antiwhale* mechanics can use these | |
| * values to adjust the fees total for each tx | |
| */ | |
| // function _getAntiwhaleFees(uint256 sendersBalance, uint256 amount) internal view returns (uint256){ | |
| function _getAntiwhaleFees(uint256, uint256) | |
| internal | |
| view | |
| returns (uint256) | |
| { | |
| return sumOfFees; | |
| } | |
| } | |
| ////////////////////////////////////////////////////////////////////////// | |
| abstract contract PokeDX is BaseRfiToken, Liquifier, Antiwhale { | |
| using SafeMath for uint256; | |
| // constructor(string memory _name, string memory _symbol, uint8 _decimals){ | |
| constructor(Env _env) { | |
| initializeLiquiditySwapper( | |
| _env, | |
| maxTransactionAmount, | |
| numberOfTokensToSwapToLiquidity | |
| ); | |
| // exclude the pair address from rewards - we don't want to redistribute | |
| // tx fees to these two; redistribution is only for holders, dah! | |
| _exclude(_pair); | |
| _exclude(burnAddress); | |
| } | |
| function _isV2Pair(address account) internal view override returns (bool) { | |
| return (account == _pair); | |
| } | |
| function _getSumOfFees(address sender, uint256 amount) | |
| internal | |
| view | |
| override | |
| returns (uint256) | |
| { | |
| return _getAntiwhaleFees(balanceOf(sender), amount); | |
| } | |
| // function _beforeTokenTransfer(address sender, address recipient, uint256 amount, bool takeFee) internal override { | |
| function _beforeTokenTransfer( | |
| address sender, | |
| address, | |
| uint256, | |
| bool | |
| ) internal override { | |
| if (!isInPresale) { | |
| uint256 contractTokenBalance = balanceOf(address(this)); | |
| liquify(contractTokenBalance, sender); | |
| } | |
| } | |
| function _takeTransactionFees(uint256 amount, uint256 currentRate) | |
| internal | |
| override | |
| { | |
| if (isInPresale) { | |
| return; | |
| } | |
| uint256 feesCount = _getFeesCount(); | |
| for (uint256 index = 0; index < feesCount; index++) { | |
| (FeeType name, uint256 value, address recipient, ) = _getFee(index); | |
| // no need to check value < 0 as the value is uint (i.e. from 0 to 2^256-1) | |
| if (value == 0) continue; | |
| if (name == FeeType.Rfi) { | |
| _redistribute(amount, currentRate, value, index); | |
| } else if (name == FeeType.Burn) { | |
| _burn(amount, currentRate, value, index); | |
| } else if (name == FeeType.Antiwhale) { | |
| // TODO | |
| } else if (name == FeeType.ExternalToETH) { | |
| _takeFeeToETH(amount, currentRate, value, recipient, index); | |
| } else { | |
| _takeFee(amount, currentRate, value, recipient, index); | |
| } | |
| } | |
| } | |
| function _burn( | |
| uint256 amount, | |
| uint256 currentRate, | |
| uint256 fee, | |
| uint256 index | |
| ) private { | |
| uint256 tBurn = amount.mul(fee).div(FEES_DIVISOR); | |
| uint256 rBurn = tBurn.mul(currentRate); | |
| _burnTokens(address(this), tBurn, rBurn); | |
| _addFeeCollectedAmount(index, tBurn); | |
| } | |
| function _takeFee( | |
| uint256 amount, | |
| uint256 currentRate, | |
| uint256 fee, | |
| address recipient, | |
| uint256 index | |
| ) private { | |
| uint256 tAmount = amount.mul(fee).div(FEES_DIVISOR); | |
| uint256 rAmount = tAmount.mul(currentRate); | |
| _reflectedBalances[recipient] = _reflectedBalances[recipient].add( | |
| rAmount | |
| ); | |
| if (_isExcludedFromRewards[recipient]) | |
| _balances[recipient] = _balances[recipient].add(tAmount); | |
| _addFeeCollectedAmount(index, tAmount); | |
| } | |
| /** | |
| * @dev When implemented this will convert the fee amount of tokens into ETH/BNB | |
| * and send to the recipient's wallet. Note that this reduces liquidity so it | |
| * might be a good idea to add a % into the liquidity fee for % you take our through | |
| * this method (just a suggestions) | |
| */ | |
| function _takeFeeToETH( | |
| uint256 amount, | |
| uint256 currentRate, | |
| uint256 fee, | |
| address recipient, | |
| uint256 index | |
| ) private { | |
| _takeFee(amount, currentRate, fee, recipient, index); | |
| } | |
| function _approveDelegate( | |
| address owner, | |
| address spender, | |
| uint256 amount | |
| ) internal override { | |
| _approve(owner, spender, amount); | |
| } | |
| } | |
| contract PokeDXV1Beta is PokeDX { | |
| constructor() PokeDX(Env.Testnet) { | |
| // pre-approve the initial liquidity supply (to safe a bit of time) | |
| _approve(owner(), address(_router), ~uint256(0)); | |
| } | |
| } | |
| /** | |
| * Todo (beta): | |
| * | |
| * - reorganize the sol file(s) to make put everything editable in a single .sol file | |
| * and keep all other code in other .sol file(s) | |
| * - move variable values initialized in the contract to be constructor parameters | |
| * - add/remove setters/getter where appropriate | |
| * - add unit tests (via ganache-cli + truffle) | |
| * - add full dev evn (truffle) folders & files | |
| * | |
| * Todo: | |
| * | |
| * - implement `_takeFeeToETH` (currently just calls `_takeFee`) | |
| * - implement anti whale mechanics (via different pre-created libraries?), eg progressive tax | |
| * - implement anti sell mechanics | |
| * - address SSL-04 | Centralized risk in addLiquidity - https://www.certik.org/projects/safemoon | |
| * change the recipient to `address(this)` or implement a decentralized mechanism or | |
| * smart-contract solution | |
| * - change Uniswap to PancakeSwap in contract/interface names and local var names | |
| * - change ETH to BNB in names and comments | |
| */ | |
| /** | |
| * Tests to pass: | |
| * | |
| * - Tokenomics fees can be added/removed/edited | |
| * - Tokenomics fees are correctly taken from each (qualifying) transaction | |
| * - The RFI fee is correctly distributed among holders (which are not excluded from rewards) | |
| * - `swapAndLiquify` works correctly when the threshold balance is reached | |
| * - `maxTransactionAmount` works correctly and *unlimited* accounts are not subject to the limit | |
| * - `maxWalletBalance` works correctly and *unlimited* accounts are not subject to the limit | |
| * - accounts excluded from fees are not subject to tx fees | |
| * - accounts excluded from rewards do not share in rewards | |
| * - ETH/BNB collected/stuck in the contract can be withdrawn (see) | |
| */ | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * SPDX-License-Identifier: MIT | |
| */ | |
| pragma solidity ^0.8.4; | |
| interface IERC20 { | |
| function totalSupply() external view returns (uint256); | |
| function balanceOf(address account) external view returns (uint256); | |
| function transfer(address recipient, uint256 amount) external returns (bool); | |
| function allowance(address owner, address spender) external view returns (uint256); | |
| function approve(address spender, uint256 amount) external returns (bool); | |
| function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); | |
| event Transfer(address indexed from, address indexed to, uint256 value); | |
| event Approval(address indexed owner, address indexed spender, uint256 value); | |
| } | |
| interface IERC20Metadata is IERC20 { | |
| function name() external view returns (string memory); | |
| function symbol() external view returns (string memory); | |
| function decimals() external view returns (uint8); | |
| } | |
| abstract contract Context { | |
| function _msgSender() internal view virtual returns (address) {return msg.sender;} | |
| function _msgData() internal view virtual returns (bytes calldata) {this; return msg.data;} | |
| } | |
| library SafeMath { | |
| function add(uint256 a, uint256 b) internal pure returns (uint256) {return a + b;} | |
| function sub(uint256 a, uint256 b) internal pure returns (uint256) {return a - b;} | |
| function mul(uint256 a, uint256 b) internal pure returns (uint256) {return a * b;} | |
| function div(uint256 a, uint256 b) internal pure returns (uint256) {return a / b;} | |
| function mod(uint256 a, uint256 b) internal pure returns (uint256) {return a % b;} | |
| function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
| unchecked { require(b <= a, errorMessage); return a - b; } | |
| } | |
| } | |
| library Address { | |
| function isContract(address account) internal view returns (bool) { uint256 size; assembly { size := extcodesize(account) } return size > 0;} | |
| function sendValue(address payable 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"); | |
| } | |
| function functionCall(address target, bytes memory data) internal returns (bytes memory) {return functionCall(target, data, "Address: low-level call failed");} | |
| function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {return functionCallWithValue(target, data, 0, errorMessage);} | |
| function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {return functionCallWithValue(target, data, value, "Address: low-level call with value failed");} | |
| function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { | |
| require(address(this).balance >= value, "Address: insufficient balance for call"); | |
| require(isContract(target), "Address: call to non-contract"); | |
| (bool success, bytes memory returndata) = target.call{ value: value }(data); | |
| return _verifyCallResult(success, returndata, errorMessage); | |
| } | |
| function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { | |
| return functionStaticCall(target, data, "Address: low-level static call failed"); | |
| } | |
| function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) { | |
| require(isContract(target), "Address: static call to non-contract"); | |
| (bool success, bytes memory returndata) = target.staticcall(data); | |
| return _verifyCallResult(success, returndata, errorMessage); | |
| } | |
| function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { | |
| return functionDelegateCall(target, data, "Address: low-level delegate call failed"); | |
| } | |
| function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { | |
| require(isContract(target), "Address: delegate call to non-contract"); | |
| (bool success, bytes memory returndata) = target.delegatecall(data); | |
| return _verifyCallResult(success, returndata, errorMessage); | |
| } | |
| function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) { | |
| if (success) { return returndata; } else { | |
| if (returndata.length > 0) { | |
| assembly { | |
| let returndata_size := mload(returndata) | |
| revert(add(32, returndata), returndata_size) | |
| } | |
| } else {revert(errorMessage);} | |
| } | |
| } | |
| } | |
| abstract contract Ownable is Context { | |
| address private _owner; | |
| address private _previousOwner; | |
| uint256 private _lockTime; | |
| event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); | |
| constructor () { | |
| address msgSender = _msgSender(); | |
| _owner = msgSender; | |
| emit OwnershipTransferred(address(0), msgSender); | |
| } | |
| function owner() public view returns (address) { | |
| return _owner; | |
| } | |
| modifier onlyOwner() { | |
| require(_owner == _msgSender(), "Ownable: caller is not the owner"); | |
| _; | |
| } | |
| function renounceOwnership() public virtual onlyOwner { | |
| emit OwnershipTransferred(_owner, address(0)); | |
| _owner = address(0); | |
| } | |
| function transferOwnership(address newOwner) public virtual onlyOwner { | |
| require(newOwner != address(0), "Ownable: new owner is the zero address"); | |
| emit OwnershipTransferred(_owner, newOwner); | |
| _owner = newOwner; | |
| } | |
| function getUnlockTime() public view returns (uint256) { | |
| return _lockTime; | |
| } | |
| function lock(uint256 time) public virtual onlyOwner { | |
| _previousOwner = _owner; | |
| _owner = address(0); | |
| _lockTime = block.timestamp + time; | |
| emit OwnershipTransferred(_owner, address(0)); | |
| } | |
| function unlock() public virtual { | |
| require(_previousOwner == msg.sender, "Only the previous owner can unlock onwership"); | |
| require(block.timestamp > _lockTime , "The contract is still locked"); | |
| emit OwnershipTransferred(_owner, _previousOwner); | |
| _owner = _previousOwner; | |
| } | |
| } | |
| abstract contract Manageable is Context { | |
| address private _manager; | |
| event ManagementTransferred(address indexed previousManager, address indexed newManager); | |
| constructor(){ | |
| address msgSender = _msgSender(); | |
| _manager = msgSender; | |
| emit ManagementTransferred(address(0), msgSender); | |
| } | |
| function manager() public view returns(address){ return _manager; } | |
| modifier onlyManager(){ | |
| require(_manager == _msgSender(), "Manageable: caller is not the manager"); | |
| _; | |
| } | |
| function transferManagement(address newManager) external virtual onlyManager { | |
| emit ManagementTransferred(_manager, newManager); | |
| _manager = newManager; | |
| } | |
| } | |
| interface IPancakeV2Factory { | |
| event PairCreated(address indexed token0, address indexed token1, address pair, uint); | |
| function createPair(address tokenA, address tokenB) external returns (address pair); | |
| } | |
| interface IPancakeV2Router { | |
| function factory() external pure returns (address); | |
| function WETH() external pure returns (address); | |
| function addLiquidityETH( | |
| address token, | |
| uint amountTokenDesired, | |
| uint amountTokenMin, | |
| uint amountETHMin, | |
| address to, | |
| uint deadline | |
| ) external payable returns (uint amountToken, uint amountETH, uint liquidity); | |
| function swapExactTokensForETHSupportingFeeOnTransferTokens( | |
| uint amountIn, | |
| uint amountOutMin, | |
| address[] calldata path, | |
| address to, | |
| uint deadline | |
| ) external; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * author: | |
| * discord: | |
| * telegram: | |
| * website: | |
| * twitter: | |
| * PokeDX v0.01 | |
| * | |
| * This is a rewrite of Safeoon & S@fetoken in the hope to: | |
| * | |
| * - make it easier to change the tokenomics | |
| * - make it easier to maintain the code and develop it further | |
| * - remove redundant code | |
| * - fix some of the issues reported in the Safemoon audit (e.g. SSL-03) | |
| * https://www.certik.org/projects/safemoon | |
| * | |
| * | |
| * | |
| * __/\\\\\\\\\\\\\___ _______/\\\\\______ __/\\\________/\\\_ __/\\\\\\\\\\\\\\\_ __/\\\\\\\\\\\\____ __/\\\_______/\\\_ | |
| * _\/\\\/////////\\\_ _____/\\\///\\\____ _\/\\\_____/\\\//__ _\/\\\///////////__ _\/\\\////////\\\__ _\///\\\___/\\\/__ | |
| * _\/\\\_______\/\\\_ ___/\\\/__\///\\\__ _\/\\\__/\\\//_____ _\/\\\_____________ _\/\\\______\//\\\_ ___\///\\\\\\/____ | |
| * _\/\\\\\\\\\\\\\/__ __/\\\______\//\\\_ _\/\\\\\\//\\\_____ _\/\\\\\\\\\\\_____ _\/\\\_______\/\\\_ _____\//\\\\______ | |
| * _\/\\\/////////____ _\/\\\_______\/\\\_ _\/\\\//_\//\\\____ _\/\\\///////______ _\/\\\_______\/\\\_ ______\/\\\\______ | |
| * _\/\\\_____________ _\//\\\______/\\\__ _\/\\\____\//\\\___ _\/\\\_____________ _\/\\\_______\/\\\_ ______/\\\\\\_____ | |
| * _\/\\\_____________ __\///\\\__/\\\____ _\/\\\_____\//\\\__ _\/\\\_____________ _\/\\\_______/\\\__ ____/\\\////\\\___ | |
| * _\/\\\_____________ ____\///\\\\\/_____ _\/\\\______\//\\\_ _\/\\\\\\\\\\\\\\\_ _\/\\\\\\\\\\\\/___ __/\\\/___\///\\\_ | |
| * _\///______________ ______\/////_______ _\///________\///__ _\///////////////__ _\////////////_____ _\///_______\///__ | |
| */ | |
| // SPDX-License-Identifier: Unlicensed | |
| pragma solidity ^0.8.4; | |
| /** | |
| * Tokenomics: | |
| * | |
| * Liquidity 5% | |
| * Redistribution 4% | |
| * Burn 1% | |
| * Charity 2% | |
| * Marketing 3% | |
| * Tip to the Dev 0.1% | |
| */ | |
| import "./pokedx-token-imports.sol"; | |
| abstract contract Tokenomics { | |
| using SafeMath for uint256; | |
| // --------------------- Token Settings ------------------- // | |
| string internal constant NAME = "PokeDX.v0.01"; | |
| string internal constant SYMBOL = "PKDX.v0.01"; | |
| uint16 internal constant FEES_DIVISOR = 10**3; | |
| uint8 internal constant DECIMALS = 18; | |
| uint256 internal constant ZEROES = 10**DECIMALS; | |
| uint256 private constant MAX = ~uint256(0); | |
| uint256 internal constant TOTAL_SUPPLY = 23000000 * ZEROES; | |
| uint256 internal _reflectedSupply = (MAX - (MAX % TOTAL_SUPPLY)); | |
| /** | |
| * @dev Set the maximum transaction amount allowed in a transfer. | |
| * | |
| * The default value is 1% of the total supply. | |
| * | |
| * NOTE: set the value to `TOTAL_SUPPLY` to have an unlimited max, i.e. | |
| * `maxTransactionAmount = TOTAL_SUPPLY;` | |
| */ | |
| uint256 internal constant maxTransactionAmount = TOTAL_SUPPLY / 100; // 1% of the total supply | |
| /** | |
| * @dev Set the maximum allowed balance in a wallet. | |
| * | |
| * The default value is 2% of the total supply. | |
| * | |
| * NOTE: set the value to 0 to have an unlimited max. | |
| * | |
| * IMPORTANT: This value MUST be greater than `numberOfTokensToSwapToLiquidity` set below, | |
| * otherwise the liquidity swap will never be executed | |
| */ | |
| uint256 internal constant maxWalletBalance = TOTAL_SUPPLY / 50; // 2% of the total supply | |
| /** | |
| * @dev Set the number of tokens to swap and add to liquidity. | |
| * | |
| * Whenever the contract's balance reaches this number of tokens, swap & liquify will be | |
| * executed in the very next transfer (via the `_beforeTokenTransfer`) | |
| * | |
| * If the `FeeType.Liquidity` is enabled in `FeesSettings`, the given % of each transaction will be first | |
| * sent to the contract address. Once the contract's balance reaches `numberOfTokensToSwapToLiquidity` the | |
| * `swapAndLiquify` of `Liquifier` will be executed. Half of the tokens will be swapped for ETH | |
| * (or BNB on BSC) and together with the other half converted into a Token-ETH/Token-BNB LP Token. | |
| * | |
| * See: `Liquifier` | |
| */ | |
| uint256 internal constant numberOfTokensToSwapToLiquidity = | |
| TOTAL_SUPPLY / 1000; // 0.1% of the total supply | |
| // --------------------- Fees Settings ------------------- // | |
| /** | |
| * @dev To add/edit/remove fees scroll down to the `addFees` function below | |
| */ | |
| address internal charityAddress = | |
| 0x3De92b2308f4acBA823fA58A0C02633380d570eE; | |
| address internal marketingAddress = | |
| 0x65b4eF486971839517d6FF08Af90fD69F26FbB1B; | |
| /** | |
| * @dev You can change the value of the burn address to pretty much anything | |
| * that's (clearly) a non-random address, i.e. for which the probability of | |
| * someone having the private key is (virtually) 0. For example, 0x00.....1, | |
| * 0x111...111, 0x12345.....12345, etc. | |
| * | |
| * NOTE: This does NOT need to be the zero address, adress(0) = 0x000...000; | |
| * | |
| * Trasfering tokens to the burn address is good for optics/marketing. Nevertheless | |
| * if the burn address is excluded from rewards (unlike in Safemoon), sending tokens | |
| * to the burn address actually improves redistribution to holders (as they will | |
| * have a larger % of tokens in non-excluded accounts) | |
| * | |
| * p.s. the address below is the speed of light in vacuum in m/s (expressed in decimals), | |
| * the hex value is 0x0000000000000000000000000000000011dE784A; :) | |
| * | |
| * Here are the values of some other fundamental constants to use: | |
| * 0x0000000000000000000000000000000602214076 (Avogardo constant) | |
| * 0x0000000000000000000000000000000001380649 (Boltzmann constant) | |
| * 0x2718281828459045235360287471352662497757 (e) | |
| * 0x0000000000000000000000000000001602176634 (elementary charge) | |
| * 0x0000000000000000000000000200231930436256 (electron g-factor) | |
| * 0x0000000000000000000000000000091093837015 (electron mass) | |
| * 0x0000000000000000000000000000137035999084 (fine structure constant) | |
| * 0x0577215664901532860606512090082402431042 (Euler-Mascheroni constant) | |
| * 0x1618033988749894848204586834365638117720 (golden ratio) | |
| * 0x0000000000000000000000000000009192631770 (hyperfine transition fq) | |
| * 0x0000000000000000000000000000010011659208 (muom g-2) | |
| * 0x3141592653589793238462643383279502884197 (pi) | |
| * 0x0000000000000000000000000000000662607015 (Planck's constant) | |
| * 0x0000000000000000000000000000001054571817 (reduced Planck's constant) | |
| * 0x1414213562373095048801688724209698078569 (sqrt(2)) | |
| */ | |
| address internal burnAddress = 0x0000000000000000000000000000000299792458; | |
| enum FeeType {Antiwhale, Burn, Liquidity, Rfi, External, ExternalToETH} | |
| struct Fee { | |
| FeeType name; | |
| uint256 value; | |
| address recipient; | |
| uint256 total; | |
| } | |
| Fee[] internal fees; | |
| uint256 internal sumOfFees; | |
| constructor() { | |
| _addFees(); | |
| } | |
| function _addFee( | |
| FeeType name, | |
| uint256 value, | |
| address recipient | |
| ) private { | |
| fees.push(Fee(name, value, recipient, 0)); | |
| sumOfFees += value; | |
| } | |
| function _addFees() private { | |
| /** | |
| * The RFI recipient is ignored but we need to give a valid address value | |
| * | |
| * CAUTION: If you don't want to use RFI this implementation isn't really for you! | |
| * There are much more efficient and cleaner token contracts without RFI | |
| * so you should use one of those | |
| * | |
| * The value of fees is given in part per 1000 (based on the value of FEES_DIVISOR), | |
| * e.g. for 5% use 50, for 3.5% use 35, etc. | |
| */ | |
| _addFee(FeeType.Rfi, 50, address(this)); | |
| // _addFee(FeeType.Burn, 10, burnAddress); | |
| _addFee(FeeType.Liquidity, 50, address(this)); | |
| // _addFee(FeeType.External, 20, charityAddress); | |
| // _addFee(FeeType.External, 30, marketingAddress); | |
| } | |
| function _getFeesCount() internal view returns (uint256) { | |
| return fees.length; | |
| } | |
| function _getFeeStruct(uint256 index) private view returns (Fee storage) { | |
| require( | |
| index >= 0 && index < fees.length, | |
| "FeesSettings._getFeeStruct: Fee index out of bounds" | |
| ); | |
| return fees[index]; | |
| } | |
| function _getFee(uint256 index) | |
| internal | |
| view | |
| returns ( | |
| FeeType, | |
| uint256, | |
| address, | |
| uint256 | |
| ) | |
| { | |
| Fee memory fee = _getFeeStruct(index); | |
| return (fee.name, fee.value, fee.recipient, fee.total); | |
| } | |
| function _addFeeCollectedAmount(uint256 index, uint256 amount) internal { | |
| Fee storage fee = _getFeeStruct(index); | |
| fee.total = fee.total.add(amount); | |
| } | |
| // function getCollectedFeeTotal(uint256 index) external view returns (uint256){ | |
| function getCollectedFeeTotal(uint256 index) | |
| internal | |
| view | |
| returns (uint256) | |
| { | |
| Fee memory fee = _getFeeStruct(index); | |
| return fee.total; | |
| } | |
| } | |
| abstract contract Presaleable is Manageable { | |
| bool internal isInPresale; | |
| function setPreseableEnabled(bool value) external onlyManager { | |
| isInPresale = value; | |
| } | |
| } | |
| abstract contract BaseRfiToken is | |
| IERC20, | |
| IERC20Metadata, | |
| Ownable, | |
| Presaleable, | |
| Tokenomics | |
| { | |
| using SafeMath for uint256; | |
| using Address for address; | |
| mapping(address => uint256) internal _reflectedBalances; | |
| mapping(address => uint256) internal _balances; | |
| mapping(address => mapping(address => uint256)) internal _allowances; | |
| mapping(address => bool) internal _isExcludedFromFee; | |
| mapping(address => bool) internal _isExcludedFromRewards; | |
| address[] private _excluded; | |
| constructor() { | |
| _reflectedBalances[owner()] = _reflectedSupply; | |
| // exclude owner and this contract from fee | |
| _isExcludedFromFee[owner()] = true; | |
| _isExcludedFromFee[address(this)] = true; | |
| // exclude the owner and this contract from rewards | |
| _exclude(owner()); | |
| _exclude(address(this)); | |
| emit Transfer(address(0), owner(), TOTAL_SUPPLY); | |
| } | |
| /** Functions required by IERC20Metadat **/ | |
| function name() external pure override returns (string memory) { | |
| return NAME; | |
| } | |
| function symbol() external pure override returns (string memory) { | |
| return SYMBOL; | |
| } | |
| function decimals() external pure override returns (uint8) { | |
| return DECIMALS; | |
| } | |
| /** Functions required by IERC20Metadat - END **/ | |
| /** Functions required by IERC20 **/ | |
| function totalSupply() external pure override returns (uint256) { | |
| return TOTAL_SUPPLY; | |
| } | |
| function balanceOf(address account) public view override returns (uint256) { | |
| if (_isExcludedFromRewards[account]) return _balances[account]; | |
| return tokenFromReflection(_reflectedBalances[account]); | |
| } | |
| function transfer(address recipient, uint256 amount) | |
| external | |
| override | |
| returns (bool) | |
| { | |
| _transfer(_msgSender(), recipient, amount); | |
| return true; | |
| } | |
| function allowance(address owner, address spender) | |
| external | |
| view | |
| override | |
| returns (uint256) | |
| { | |
| return _allowances[owner][spender]; | |
| } | |
| function approve(address spender, uint256 amount) | |
| external | |
| override | |
| returns (bool) | |
| { | |
| _approve(_msgSender(), spender, amount); | |
| return true; | |
| } | |
| function transferFrom( | |
| address sender, | |
| address recipient, | |
| uint256 amount | |
| ) external override returns (bool) { | |
| _transfer(sender, recipient, amount); | |
| _approve( | |
| sender, | |
| _msgSender(), | |
| _allowances[sender][_msgSender()].sub( | |
| amount, | |
| "ERC20: transfer amount exceeds allowance" | |
| ) | |
| ); | |
| return true; | |
| } | |
| /** Functions required by IERC20 - END **/ | |
| /** | |
| * @dev this is really a "soft" burn (total supply is not reduced). RFI holders | |
| * get two benefits from burning tokens: | |
| * | |
| * 1) Tokens in the burn address increase the % of tokens held by holders not | |
| * excluded from rewards (assuming the burn address is excluded) | |
| * 2) Tokens in the burn address cannot be sold (which in turn draing the | |
| * liquidity pool) | |
| * | |
| * | |
| * In RFI holders already get % of each transaction so the value of their tokens | |
| * increases (in a way). Therefore there is really no need to do a "hard" burn | |
| * (reduce the total supply). What matters (in RFI) is to make sure that a large | |
| * amount of tokens cannot be sold = draining the liquidity pool = lowering the | |
| * value of tokens holders own. For this purpose, transfering tokens to a (vanity) | |
| * burn address is the most appropriate way to "burn". | |
| * | |
| * There is an extra check placed into the `transfer` function to make sure the | |
| * burn address cannot withdraw the tokens is has (although the chance of someone | |
| * having/finding the private key is virtually zero). | |
| */ | |
| function burn(uint256 amount) external { | |
| address sender = _msgSender(); | |
| require( | |
| sender != address(0), | |
| "BaseRfiToken: burn from the zero address" | |
| ); | |
| require( | |
| sender != address(burnAddress), | |
| "BaseRfiToken: burn from the burn address" | |
| ); | |
| uint256 balance = balanceOf(sender); | |
| require(balance >= amount, "BaseRfiToken: burn amount exceeds balance"); | |
| uint256 reflectedAmount = amount.mul(_getCurrentRate()); | |
| // remove the amount from the sender's balance first | |
| _reflectedBalances[sender] = _reflectedBalances[sender].sub( | |
| reflectedAmount | |
| ); | |
| if (_isExcludedFromRewards[sender]) | |
| _balances[sender] = _balances[sender].sub(amount); | |
| _burnTokens(sender, amount, reflectedAmount); | |
| } | |
| /** | |
| * @dev "Soft" burns the specified amount of tokens by sending them | |
| * to the burn address | |
| */ | |
| function _burnTokens( | |
| address sender, | |
| uint256 tBurn, | |
| uint256 rBurn | |
| ) internal { | |
| /** | |
| * @dev Do not reduce _totalSupply and/or _reflectedSupply. (soft) burning by sending | |
| * tokens to the burn address (which should be excluded from rewards) is sufficient | |
| * in RFI | |
| */ | |
| _reflectedBalances[burnAddress] = _reflectedBalances[burnAddress].add( | |
| rBurn | |
| ); | |
| if (_isExcludedFromRewards[burnAddress]) | |
| _balances[burnAddress] = _balances[burnAddress].add(tBurn); | |
| /** | |
| * @dev Emit the event so that the burn address balance is updated (on bscscan) | |
| */ | |
| emit Transfer(sender, burnAddress, tBurn); | |
| } | |
| function increaseAllowance(address spender, uint256 addedValue) | |
| public | |
| virtual | |
| returns (bool) | |
| { | |
| _approve( | |
| _msgSender(), | |
| spender, | |
| _allowances[_msgSender()][spender].add(addedValue) | |
| ); | |
| return true; | |
| } | |
| 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; | |
| } | |
| function isExcludedFromReward(address account) | |
| external | |
| view | |
| returns (bool) | |
| { | |
| return _isExcludedFromRewards[account]; | |
| } | |
| /** | |
| * @dev Calculates and returns the reflected amount for the given amount with or without | |
| * the transfer fees (deductTransferFee true/false) | |
| */ | |
| function reflectionFromToken(uint256 tAmount, bool deductTransferFee) | |
| external | |
| view | |
| returns (uint256) | |
| { | |
| require(tAmount <= TOTAL_SUPPLY, "Amount must be less than supply"); | |
| if (!deductTransferFee) { | |
| (uint256 rAmount, , , , ) = _getValues(tAmount, 0); | |
| return rAmount; | |
| } else { | |
| (, uint256 rTransferAmount, , , ) = | |
| _getValues(tAmount, _getSumOfFees(_msgSender(), tAmount)); | |
| return rTransferAmount; | |
| } | |
| } | |
| /** | |
| * @dev Calculates and returns the amount of tokens corresponding to the given reflected amount. | |
| */ | |
| function tokenFromReflection(uint256 rAmount) | |
| internal | |
| view | |
| returns (uint256) | |
| { | |
| require( | |
| rAmount <= _reflectedSupply, | |
| "Amount must be less than total reflections" | |
| ); | |
| uint256 currentRate = _getCurrentRate(); | |
| return rAmount.div(currentRate); | |
| } | |
| function excludeFromReward(address account) external onlyOwner() { | |
| require(!_isExcludedFromRewards[account], "Account is not included"); | |
| _exclude(account); | |
| } | |
| function _exclude(address account) internal { | |
| if (_reflectedBalances[account] > 0) { | |
| _balances[account] = tokenFromReflection( | |
| _reflectedBalances[account] | |
| ); | |
| } | |
| _isExcludedFromRewards[account] = true; | |
| _excluded.push(account); | |
| } | |
| function includeInReward(address account) external onlyOwner() { | |
| require(_isExcludedFromRewards[account], "Account is not excluded"); | |
| for (uint256 i = 0; i < _excluded.length; i++) { | |
| if (_excluded[i] == account) { | |
| _excluded[i] = _excluded[_excluded.length - 1]; | |
| _balances[account] = 0; | |
| _isExcludedFromRewards[account] = false; | |
| _excluded.pop(); | |
| break; | |
| } | |
| } | |
| } | |
| function setExcludedFromFee(address account, bool value) | |
| external | |
| onlyOwner | |
| { | |
| _isExcludedFromFee[account] = value; | |
| } | |
| function isExcludedFromFee(address account) public view returns (bool) { | |
| return _isExcludedFromFee[account]; | |
| } | |
| function _approve( | |
| address owner, | |
| address spender, | |
| uint256 amount | |
| ) internal { | |
| require( | |
| owner != address(0), | |
| "BaseRfiToken: approve from the zero address" | |
| ); | |
| require( | |
| spender != address(0), | |
| "BaseRfiToken: approve to the zero address" | |
| ); | |
| _allowances[owner][spender] = amount; | |
| emit Approval(owner, spender, amount); | |
| } | |
| /** | |
| */ | |
| function _isUnlimitedSender(address account) internal view returns (bool) { | |
| // the owner should be the only whitelisted sender | |
| return (account == owner()); | |
| } | |
| /** | |
| */ | |
| function _isUnlimitedRecipient(address account) | |
| internal | |
| view | |
| returns (bool) | |
| { | |
| // the owner should be a white-listed recipient | |
| // and anyone should be able to burn as many tokens as | |
| // he/she wants | |
| return (account == owner() || account == burnAddress); | |
| } | |
| function _transfer( | |
| address sender, | |
| address recipient, | |
| uint256 amount | |
| ) private { | |
| require( | |
| sender != address(0), | |
| "BaseRfiToken: transfer from the zero address" | |
| ); | |
| require( | |
| recipient != address(0), | |
| "BaseRfiToken: transfer to the zero address" | |
| ); | |
| require( | |
| sender != address(burnAddress), | |
| "BaseRfiToken: transfer from the burn address" | |
| ); | |
| require(amount > 0, "Transfer amount must be greater than zero"); | |
| // indicates whether or not feee should be deducted from the transfer | |
| bool takeFee = true; | |
| if (isInPresale) { | |
| takeFee = false; | |
| } else { | |
| /** | |
| * Check the amount is within the max allowed limit as long as a | |
| * unlimited sender/recepient is not involved in the transaction | |
| */ | |
| if ( | |
| amount > maxTransactionAmount && | |
| !_isUnlimitedSender(sender) && | |
| !_isUnlimitedRecipient(recipient) | |
| ) { | |
| revert("Transfer amount exceeds the maxTxAmount."); | |
| } | |
| /** | |
| * The pair needs to excluded from the max wallet balance check; | |
| * selling tokens is sending them back to the pair (without this | |
| * check, selling tokens would not work if the pair's balance | |
| * was over the allowed max) | |
| * | |
| * Note: This does NOT take into account the fees which will be deducted | |
| * from the amount. As such it could be a bit confusing | |
| */ | |
| if ( | |
| maxWalletBalance > 0 && | |
| !_isUnlimitedSender(sender) && | |
| !_isUnlimitedRecipient(recipient) && | |
| !_isV2Pair(recipient) | |
| ) { | |
| uint256 recipientBalance = balanceOf(recipient); | |
| require( | |
| recipientBalance + amount <= maxWalletBalance, | |
| "New balance would exceed the maxWalletBalance" | |
| ); | |
| } | |
| } | |
| // if any account belongs to _isExcludedFromFee account then remove the fee | |
| if (_isExcludedFromFee[sender] || _isExcludedFromFee[recipient]) { | |
| takeFee = false; | |
| } | |
| _beforeTokenTransfer(sender, recipient, amount, takeFee); | |
| _transferTokens(sender, recipient, amount, takeFee); | |
| } | |
| function _transferTokens( | |
| address sender, | |
| address recipient, | |
| uint256 amount, | |
| bool takeFee | |
| ) private { | |
| /** | |
| * We don't need to know anything about the individual fees here | |
| * (like Safemoon does with `_getValues`). All that is required | |
| * for the transfer is the sum of all fees to calculate the % of the total | |
| * transaction amount which should be transferred to the recipient. | |
| * | |
| * The `_takeFees` call will/should take care of the individual fees | |
| */ | |
| uint256 sumOfFees = _getSumOfFees(sender, amount); | |
| if (!takeFee) { | |
| sumOfFees = 0; | |
| } | |
| ( | |
| uint256 rAmount, | |
| uint256 rTransferAmount, | |
| uint256 tAmount, | |
| uint256 tTransferAmount, | |
| uint256 currentRate | |
| ) = _getValues(amount, sumOfFees); | |
| /** | |
| * Sender's and Recipient's reflected balances must be always updated regardless of | |
| * whether they are excluded from rewards or not. | |
| */ | |
| _reflectedBalances[sender] = _reflectedBalances[sender].sub(rAmount); | |
| _reflectedBalances[recipient] = _reflectedBalances[recipient].add( | |
| rTransferAmount | |
| ); | |
| /** | |
| * Update the true/nominal balances for excluded accounts | |
| */ | |
| if (_isExcludedFromRewards[sender]) { | |
| _balances[sender] = _balances[sender].sub(tAmount); | |
| } | |
| if (_isExcludedFromRewards[recipient]) { | |
| _balances[recipient] = _balances[recipient].add(tTransferAmount); | |
| } | |
| _takeFees(amount, currentRate, sumOfFees); | |
| emit Transfer(sender, recipient, tTransferAmount); | |
| } | |
| function _takeFees( | |
| uint256 amount, | |
| uint256 currentRate, | |
| uint256 sumOfFees | |
| ) private { | |
| if (sumOfFees > 0 && !isInPresale) { | |
| _takeTransactionFees(amount, currentRate); | |
| } | |
| } | |
| function _getValues(uint256 tAmount, uint256 feesSum) | |
| internal | |
| view | |
| returns ( | |
| uint256, | |
| uint256, | |
| uint256, | |
| uint256, | |
| uint256 | |
| ) | |
| { | |
| uint256 tTotalFees = tAmount.mul(feesSum).div(FEES_DIVISOR); | |
| uint256 tTransferAmount = tAmount.sub(tTotalFees); | |
| uint256 currentRate = _getCurrentRate(); | |
| uint256 rAmount = tAmount.mul(currentRate); | |
| uint256 rTotalFees = tTotalFees.mul(currentRate); | |
| uint256 rTransferAmount = rAmount.sub(rTotalFees); | |
| return ( | |
| rAmount, | |
| rTransferAmount, | |
| tAmount, | |
| tTransferAmount, | |
| currentRate | |
| ); | |
| } | |
| function _getCurrentRate() internal view returns (uint256) { | |
| (uint256 rSupply, uint256 tSupply) = _getCurrentSupply(); | |
| return rSupply.div(tSupply); | |
| } | |
| function _getCurrentSupply() internal view returns (uint256, uint256) { | |
| uint256 rSupply = _reflectedSupply; | |
| uint256 tSupply = TOTAL_SUPPLY; | |
| /** | |
| * The code below removes balances of addresses excluded from rewards from | |
| * rSupply and tSupply, which effectively increases the % of transaction fees | |
| * delivered to non-excluded holders | |
| */ | |
| for (uint256 i = 0; i < _excluded.length; i++) { | |
| if ( | |
| _reflectedBalances[_excluded[i]] > rSupply || | |
| _balances[_excluded[i]] > tSupply | |
| ) return (_reflectedSupply, TOTAL_SUPPLY); | |
| rSupply = rSupply.sub(_reflectedBalances[_excluded[i]]); | |
| tSupply = tSupply.sub(_balances[_excluded[i]]); | |
| } | |
| if (tSupply == 0 || rSupply < _reflectedSupply.div(TOTAL_SUPPLY)) | |
| return (_reflectedSupply, TOTAL_SUPPLY); | |
| return (rSupply, tSupply); | |
| } | |
| /** | |
| * @dev Hook that is called before any transfer of tokens. | |
| */ | |
| function _beforeTokenTransfer( | |
| address sender, | |
| address recipient, | |
| uint256 amount, | |
| bool takeFee | |
| ) internal virtual; | |
| /** | |
| * @dev Returns the total sum of fees to be processed in each transaction. | |
| * | |
| * To separate concerns this contract (class) will take care of ONLY handling RFI, i.e. | |
| * changing the rates and updating the holder's balance (via `_redistribute`). | |
| * It is the responsibility of the dev/user to handle all other fees and taxes | |
| * in the appropriate contracts (classes). | |
| */ | |
| function _getSumOfFees(address sender, uint256 amount) | |
| internal | |
| view | |
| virtual | |
| returns (uint256); | |
| /** | |
| * @dev A delegate which should return true if the given address is the V2 Pair and false otherwise | |
| */ | |
| function _isV2Pair(address account) internal view virtual returns (bool); | |
| /** | |
| * @dev Redistributes the specified amount among the current holders via the reflect.finance | |
| * algorithm, i.e. by updating the _reflectedSupply (_rSupply) which ultimately adjusts the | |
| * current rate used by `tokenFromReflection` and, in turn, the value returns from `balanceOf`. | |
| * This is the bit of clever math which allows rfi to redistribute the fee without | |
| * having to iterate through all holders. | |
| * | |
| * Visit our discord at https://discord.gg/dAmr6eUTpM | |
| */ | |
| function _redistribute( | |
| uint256 amount, | |
| uint256 currentRate, | |
| uint256 fee, | |
| uint256 index | |
| ) internal { | |
| uint256 tFee = amount.mul(fee).div(FEES_DIVISOR); | |
| uint256 rFee = tFee.mul(currentRate); | |
| _reflectedSupply = _reflectedSupply.sub(rFee); | |
| _addFeeCollectedAmount(index, tFee); | |
| } | |
| /** | |
| * @dev Hook that is called before the `Transfer` event is emitted if fees are enabled for the transfer | |
| */ | |
| function _takeTransactionFees(uint256 amount, uint256 currentRate) | |
| internal | |
| virtual; | |
| } | |
| abstract contract Liquifier is Ownable, Manageable { | |
| using SafeMath for uint256; | |
| uint256 private withdrawableBalance; | |
| enum Env {Testnet, MainnetV1, MainnetV2} | |
| Env private _env; | |
| // PancakeSwap V1 | |
| address private _mainnetRouterV1Address = | |
| 0x05fF2B0DB69458A0750badebc4f9e13aDd608C7F; | |
| // PancakeSwap V2 | |
| address private _mainnetRouterV2Address = | |
| 0x10ED43C718714eb63d5aA57B78B54704E256024E; | |
| // Testnet | |
| // address private _testnetRouterAddress = 0xD99D1c33F9fC3444f8101754aBC46c52416550D1; | |
| // PancakeSwap Testnet = https://pancake.kiemtienonline360.com/ | |
| address private _testnetRouterAddress = | |
| 0x9Ac64Cc6e4415144C455BD8E4837Fea55603e5c3; | |
| IPancakeV2Router internal _router; | |
| address internal _pair; | |
| bool private inSwapAndLiquify; | |
| bool private swapAndLiquifyEnabled = true; | |
| uint256 private maxTransactionAmount; | |
| uint256 private numberOfTokensToSwapToLiquidity; | |
| modifier lockTheSwap { | |
| inSwapAndLiquify = true; | |
| _; | |
| inSwapAndLiquify = false; | |
| } | |
| event RouterSet(address indexed router); | |
| event SwapAndLiquify( | |
| uint256 tokensSwapped, | |
| uint256 ethReceived, | |
| uint256 tokensIntoLiquidity | |
| ); | |
| event SwapAndLiquifyEnabledUpdated(bool enabled); | |
| event LiquidityAdded( | |
| uint256 tokenAmountSent, | |
| uint256 ethAmountSent, | |
| uint256 liquidity | |
| ); | |
| receive() external payable {} | |
| function initializeLiquiditySwapper( | |
| Env env, | |
| uint256 maxTx, | |
| uint256 liquifyAmount | |
| ) internal { | |
| _env = env; | |
| if (_env == Env.MainnetV1) { | |
| _setRouterAddress(_mainnetRouterV1Address); | |
| } else if (_env == Env.MainnetV2) { | |
| _setRouterAddress(_mainnetRouterV2Address); | |
| } | |
| /*(_env == Env.Testnet)*/ | |
| else { | |
| _setRouterAddress(_testnetRouterAddress); | |
| } | |
| maxTransactionAmount = maxTx; | |
| numberOfTokensToSwapToLiquidity = liquifyAmount; | |
| } | |
| /** | |
| * NOTE: passing the `contractTokenBalance` here is preferred to creating `balanceOfDelegate` | |
| */ | |
| function liquify(uint256 contractTokenBalance, address sender) internal { | |
| if (contractTokenBalance >= maxTransactionAmount) | |
| contractTokenBalance = maxTransactionAmount; | |
| bool isOverRequiredTokenBalance = | |
| (contractTokenBalance >= numberOfTokensToSwapToLiquidity); | |
| /** | |
| * - first check if the contract has collected enough tokens to swap and liquify | |
| * - then check swap and liquify is enabled | |
| * - then make sure not to get caught in a circular liquidity event | |
| * - finally, don't swap & liquify if the sender is the uniswap pair | |
| */ | |
| if ( | |
| isOverRequiredTokenBalance && | |
| swapAndLiquifyEnabled && | |
| !inSwapAndLiquify && | |
| (sender != _pair) | |
| ) { | |
| // TODO check if the `(sender != _pair)` is necessary because that basically | |
| // stops swap and liquify for all "buy" transactions | |
| _swapAndLiquify(contractTokenBalance); | |
| } | |
| } | |
| /** | |
| * @dev sets the router address and created the router, factory pair to enable | |
| * swapping and liquifying (contract) tokens | |
| */ | |
| function _setRouterAddress(address router) private { | |
| IPancakeV2Router _newPancakeRouter = IPancakeV2Router(router); | |
| _pair = IPancakeV2Factory(_newPancakeRouter.factory()).createPair( | |
| address(this), | |
| _newPancakeRouter.WETH() | |
| ); | |
| _router = _newPancakeRouter; | |
| emit RouterSet(router); | |
| } | |
| function _swapAndLiquify(uint256 amount) private lockTheSwap { | |
| // split the contract balance into halves | |
| uint256 half = amount.div(2); | |
| uint256 otherHalf = amount.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); // <- 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] = _router.WETH(); | |
| _approveDelegate(address(this), address(_router), tokenAmount); | |
| // make the swap | |
| _router.swapExactTokensForETHSupportingFeeOnTransferTokens( | |
| tokenAmount, | |
| // The minimum amount of output tokens that must be received for the transaction not to revert. | |
| // 0 = accept any amount (slippage is inevitable) | |
| 0, | |
| path, | |
| address(this), | |
| block.timestamp | |
| ); | |
| } | |
| function _addLiquidity(uint256 tokenAmount, uint256 ethAmount) private { | |
| // approve token transfer to cover all possible scenarios | |
| _approveDelegate(address(this), address(_router), tokenAmount); | |
| // add tahe liquidity | |
| (uint256 tokenAmountSent, uint256 ethAmountSent, uint256 liquidity) = | |
| _router.addLiquidityETH{value: ethAmount}( | |
| address(this), | |
| tokenAmount, | |
| // Bounds the extent to which the WETH/token price can go up before the transaction reverts. | |
| // Must be <= amountTokenDesired; 0 = accept any amount (slippage is inevitable) | |
| 0, | |
| // Bounds the extent to which the token/WETH price can go up before the transaction reverts. | |
| // 0 = accept any amount (slippage is inevitable) | |
| 0, | |
| // this is a centralized risk if the owner's account is ever compromised (see Certik SSL-04) | |
| owner(), | |
| block.timestamp | |
| ); | |
| // fix the forever locked BNBs as per the certik's audit | |
| /** | |
| * The swapAndLiquify function converts half of the contractTokenBalance SafeMoon tokens to BNB. | |
| * For every swapAndLiquify function call, a small amount of BNB remains in the contract. | |
| * This amount grows over time with the swapAndLiquify function being called throughout the life | |
| * of the contract. The Safemoon contract does not contain a method to withdraw these funds, | |
| * and the BNB will be locked in the Safemoon contract forever. | |
| */ | |
| withdrawableBalance = address(this).balance; | |
| emit LiquidityAdded(tokenAmountSent, ethAmountSent, liquidity); | |
| } | |
| /** | |
| * @dev Sets the uniswapV2 pair (router & factory) for swapping and liquifying tokens | |
| */ | |
| function setRouterAddress(address router) external onlyManager() { | |
| _setRouterAddress(router); | |
| } | |
| /** | |
| * @dev Sends the swap and liquify flag to the provided value. If set to `false` tokens collected in the contract will | |
| * NOT be converted into liquidity. | |
| */ | |
| function setSwapAndLiquifyEnabled(bool enabled) external onlyManager { | |
| swapAndLiquifyEnabled = enabled; | |
| emit SwapAndLiquifyEnabledUpdated(swapAndLiquifyEnabled); | |
| } | |
| /** | |
| * @dev The owner can withdraw ETH(BNB) collected in the contract from `swapAndLiquify` | |
| * or if someone (accidentally) sends ETH/BNB directly to the contract. | |
| * | |
| * Note: This addresses the contract flaw pointed out in the Certik Audit of Safemoon (SSL-03): | |
| * | |
| * The swapAndLiquify function converts half of the contractTokenBalance SafeMoon tokens to BNB. | |
| * For every swapAndLiquify function call, a small amount of BNB remains in the contract. | |
| * This amount grows over time with the swapAndLiquify function being called | |
| * throughout the life of the contract. The Safemoon contract does not contain a method | |
| * to withdraw these funds, and the BNB will be locked in the Safemoon contract forever. | |
| * https://www.certik.org/projects/safemoon | |
| */ | |
| function withdrawLockedEth(address payable recipient) | |
| external | |
| onlyManager() | |
| { | |
| require( | |
| recipient != address(0), | |
| "Cannot withdraw the ETH balance to the zero address" | |
| ); | |
| require( | |
| withdrawableBalance > 0, | |
| "The ETH balance must be greater than 0" | |
| ); | |
| // prevent re-entrancy attacks | |
| uint256 amount = withdrawableBalance; | |
| withdrawableBalance = 0; | |
| recipient.transfer(amount); | |
| } | |
| /** | |
| * @dev Use this delegate instead of having (unnecessarily) extend `BaseRfiToken` to gained access | |
| * to the `_approve` function. | |
| */ | |
| function _approveDelegate( | |
| address owner, | |
| address spender, | |
| uint256 amount | |
| ) internal virtual; | |
| } | |
| ////////////////////////////////////////////////////////////////////////// | |
| abstract contract Antiwhale is Tokenomics { | |
| /** | |
| * @dev Returns the total sum of fees (in percents / per-mille - this depends on the FEES_DIVISOR value) | |
| * | |
| * NOTE: Currently this is just a placeholder. The parameters passed to this function are the | |
| * sender's token balance and the transfer amount. An *antiwhale* mechanics can use these | |
| * values to adjust the fees total for each tx | |
| */ | |
| // function _getAntiwhaleFees(uint256 sendersBalance, uint256 amount) internal view returns (uint256){ | |
| function _getAntiwhaleFees(uint256, uint256) | |
| internal | |
| view | |
| returns (uint256) | |
| { | |
| return sumOfFees; | |
| } | |
| } | |
| ////////////////////////////////////////////////////////////////////////// | |
| abstract contract PokeDX is BaseRfiToken, Liquifier, Antiwhale { | |
| using SafeMath for uint256; | |
| // constructor(string memory _name, string memory _symbol, uint8 _decimals){ | |
| constructor(Env _env) { | |
| initializeLiquiditySwapper( | |
| _env, | |
| maxTransactionAmount, | |
| numberOfTokensToSwapToLiquidity | |
| ); | |
| // exclude the pair address from rewards - we don't want to redistribute | |
| // tx fees to these two; redistribution is only for holders, dah! | |
| _exclude(_pair); | |
| _exclude(burnAddress); | |
| } | |
| function _isV2Pair(address account) internal view override returns (bool) { | |
| return (account == _pair); | |
| } | |
| function _getSumOfFees(address sender, uint256 amount) | |
| internal | |
| view | |
| override | |
| returns (uint256) | |
| { | |
| return _getAntiwhaleFees(balanceOf(sender), amount); | |
| } | |
| // function _beforeTokenTransfer(address sender, address recipient, uint256 amount, bool takeFee) internal override { | |
| function _beforeTokenTransfer( | |
| address sender, | |
| address, | |
| uint256, | |
| bool | |
| ) internal override { | |
| if (!isInPresale) { | |
| uint256 contractTokenBalance = balanceOf(address(this)); | |
| liquify(contractTokenBalance, sender); | |
| } | |
| } | |
| function _takeTransactionFees(uint256 amount, uint256 currentRate) | |
| internal | |
| override | |
| { | |
| if (isInPresale) { | |
| return; | |
| } | |
| uint256 feesCount = _getFeesCount(); | |
| for (uint256 index = 0; index < feesCount; index++) { | |
| (FeeType name, uint256 value, address recipient, ) = _getFee(index); | |
| // no need to check value < 0 as the value is uint (i.e. from 0 to 2^256-1) | |
| if (value == 0) continue; | |
| if (name == FeeType.Rfi) { | |
| _redistribute(amount, currentRate, value, index); | |
| } else if (name == FeeType.Burn) { | |
| _burn(amount, currentRate, value, index); | |
| } else if (name == FeeType.Antiwhale) { | |
| // TODO | |
| } else if (name == FeeType.ExternalToETH) { | |
| _takeFeeToETH(amount, currentRate, value, recipient, index); | |
| } else { | |
| _takeFee(amount, currentRate, value, recipient, index); | |
| } | |
| } | |
| } | |
| function _burn( | |
| uint256 amount, | |
| uint256 currentRate, | |
| uint256 fee, | |
| uint256 index | |
| ) private { | |
| uint256 tBurn = amount.mul(fee).div(FEES_DIVISOR); | |
| uint256 rBurn = tBurn.mul(currentRate); | |
| _burnTokens(address(this), tBurn, rBurn); | |
| _addFeeCollectedAmount(index, tBurn); | |
| } | |
| function _takeFee( | |
| uint256 amount, | |
| uint256 currentRate, | |
| uint256 fee, | |
| address recipient, | |
| uint256 index | |
| ) private { | |
| uint256 tAmount = amount.mul(fee).div(FEES_DIVISOR); | |
| uint256 rAmount = tAmount.mul(currentRate); | |
| _reflectedBalances[recipient] = _reflectedBalances[recipient].add( | |
| rAmount | |
| ); | |
| if (_isExcludedFromRewards[recipient]) | |
| _balances[recipient] = _balances[recipient].add(tAmount); | |
| _addFeeCollectedAmount(index, tAmount); | |
| } | |
| /** | |
| * @dev When implemented this will convert the fee amount of tokens into ETH/BNB | |
| * and send to the recipient's wallet. Note that this reduces liquidity so it | |
| * might be a good idea to add a % into the liquidity fee for % you take our through | |
| * this method (just a suggestions) | |
| */ | |
| function _takeFeeToETH( | |
| uint256 amount, | |
| uint256 currentRate, | |
| uint256 fee, | |
| address recipient, | |
| uint256 index | |
| ) private { | |
| _takeFee(amount, currentRate, fee, recipient, index); | |
| } | |
| function _approveDelegate( | |
| address owner, | |
| address spender, | |
| uint256 amount | |
| ) internal override { | |
| _approve(owner, spender, amount); | |
| } | |
| } | |
| contract PokeDXV1Beta is PokeDX { | |
| constructor() PokeDX(Env.Testnet) { | |
| // pre-approve the initial liquidity supply (to safe a bit of time) | |
| _approve(owner(), address(_router), ~uint256(0)); | |
| } | |
| } | |
| /** | |
| * Todo (beta): | |
| * | |
| * - reorganize the sol file(s) to make put everything editable in a single .sol file | |
| * and keep all other code in other .sol file(s) | |
| * - move variable values initialized in the contract to be constructor parameters | |
| * - add/remove setters/getter where appropriate | |
| * - add unit tests (via ganache-cli + truffle) | |
| * - add full dev evn (truffle) folders & files | |
| * | |
| * Todo: | |
| * | |
| * - implement `_takeFeeToETH` (currently just calls `_takeFee`) | |
| * - implement anti whale mechanics (via different pre-created libraries?), eg progressive tax | |
| * - implement anti sell mechanics | |
| * - address SSL-04 | Centralized risk in addLiquidity - https://www.certik.org/projects/safemoon | |
| * change the recipient to `address(this)` or implement a decentralized mechanism or | |
| * smart-contract solution | |
| * - change Uniswap to PancakeSwap in contract/interface names and local var names | |
| * - change ETH to BNB in names and comments | |
| */ | |
| /** | |
| * Tests to pass: | |
| * | |
| * - Tokenomics fees can be added/removed/edited | |
| * - Tokenomics fees are correctly taken from each (qualifying) transaction | |
| * - The RFI fee is correctly distributed among holders (which are not excluded from rewards) | |
| * - `swapAndLiquify` works correctly when the threshold balance is reached | |
| * - `maxTransactionAmount` works correctly and *unlimited* accounts are not subject to the limit | |
| * - `maxWalletBalance` works correctly and *unlimited* accounts are not subject to the limit | |
| * - accounts excluded from fees are not subjecto tx fees | |
| * - accounts excluded from rewards do not share in rewards | |
| * - ETH/BNB collected/stuck in the contract can be withdrawn (see) | |
| */ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| *Submitted for verification at BscScan.com on 2021-03-01 | |
| */ | |
| /** | |
| *Submitted for verification at BscScan.com on 2021-03-01 | |
| */ | |
| /** | |
| #BEE | |
| #LIQ+#RFI+#SHIB+#DOGE = #BEE | |
| #SAFEMOON features: | |
| 3% fee auto add to the liquidity pool to locked forever when selling | |
| 2% fee auto distribute to all holders | |
| I created a black hole so #Bee token will deflate itself in supply with every transaction | |
| 50% Supply is burned at start. | |
| */ | |
| pragma solidity ^0.6.12; | |
| // SPDX-License-Identifier: Unlicensed | |
| interface IERC20 { | |
| 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); | |
| } | |
| /** | |
| * @dev Wrappers over Solidity's arithmetic operations with added overflow | |
| * checks. | |
| * | |
| * Arithmetic operations in Solidity wrap on overflow. This can easily result | |
| * in bugs, because programmers usually assume that an overflow raises an | |
| * error, which is the standard behavior in high level programming languages. | |
| * `SafeMath` restores this intuition by reverting the transaction when an | |
| * operation overflows. | |
| * | |
| * Using this library instead of the unchecked operations eliminates an entire | |
| * class of bugs, so it's recommended to use it always. | |
| */ | |
| 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 <= 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; | |
| } | |
| } | |
| abstract contract Context { | |
| function _msgSender() internal view virtual returns (address payable) { | |
| return msg.sender; | |
| } | |
| function _msgData() internal view virtual returns (bytes memory) { | |
| this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 | |
| return msg.data; | |
| } | |
| } | |
| /** | |
| * @dev Collection of functions related to the address type | |
| */ | |
| library Address { | |
| /** | |
| * @dev Returns true if `account` is a contract. | |
| * | |
| * [IMPORTANT] | |
| * ==== | |
| * It is unsafe to assume that an address for which this function returns | |
| * false is an externally-owned account (EOA) and not a contract. | |
| * | |
| * Among others, `isContract` will return false for the following | |
| * types of addresses: | |
| * | |
| * - an externally-owned account | |
| * - a contract in construction | |
| * - an address where a contract will be created | |
| * - an address where a contract lived, but was destroyed | |
| * ==== | |
| */ | |
| function isContract(address account) internal view returns (bool) { | |
| // According to EIP-1052, 0x0 is the value returned for not-yet created accounts | |
| // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned | |
| // for accounts without code, i.e. `keccak256('')` | |
| bytes32 codehash; | |
| bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; | |
| // solhint-disable-next-line no-inline-assembly | |
| assembly { codehash := extcodehash(account) } | |
| return (codehash != accountHash && codehash != 0x0); | |
| } | |
| /** | |
| * @dev Replacement for Solidity's `transfer`: sends `amount` wei to | |
| * `recipient`, forwarding all available gas and reverting on errors. | |
| * | |
| * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost | |
| * of certain opcodes, possibly making contracts go over the 2300 gas limit | |
| * imposed by `transfer`, making them unable to receive funds via | |
| * `transfer`. {sendValue} removes this limitation. | |
| * | |
| * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. | |
| * | |
| * IMPORTANT: because control is transferred to `recipient`, care must be | |
| * taken to not create reentrancy vulnerabilities. Consider using | |
| * {ReentrancyGuard} or the | |
| * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. | |
| */ | |
| function sendValue(address payable recipient, uint256 amount) internal { | |
| require(address(this).balance >= amount, "Address: insufficient balance"); | |
| // solhint-disable-next-line avoid-low-level-calls, avoid-call-value | |
| (bool success, ) = recipient.call{ value: amount }(""); | |
| require(success, "Address: unable to send value, recipient may have reverted"); | |
| } | |
| /** | |
| * @dev Performs a Solidity function call using a low level `call`. A | |
| * plain`call` is an unsafe replacement for a function call: use this | |
| * function instead. | |
| * | |
| * If `target` reverts with a revert reason, it is bubbled up by this | |
| * function (like regular Solidity function calls). | |
| * | |
| * Returns the raw returned data. To convert to the expected return value, | |
| * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. | |
| * | |
| * Requirements: | |
| * | |
| * - `target` must be a contract. | |
| * - calling `target` with `data` must not revert. | |
| * | |
| * _Available since v3.1._ | |
| */ | |
| function functionCall(address target, bytes memory data) internal returns (bytes memory) { | |
| return functionCall(target, data, "Address: low-level call failed"); | |
| } | |
| /** | |
| * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with | |
| * `errorMessage` as a fallback revert reason when `target` reverts. | |
| * | |
| * _Available since v3.1._ | |
| */ | |
| function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { | |
| return _functionCallWithValue(target, data, 0, errorMessage); | |
| } | |
| /** | |
| * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], | |
| * but also transferring `value` wei to `target`. | |
| * | |
| * Requirements: | |
| * | |
| * - the calling contract must have an ETH balance of at least `value`. | |
| * - the called Solidity function must be `payable`. | |
| * | |
| * _Available since v3.1._ | |
| */ | |
| function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { | |
| return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); | |
| } | |
| /** | |
| * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but | |
| * with `errorMessage` as a fallback revert reason when `target` reverts. | |
| * | |
| * _Available since v3.1._ | |
| */ | |
| function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { | |
| require(address(this).balance >= value, "Address: insufficient balance for call"); | |
| return _functionCallWithValue(target, data, value, errorMessage); | |
| } | |
| function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) { | |
| require(isContract(target), "Address: call to non-contract"); | |
| // solhint-disable-next-line avoid-low-level-calls | |
| (bool success, bytes memory returndata) = target.call{ value: weiValue }(data); | |
| if (success) { | |
| return returndata; | |
| } else { | |
| // Look for revert reason and bubble it up if present | |
| if (returndata.length > 0) { | |
| // The easiest way to bubble the revert reason is using memory via assembly | |
| // solhint-disable-next-line no-inline-assembly | |
| assembly { | |
| let returndata_size := mload(returndata) | |
| revert(add(32, returndata), returndata_size) | |
| } | |
| } else { | |
| revert(errorMessage); | |
| } | |
| } | |
| } | |
| } | |
| /** | |
| * @dev Contract module which provides a basic access control mechanism, where | |
| * there is an account (an owner) that can be granted exclusive access to | |
| * specific functions. | |
| * | |
| * By default, the owner account will be the one that deploys the contract. This | |
| * can later be changed with {transferOwnership}. | |
| * | |
| * This module is used through inheritance. It will make available the modifier | |
| * `onlyOwner`, which can be applied to your functions to restrict their use to | |
| * the owner. | |
| */ | |
| contract Ownable is Context { | |
| address private _owner; | |
| address private _previousOwner; | |
| uint256 private _lockTime; | |
| event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); | |
| /** | |
| * @dev Initializes the contract setting the deployer as the initial owner. | |
| */ | |
| constructor () internal { | |
| 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; | |
| } | |
| function geUnlockTime() public view returns (uint256) { | |
| return _lockTime; | |
| } | |
| //Locks the contract for owner for the amount of time provided | |
| function lock(uint256 time) public virtual onlyOwner { | |
| _previousOwner = _owner; | |
| _owner = address(0); | |
| _lockTime = now + time; | |
| emit OwnershipTransferred(_owner, address(0)); | |
| } | |
| //Unlocks the contract for owner when _lockTime is exceeds | |
| function unlock() public virtual { | |
| require(_previousOwner == msg.sender, "You don't have permission to unlock"); | |
| require(now > _lockTime , "Contract is locked until 7 days"); | |
| emit OwnershipTransferred(_owner, _previousOwner); | |
| _owner = _previousOwner; | |
| } | |
| } | |
| // pragma solidity >=0.5.0; | |
| 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.5.0; | |
| 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; | |
| } | |
| contract SafeMoon is Context, IERC20, Ownable { | |
| using SafeMath for uint256; | |
| using Address for address; | |
| mapping (address => uint256) public _rOwned; | |
| mapping (address => uint256) public _tOwned; | |
| mapping (address => mapping (address => uint256)) public _allowances; | |
| mapping (address => bool) public _isExcludedFromFee; | |
| mapping (address => bool) public _isExcluded; | |
| address[] public _excluded; | |
| uint256 public constant MAX = ~uint256(0); | |
| uint256 public _tTotal = 1000000000 * 10**6 * 10**9; | |
| uint256 public _rTotal = (MAX - (MAX % _tTotal)); | |
| uint256 public _tFeeTotal; | |
| string private _name = "SafeMoon"; | |
| string private _symbol = "SAFEMOON"; | |
| uint8 private _decimals = 9; | |
| uint256 public _taxFee = 5; | |
| uint256 private _previousTaxFee = _taxFee; | |
| uint256 public _liquidityFee = 5; | |
| uint256 private _previousLiquidityFee = _liquidityFee; | |
| IUniswapV2Router02 public immutable uniswapV2Router; | |
| address public immutable uniswapV2Pair; | |
| bool inSwapAndLiquify; | |
| bool public swapAndLiquifyEnabled = true; | |
| uint256 public _maxTxAmount = 5000000 * 10**6 * 10**9; | |
| uint256 private numTokensSellToAddToLiquidity = 500000 * 10**6 * 10**9; | |
| event MinTokensBeforeSwapUpdated(uint256 minTokensBeforeSwap); | |
| event SwapAndLiquifyEnabledUpdated(bool enabled); | |
| event SwapAndLiquify( | |
| uint256 tokensSwapped, | |
| uint256 ethReceived, | |
| uint256 tokensIntoLiqudity | |
| ); | |
| modifier lockTheSwap { | |
| inSwapAndLiquify = true; | |
| _; | |
| inSwapAndLiquify = false; | |
| } | |
| constructor () public { | |
| _rOwned[_msgSender()] = _rTotal; | |
| IUniswapV2Router02 _uniswapV2Router = IUniswapV2Router02(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D); | |
| // Create a uniswap pair for this new token | |
| uniswapV2Pair = IUniswapV2Factory(_uniswapV2Router.factory()) | |
| .createPair(address(this), _uniswapV2Router.WETH()); | |
| // set the rest of the contract variables | |
| uniswapV2Router = _uniswapV2Router; | |
| //exclude owner and this contract from fee | |
| _isExcludedFromFee[owner()] = true; | |
| _isExcludedFromFee[address(this)] = true; | |
| emit Transfer(address(0), _msgSender(), _tTotal); | |
| } | |
| function name() public view returns (string memory) { | |
| return _name; | |
| } | |
| function symbol() public view returns (string memory) { | |
| return _symbol; | |
| } | |
| function decimals() public view returns (uint8) { | |
| return _decimals; | |
| } | |
| function totalSupply() public view override returns (uint256) { | |
| return _tTotal; | |
| } | |
| function balanceOf(address account) public view override returns (uint256) { | |
| if (_isExcluded[account]) return _tOwned[account]; | |
| return tokenFromReflection(_rOwned[account]); | |
| } | |
| function transfer(address recipient, uint256 amount) public override returns (bool) { | |
| _transfer(_msgSender(), recipient, amount); | |
| return true; | |
| } | |
| function allowance(address owner, address spender) public view override returns (uint256) { | |
| return _allowances[owner][spender]; | |
| } | |
| function approve(address spender, uint256 amount) public override returns (bool) { | |
| _approve(_msgSender(), spender, amount); | |
| return true; | |
| } | |
| function transferFrom(address sender, address recipient, uint256 amount) public override returns (bool) { | |
| _transfer(sender, recipient, amount); | |
| _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); | |
| return true; | |
| } | |
| function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { | |
| _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); | |
| return true; | |
| } | |
| 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; | |
| } | |
| function isExcludedFromReward(address account) public view returns (bool) { | |
| return _isExcluded[account]; | |
| } | |
| function totalFees() public view returns (uint256) { | |
| return _tFeeTotal; | |
| } | |
| function deliver(uint256 tAmount) public { | |
| address sender = _msgSender(); | |
| require(!_isExcluded[sender], "Excluded addresses cannot call this function"); | |
| (uint256 rAmount,,,,,) = _getValues(tAmount); | |
| _rOwned[sender] = _rOwned[sender].sub(rAmount); | |
| _rTotal = _rTotal.sub(rAmount); | |
| _tFeeTotal = _tFeeTotal.add(tAmount); | |
| } | |
| function reflectionFromToken(uint256 tAmount, bool deductTransferFee) public view returns(uint256) { | |
| require(tAmount <= _tTotal, "Amount must be less than supply"); | |
| if (!deductTransferFee) { | |
| (uint256 rAmount,,,,,) = _getValues(tAmount); | |
| return rAmount; | |
| } else { | |
| (,uint256 rTransferAmount,,,,) = _getValues(tAmount); | |
| return rTransferAmount; | |
| } | |
| } | |
| function tokenFromReflection(uint256 rAmount) public view returns(uint256) { | |
| require(rAmount <= _rTotal, "Amount must be less than total reflections"); | |
| uint256 currentRate = _getRate(); | |
| return rAmount.div(currentRate); | |
| } | |
| function excludeFromReward(address account) public onlyOwner() { | |
| // require(account != 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D, 'We can not exclude Uniswap router.'); | |
| require(!_isExcluded[account], "Account is already excluded"); | |
| if(_rOwned[account] > 0) { | |
| _tOwned[account] = tokenFromReflection(_rOwned[account]); | |
| } | |
| _isExcluded[account] = true; | |
| _excluded.push(account); | |
| } | |
| function includeInReward(address account) external onlyOwner() { | |
| require(_isExcluded[account], "Account is already excluded"); | |
| for (uint256 i = 0; i < _excluded.length; i++) { | |
| if (_excluded[i] == account) { | |
| _excluded[i] = _excluded[_excluded.length - 1]; | |
| _tOwned[account] = 0; | |
| _isExcluded[account] = false; | |
| _excluded.pop(); | |
| break; | |
| } | |
| } | |
| } | |
| function _transferBothExcluded(address sender, address recipient, uint256 tAmount) private { | |
| (uint256 rAmount, uint256 rTransferAmount, uint256 rFee, uint256 tTransferAmount, uint256 tFee, uint256 tLiquidity) = _getValues(tAmount); | |
| _tOwned[sender] = _tOwned[sender].sub(tAmount); | |
| _rOwned[sender] = _rOwned[sender].sub(rAmount); | |
| _tOwned[recipient] = _tOwned[recipient].add(tTransferAmount); | |
| _rOwned[recipient] = _rOwned[recipient].add(rTransferAmount); | |
| _takeLiquidity(tLiquidity); | |
| _reflectFee(rFee, tFee); | |
| emit Transfer(sender, recipient, tTransferAmount); | |
| } | |
| function excludeFromFee(address account) public onlyOwner { | |
| _isExcludedFromFee[account] = true; | |
| } | |
| function includeInFee(address account) public onlyOwner { | |
| _isExcludedFromFee[account] = false; | |
| } | |
| function setTaxFeePercent(uint256 taxFee) external onlyOwner() { | |
| _taxFee = taxFee; | |
| } | |
| function setLiquidityFeePercent(uint256 liquidityFee) external onlyOwner() { | |
| _liquidityFee = liquidityFee; | |
| } | |
| function setMaxTxPercent(uint256 maxTxPercent) external onlyOwner() { | |
| _maxTxAmount = _tTotal.mul(maxTxPercent).div( | |
| 10**2 | |
| ); | |
| } | |
| function setSwapAndLiquifyEnabled(bool _enabled) public onlyOwner { | |
| swapAndLiquifyEnabled = _enabled; | |
| emit SwapAndLiquifyEnabledUpdated(_enabled); | |
| } | |
| //to recieve ETH from uniswapV2Router when swaping | |
| receive() external payable {} | |
| function _reflectFee(uint256 rFee, uint256 tFee) private { | |
| _rTotal = _rTotal.sub(rFee); | |
| _tFeeTotal = _tFeeTotal.add(tFee); | |
| } | |
| function _getValues(uint256 tAmount) private view returns (uint256, uint256, uint256, uint256, uint256, uint256) { | |
| (uint256 tTransferAmount, uint256 tFee, uint256 tLiquidity) = _getTValues(tAmount); | |
| (uint256 rAmount, uint256 rTransferAmount, uint256 rFee) = _getRValues(tAmount, tFee, tLiquidity, _getRate()); | |
| return (rAmount, rTransferAmount, rFee, tTransferAmount, tFee, tLiquidity); | |
| } | |
| function _getTValues(uint256 tAmount) private view returns (uint256, uint256, uint256) { | |
| uint256 tFee = calculateTaxFee(tAmount); | |
| uint256 tLiquidity = calculateLiquidityFee(tAmount); | |
| uint256 tTransferAmount = tAmount.sub(tFee).sub(tLiquidity); | |
| return (tTransferAmount, tFee, tLiquidity); | |
| } | |
| function _getRValues(uint256 tAmount, uint256 tFee, uint256 tLiquidity, uint256 currentRate) private pure returns (uint256, uint256, uint256) { | |
| uint256 rAmount = tAmount.mul(currentRate); | |
| uint256 rFee = tFee.mul(currentRate); | |
| uint256 rLiquidity = tLiquidity.mul(currentRate); | |
| uint256 rTransferAmount = rAmount.sub(rFee).sub(rLiquidity); | |
| return (rAmount, rTransferAmount, rFee); | |
| } | |
| function _getRate() private view returns(uint256) { | |
| (uint256 rSupply, uint256 tSupply) = _getCurrentSupply(); | |
| return rSupply.div(tSupply); | |
| } | |
| function _getCurrentSupply() private view returns(uint256, uint256) { | |
| uint256 rSupply = _rTotal; | |
| uint256 tSupply = _tTotal; | |
| for (uint256 i = 0; i < _excluded.length; i++) { | |
| if (_rOwned[_excluded[i]] > rSupply || _tOwned[_excluded[i]] > tSupply) return (_rTotal, _tTotal); | |
| rSupply = rSupply.sub(_rOwned[_excluded[i]]); | |
| tSupply = tSupply.sub(_tOwned[_excluded[i]]); | |
| } | |
| if (rSupply < _rTotal.div(_tTotal)) return (_rTotal, _tTotal); | |
| return (rSupply, tSupply); | |
| } | |
| function _takeLiquidity(uint256 tLiquidity) private { | |
| uint256 currentRate = _getRate(); | |
| uint256 rLiquidity = tLiquidity.mul(currentRate); | |
| _rOwned[address(this)] = _rOwned[address(this)].add(rLiquidity); | |
| if(_isExcluded[address(this)]) | |
| _tOwned[address(this)] = _tOwned[address(this)].add(tLiquidity); | |
| } | |
| function calculateTaxFee(uint256 _amount) private view returns (uint256) { | |
| return _amount.mul(_taxFee).div( | |
| 10**2 | |
| ); | |
| } | |
| function calculateLiquidityFee(uint256 _amount) private view returns (uint256) { | |
| return _amount.mul(_liquidityFee).div( | |
| 10**2 | |
| ); | |
| } | |
| function removeAllFee() private { | |
| if(_taxFee == 0 && _liquidityFee == 0) return; | |
| _previousTaxFee = _taxFee; | |
| _previousLiquidityFee = _liquidityFee; | |
| _taxFee = 0; | |
| _liquidityFee = 0; | |
| } | |
| function restoreAllFee() private { | |
| _taxFee = _previousTaxFee; | |
| _liquidityFee = _previousLiquidityFee; | |
| } | |
| function isExcludedFromFee(address account) public view returns(bool) { | |
| return _isExcludedFromFee[account]; | |
| } | |
| function _approve(address owner, address spender, uint256 amount) private { | |
| 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); | |
| } | |
| function _transfer( | |
| address from, | |
| address to, | |
| uint256 amount | |
| ) private { | |
| require(from != address(0), "ERC20: transfer from the zero address"); | |
| require(to != address(0), "ERC20: transfer to the zero address"); | |
| require(amount > 0, "Transfer amount must be greater than zero"); | |
| if(from != owner() && to != owner()) | |
| require(amount <= _maxTxAmount, "Transfer amount exceeds the maxTxAmount."); | |
| // is the token balance of this contract address over the min number of | |
| // tokens that we need to initiate a swap + liquidity lock? | |
| // also, don't get caught in a circular liquidity event. | |
| // also, don't swap & liquify if sender is uniswap pair. | |
| uint256 contractTokenBalance = balanceOf(address(this)); | |
| if(contractTokenBalance >= _maxTxAmount) | |
| { | |
| contractTokenBalance = _maxTxAmount; | |
| } | |
| bool overMinTokenBalance = contractTokenBalance >= numTokensSellToAddToLiquidity; | |
| if ( | |
| overMinTokenBalance && | |
| !inSwapAndLiquify && | |
| from != uniswapV2Pair && | |
| swapAndLiquifyEnabled | |
| ) { | |
| contractTokenBalance = numTokensSellToAddToLiquidity; | |
| //add liquidity | |
| swapAndLiquify(contractTokenBalance); | |
| } | |
| //indicates if fee should be deducted from transfer | |
| bool takeFee = true; | |
| //if any account belongs to _isExcludedFromFee account then remove the fee | |
| if(_isExcludedFromFee[from] || _isExcludedFromFee[to]){ | |
| takeFee = false; | |
| } | |
| //transfer amount, it will take tax, burn, liquidity fee | |
| _tokenTransfer(from,to,amount,takeFee); | |
| } | |
| function swapAndLiquify(uint256 contractTokenBalance) private lockTheSwap { | |
| // split the contract balance into halves | |
| uint256 half = contractTokenBalance.div(2); | |
| uint256 otherHalf = contractTokenBalance.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); // <- 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 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 | |
| owner(), | |
| block.timestamp | |
| ); | |
| } | |
| //this method is responsible for taking all fee, if takeFee is true | |
| function _tokenTransfer(address sender, address recipient, uint256 amount,bool takeFee) private { | |
| if(!takeFee) | |
| removeAllFee(); | |
| if (_isExcluded[sender] && !_isExcluded[recipient]) { | |
| _transferFromExcluded(sender, recipient, amount); | |
| } else if (!_isExcluded[sender] && _isExcluded[recipient]) { | |
| _transferToExcluded(sender, recipient, amount); | |
| } else if (!_isExcluded[sender] && !_isExcluded[recipient]) { | |
| _transferStandard(sender, recipient, amount); | |
| } else if (_isExcluded[sender] && _isExcluded[recipient]) { | |
| _transferBothExcluded(sender, recipient, amount); | |
| } else { | |
| _transferStandard(sender, recipient, amount); | |
| } | |
| if(!takeFee) | |
| restoreAllFee(); | |
| } | |
| function _transferStandard(address sender, address recipient, uint256 tAmount) private { | |
| (uint256 rAmount, uint256 rTransferAmount, uint256 rFee, uint256 tTransferAmount, uint256 tFee, uint256 tLiquidity) = _getValues(tAmount); | |
| _rOwned[sender] = _rOwned[sender].sub(rAmount); | |
| _rOwned[recipient] = _rOwned[recipient].add(rTransferAmount); | |
| _takeLiquidity(tLiquidity); | |
| _reflectFee(rFee, tFee); | |
| emit Transfer(sender, recipient, tTransferAmount); | |
| } | |
| function _transferToExcluded(address sender, address recipient, uint256 tAmount) private { | |
| (uint256 rAmount, uint256 rTransferAmount, uint256 rFee, uint256 tTransferAmount, uint256 tFee, uint256 tLiquidity) = _getValues(tAmount); | |
| _rOwned[sender] = _rOwned[sender].sub(rAmount); | |
| _tOwned[recipient] = _tOwned[recipient].add(tTransferAmount); | |
| _rOwned[recipient] = _rOwned[recipient].add(rTransferAmount); | |
| _takeLiquidity(tLiquidity); | |
| _reflectFee(rFee, tFee); | |
| emit Transfer(sender, recipient, tTransferAmount); | |
| } | |
| function _transferFromExcluded(address sender, address recipient, uint256 tAmount) private { | |
| (uint256 rAmount, uint256 rTransferAmount, uint256 rFee, uint256 tTransferAmount, uint256 tFee, uint256 tLiquidity) = _getValues(tAmount); | |
| _tOwned[sender] = _tOwned[sender].sub(tAmount); | |
| _rOwned[sender] = _rOwned[sender].sub(rAmount); | |
| _rOwned[recipient] = _rOwned[recipient].add(rTransferAmount); | |
| _takeLiquidity(tLiquidity); | |
| _reflectFee(rFee, tFee); | |
| emit Transfer(sender, recipient, tTransferAmount); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * SourceUnit: /home/dave/blockchain/tutorials&tests/safetoken-truffle/contracts/safetoken.sol | |
| */ | |
| /** | |
| */ | |
| pragma solidity ^0.8.4; | |
| interface IERC20 { | |
| function totalSupply() external view returns (uint256); | |
| function balanceOf(address account) external view returns (uint256); | |
| function transfer(address recipient, uint256 amount) external returns (bool); | |
| function allowance(address owner, address spender) external view returns (uint256); | |
| function approve(address spender, uint256 amount) external returns (bool); | |
| function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); | |
| event Transfer(address indexed from, address indexed to, uint256 value); | |
| event Approval(address indexed owner, address indexed spender, uint256 value); | |
| } | |
| interface IERC20Metadata is IERC20 { | |
| function name() external view returns (string memory); | |
| function symbol() external view returns (string memory); | |
| function decimals() external view returns (uint8); | |
| } | |
| abstract contract Context { | |
| function _msgSender() internal view virtual returns (address) {return msg.sender;} | |
| function _msgData() internal view virtual returns (bytes calldata) {this; return msg.data;} | |
| } | |
| library SafeMath { | |
| function add(uint256 a, uint256 b) internal pure returns (uint256) {return a + b;} | |
| function sub(uint256 a, uint256 b) internal pure returns (uint256) {return a - b;} | |
| function mul(uint256 a, uint256 b) internal pure returns (uint256) {return a * b;} | |
| function div(uint256 a, uint256 b) internal pure returns (uint256) {return a / b;} | |
| function mod(uint256 a, uint256 b) internal pure returns (uint256) {return a % b;} | |
| function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
| unchecked { require(b <= a, errorMessage); return a - b; } | |
| } | |
| } | |
| library Address { | |
| function isContract(address account) internal view returns (bool) { uint256 size; assembly { size := extcodesize(account) } return size > 0;} | |
| function sendValue(address payable 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"); | |
| } | |
| function functionCall(address target, bytes memory data) internal returns (bytes memory) {return functionCall(target, data, "Address: low-level call failed");} | |
| function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {return functionCallWithValue(target, data, 0, errorMessage);} | |
| function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {return functionCallWithValue(target, data, value, "Address: low-level call with value failed");} | |
| function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { | |
| require(address(this).balance >= value, "Address: insufficient balance for call"); | |
| require(isContract(target), "Address: call to non-contract"); | |
| (bool success, bytes memory returndata) = target.call{ value: value }(data); | |
| return _verifyCallResult(success, returndata, errorMessage); | |
| } | |
| function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { | |
| return functionStaticCall(target, data, "Address: low-level static call failed"); | |
| } | |
| function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) { | |
| require(isContract(target), "Address: static call to non-contract"); | |
| (bool success, bytes memory returndata) = target.staticcall(data); | |
| return _verifyCallResult(success, returndata, errorMessage); | |
| } | |
| function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { | |
| return functionDelegateCall(target, data, "Address: low-level delegate call failed"); | |
| } | |
| function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { | |
| require(isContract(target), "Address: delegate call to non-contract"); | |
| (bool success, bytes memory returndata) = target.delegatecall(data); | |
| return _verifyCallResult(success, returndata, errorMessage); | |
| } | |
| function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) { | |
| if (success) { return returndata; } else { | |
| if (returndata.length > 0) { | |
| assembly { | |
| let returndata_size := mload(returndata) | |
| revert(add(32, returndata), returndata_size) | |
| } | |
| } else {revert(errorMessage);} | |
| } | |
| } | |
| } | |
| abstract contract Ownable is Context { | |
| address private _owner; | |
| address private _previousOwner; | |
| uint256 private _lockTime; | |
| event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); | |
| constructor () { | |
| address msgSender = _msgSender(); | |
| _owner = msgSender; | |
| emit OwnershipTransferred(address(0), msgSender); | |
| } | |
| function owner() public view returns (address) { | |
| return _owner; | |
| } | |
| modifier onlyOwner() { | |
| require(_owner == _msgSender(), "Ownable: caller is not the owner"); | |
| _; | |
| } | |
| function renounceOwnership() public virtual onlyOwner { | |
| emit OwnershipTransferred(_owner, address(0)); | |
| _owner = address(0); | |
| } | |
| function transferOwnership(address newOwner) public virtual onlyOwner { | |
| require(newOwner != address(0), "Ownable: new owner is the zero address"); | |
| emit OwnershipTransferred(_owner, newOwner); | |
| _owner = newOwner; | |
| } | |
| function getUnlockTime() public view returns (uint256) { | |
| return _lockTime; | |
| } | |
| function lock(uint256 time) public virtual onlyOwner { | |
| _previousOwner = _owner; | |
| _owner = address(0); | |
| _lockTime = block.timestamp + time; | |
| emit OwnershipTransferred(_owner, address(0)); | |
| } | |
| function unlock() public virtual { | |
| require(_previousOwner == msg.sender, "Only the previous owner can unlock onwership"); | |
| require(block.timestamp > _lockTime , "The contract is still locked"); | |
| emit OwnershipTransferred(_owner, _previousOwner); | |
| _owner = _previousOwner; | |
| } | |
| } | |
| abstract contract Manageable is Context { | |
| address private _manager; | |
| event ManagementTransferred(address indexed previousManager, address indexed newManager); | |
| constructor(){ | |
| address msgSender = _msgSender(); | |
| _manager = msgSender; | |
| emit ManagementTransferred(address(0), msgSender); | |
| } | |
| function manager() public view returns(address){ return _manager; } | |
| modifier onlyManager(){ | |
| require(_manager == _msgSender(), "Manageable: caller is not the manager"); | |
| _; | |
| } | |
| function transferManagement(address newManager) external virtual onlyManager { | |
| emit ManagementTransferred(_manager, newManager); | |
| _manager = newManager; | |
| } | |
| } | |
| interface IPancakeV2Factory { | |
| event PairCreated(address indexed token0, address indexed token1, address pair, uint); | |
| function createPair(address tokenA, address tokenB) external returns (address pair); | |
| } | |
| interface IPancakeV2Router { | |
| function factory() external pure returns (address); | |
| function WETH() external pure returns (address); | |
| function addLiquidityETH( | |
| address token, | |
| uint amountTokenDesired, | |
| uint amountTokenMin, | |
| uint amountETHMin, | |
| address to, | |
| uint deadline | |
| ) external payable returns (uint amountToken, uint amountETH, uint liquidity); | |
| function swapExactTokensForETHSupportingFeeOnTransferTokens( | |
| uint amountIn, | |
| uint amountOutMin, | |
| address[] calldata path, | |
| address to, | |
| uint deadline | |
| ) external; | |
| } | |
| /** | |
| * SourceUnit: /home/dave/blockchain/tutorials&tests/safetoken-truffle/contracts/safetoken.sol | |
| */ | |
| /** | |
| * author: 0f0crypto <00ff00crypto@gmail.com> | |
| * discord: https://discord.gg/zn86MDCQcM | |
| * | |
| * Safetoken v1.0beta | |
| * | |
| * This is a rewrite of Safemoon in the hope to: | |
| * | |
| * - make it easier to change the tokenomics | |
| * - make it easier to maintain the code and develop it further | |
| * - remove redundant code | |
| * - fix some of the issues reported in the Safemoon audit (e.g. SSL-03) | |
| * https://www.certik.org/projects/safemoon | |
| * | |
| * | |
| * ░██████╗░█████╗░███████╗███████╗████████╗░█████╗░██╗░░██╗███████╗███╗░░██╗ | |
| * ██╔════╝██╔══██╗██╔════╝██╔════╝╚══██╔══╝██╔══██╗██║░██╔╝██╔════╝████╗░██║ | |
| * ╚█████╗░███████║█████╗░░█████╗░░░░░██║░░░██║░░██║█████═╝░█████╗░░██╔██╗██║ | |
| * ░╚═══██╗██╔══██║██╔══╝░░██╔══╝░░░░░██║░░░██║░░██║██╔═██╗░██╔══╝░░██║╚████║ | |
| * ██████╔╝██║░░██║██║░░░░░███████╗░░░██║░░░╚█████╔╝██║░╚██╗███████╗██║░╚███║ | |
| * ╚═════╝░╚═╝░░╚═╝╚═╝░░░░░╚══════╝░░░╚═╝░░░░╚════╝░╚═╝░░╚═╝╚══════╝╚═╝░░╚══╝ | |
| * | |
| * SPDX-License-Identifier: MIT | |
| */ | |
| pragma solidity ^0.8.4; | |
| /** | |
| * Tokenomics: | |
| * | |
| * Liquidity 5% | |
| * Redistribution 4% | |
| * Burn 1% | |
| * Charity 2% | |
| * Marketing 3% | |
| * Tip to the Dev 0.1% | |
| */ | |
| ////import "./safetoken-imports.sol"; | |
| /** | |
| * @dev If I did a good job you should not need to change anything apart from the values in the `Tokenomics`, | |
| * the actual name of the contract `SafeTokenV1Beta` at the very bottom **and** the `environment` into which | |
| * you are deploying the contract `SafeToken(Env.Testnet)` or `SafeToken(Env.MainnetV2)` etc. | |
| * | |
| * If you wish to disable a particular tax/fee just set it to zero (or comment it out/remove it). | |
| * | |
| * You can add (in theory) as many custom taxes/fees with dedicated wallet addresses if you want. | |
| * Nevertheless, I do not recommend using more than a few as the contract has not been tested | |
| * for more than the original number of taxes/fees, which is 6 (liquidity, redistribution, burn, | |
| * marketing, charity & tip to the dev). Furthermore, exchanges may impose a limit on the total | |
| * transaction fee (so that, for example, you cannot claim 100%). Usually this is done by limiting the | |
| * max value of slippage, for example, PancakeSwap max slippage is 49.9% and the fees total of more than | |
| * 35% will most likely fail there. | |
| * | |
| * NOTE: You shouldn't really remove the Rfi fee. If you do not wish to use RFI for your token, | |
| * you shouldn't be using this contract at all (you're just wasting gas if you do). | |
| * | |
| * NOTE: ignore the note below (anti-whale mech is not implemented yet) | |
| * If you wish to modify the anti-whale mech (progressive taxation) it will require a bit of coding. | |
| * I tried to make the integration as simple as possible via the `Antiwhale` contract, so the devs | |
| * know exactly where to look and what/how to make the necessary changes. There are many possibilites, | |
| * such as modifying the fees based on the tx amount (as % of TOTAL_SUPPLY), or sender's wallet balance | |
| * (as % of TOTAL_SUPPLY), including (but not limited to): | |
| * - progressive taxation by tax brackets (e.g <1%, 1-2%, 2-5%, 5-10%) | |
| * - progressive taxation by the % over a threshold (e.g. 1%) | |
| * - extra fee (e.g. double) over a threshold | |
| */ | |
| abstract contract Tokenomics { | |
| using SafeMath for uint256; | |
| // --------------------- Token Settings ------------------- // | |
| string internal constant NAME = "SafeToken.V1Beta"; | |
| string internal constant SYMBOL = "STKN.V1Beta"; | |
| uint16 internal constant FEES_DIVISOR = 10**3; | |
| uint8 internal constant DECIMALS = 6; | |
| uint256 internal constant ZEROES = 10**DECIMALS; | |
| uint256 private constant MAX = ~uint256(0); | |
| uint256 internal constant TOTAL_SUPPLY = 299792458 * ZEROES; | |
| uint256 internal _reflectedSupply = (MAX - (MAX % TOTAL_SUPPLY)); | |
| /** | |
| * @dev Set the maximum transaction amount allowed in a transfer. | |
| * | |
| * The default value is 1% of the total supply. | |
| * | |
| * NOTE: set the value to `TOTAL_SUPPLY` to have an unlimited max, i.e. | |
| * `maxTransactionAmount = TOTAL_SUPPLY;` | |
| */ | |
| uint256 internal constant maxTransactionAmount = TOTAL_SUPPLY / 100; // 1% of the total supply | |
| /** | |
| * @dev Set the maximum allowed balance in a wallet. | |
| * | |
| * The default value is 2% of the total supply. | |
| * | |
| * NOTE: set the value to 0 to have an unlimited max. | |
| * | |
| * ////IMPORTANT: This value MUST be greater than `numberOfTokensToSwapToLiquidity` set below, | |
| * otherwise the liquidity swap will never be executed | |
| */ | |
| uint256 internal constant maxWalletBalance = TOTAL_SUPPLY / 50; // 2% of the total supply | |
| /** | |
| * @dev Set the number of tokens to swap and add to liquidity. | |
| * | |
| * Whenever the contract's balance reaches this number of tokens, swap & liquify will be | |
| * executed in the very next transfer (via the `_beforeTokenTransfer`) | |
| * | |
| * If the `FeeType.Liquidity` is enabled in `FeesSettings`, the given % of each transaction will be first | |
| * sent to the contract address. Once the contract's balance reaches `numberOfTokensToSwapToLiquidity` the | |
| * `swapAndLiquify` of `Liquifier` will be executed. Half of the tokens will be swapped for ETH | |
| * (or BNB on BSC) and together with the other half converted into a Token-ETH/Token-BNB LP Token. | |
| * | |
| * See: `Liquifier` | |
| */ | |
| uint256 internal constant numberOfTokensToSwapToLiquidity = TOTAL_SUPPLY / 1000; // 0.1% of the total supply | |
| // --------------------- Fees Settings ------------------- // | |
| /** | |
| * @dev To add/edit/remove fees scroll down to the `addFees` function below | |
| */ | |
| address internal charityAddress = 0x3De92b2308f4acBA823fA58A0C02633380d570eE; | |
| address internal marketingAddress = 0x65b4eF486971839517d6FF08Af90fD69F26FbB1B; | |
| /** | |
| * @dev You can change the value of the burn address to pretty much anything | |
| * that's (clearly) a non-random address, i.e. for which the probability of | |
| * someone having the private key is (virtually) 0. For example, 0x00.....1, | |
| * 0x111...111, 0x12345.....12345, etc. | |
| * | |
| * NOTE: This does NOT need to be the zero address, adress(0) = 0x000...000; | |
| * | |
| * Trasfering tokens to the burn address is good for optics/marketing. Nevertheless | |
| * if the burn address is excluded from rewards (unlike in Safemoon), sending tokens | |
| * to the burn address actually improves redistribution to holders (as they will | |
| * have a larger % of tokens in non-excluded accounts) | |
| * | |
| * p.s. the address below is the speed of light in vacuum in m/s (expressed in decimals), | |
| * the hex value is 0x0000000000000000000000000000000011dE784A; :) | |
| * | |
| * Here are the values of some other fundamental constants to use: | |
| * 0x0000000000000000000000000000000602214076 (Avogardo constant) | |
| * 0x0000000000000000000000000000000001380649 (Boltzmann constant) | |
| * 0x2718281828459045235360287471352662497757 (e) | |
| * 0x0000000000000000000000000000001602176634 (elementary charge) | |
| * 0x0000000000000000000000000200231930436256 (electron g-factor) | |
| * 0x0000000000000000000000000000091093837015 (electron mass) | |
| * 0x0000000000000000000000000000137035999084 (fine structure constant) | |
| * 0x0577215664901532860606512090082402431042 (Euler-Mascheroni constant) | |
| * 0x1618033988749894848204586834365638117720 (golden ratio) | |
| * 0x0000000000000000000000000000009192631770 (hyperfine transition fq) | |
| * 0x0000000000000000000000000000010011659208 (muom g-2) | |
| * 0x3141592653589793238462643383279502884197 (pi) | |
| * 0x0000000000000000000000000000000662607015 (Planck's constant) | |
| * 0x0000000000000000000000000000001054571817 (reduced Planck's constant) | |
| * 0x1414213562373095048801688724209698078569 (sqrt(2)) | |
| */ | |
| address internal burnAddress = 0x0000000000000000000000000000000299792458; | |
| /** | |
| * @dev You can disable this but if you feel generous I'd appreciate the 0.1% | |
| * donation for rewriting Safemoon and making everyone's life a little easier | |
| * | |
| * If you keep this tip enabled, let me know in Discord: https://discord.gg/zn86MDCQcM | |
| * and you'll be added to the partners section to promote your token. | |
| */ | |
| address internal tipToTheDev = 0x2d67D0A35192EB8cE9DF4988686553360A6E424f; | |
| enum FeeType { Antiwhale, Burn, Liquidity, Rfi, External, ExternalToETH } | |
| struct Fee { | |
| FeeType name; | |
| uint256 value; | |
| address recipient; | |
| uint256 total; | |
| } | |
| Fee[] internal fees; | |
| uint256 internal sumOfFees; | |
| constructor() { | |
| _addFees(); | |
| } | |
| function _addFee(FeeType name, uint256 value, address recipient) private { | |
| fees.push( Fee(name, value, recipient, 0 ) ); | |
| sumOfFees += value; | |
| } | |
| function _addFees() private { | |
| /** | |
| * The RFI recipient is ignored but we need to give a valid address value | |
| * | |
| * CAUTION: If you don't want to use RFI this implementation isn't really for you! | |
| * There are much more efficient and cleaner token contracts without RFI | |
| * so you should use one of those | |
| * | |
| * The value of fees is given in part per 1000 (based on the value of FEES_DIVISOR), | |
| * e.g. for 5% use 50, for 3.5% use 35, etc. | |
| */ | |
| _addFee(FeeType.Rfi, 40, address(this) ); | |
| _addFee(FeeType.Burn, 10, burnAddress ); | |
| _addFee(FeeType.Liquidity, 50, address(this) ); | |
| _addFee(FeeType.External, 20, charityAddress ); | |
| _addFee(FeeType.External, 30, marketingAddress ); | |
| // 0.1% as a tip to the dev; feel free to remove this! | |
| _addFee(FeeType.ExternalToETH, 1, tipToTheDev ); | |
| } | |
| function _getFeesCount() internal view returns (uint256){ return fees.length; } | |
| function _getFeeStruct(uint256 index) private view returns(Fee storage){ | |
| require( index >= 0 && index < fees.length, "FeesSettings._getFeeStruct: Fee index out of bounds"); | |
| return fees[index]; | |
| } | |
| function _getFee(uint256 index) internal view returns (FeeType, uint256, address, uint256){ | |
| Fee memory fee = _getFeeStruct(index); | |
| return ( fee.name, fee.value, fee.recipient, fee.total ); | |
| } | |
| function _addFeeCollectedAmount(uint256 index, uint256 amount) internal { | |
| Fee storage fee = _getFeeStruct(index); | |
| fee.total = fee.total.add(amount); | |
| } | |
| // function getCollectedFeeTotal(uint256 index) external view returns (uint256){ | |
| function getCollectedFeeTotal(uint256 index) internal view returns (uint256){ | |
| Fee memory fee = _getFeeStruct(index); | |
| return fee.total; | |
| } | |
| } | |
| abstract contract Presaleable is Manageable { | |
| bool internal isInPresale; | |
| function setPreseableEnabled(bool value) external onlyManager { | |
| isInPresale = value; | |
| } | |
| } | |
| abstract contract BaseRfiToken is IERC20, IERC20Metadata, Ownable, Presaleable, Tokenomics { | |
| using SafeMath for uint256; | |
| using Address for address; | |
| mapping (address => uint256) internal _reflectedBalances; | |
| mapping (address => uint256) internal _balances; | |
| mapping (address => mapping (address => uint256)) internal _allowances; | |
| mapping (address => bool) internal _isExcludedFromFee; | |
| mapping (address => bool) internal _isExcludedFromRewards; | |
| address[] private _excluded; | |
| constructor(){ | |
| _reflectedBalances[owner()] = _reflectedSupply; | |
| // exclude owner and this contract from fee | |
| _isExcludedFromFee[owner()] = true; | |
| _isExcludedFromFee[address(this)] = true; | |
| // exclude the owner and this contract from rewards | |
| _exclude(owner()); | |
| _exclude(address(this)); | |
| emit Transfer(address(0), owner(), TOTAL_SUPPLY); | |
| } | |
| /** Functions required by IERC20Metadat **/ | |
| function name() external pure override returns (string memory) { return NAME; } | |
| function symbol() external pure override returns (string memory) { return SYMBOL; } | |
| function decimals() external pure override returns (uint8) { return DECIMALS; } | |
| /** Functions required by IERC20Metadat - END **/ | |
| /** Functions required by IERC20 **/ | |
| function totalSupply() external pure override returns (uint256) { | |
| return TOTAL_SUPPLY; | |
| } | |
| function balanceOf(address account) public view override returns (uint256){ | |
| if (_isExcludedFromRewards[account]) return _balances[account]; | |
| return tokenFromReflection(_reflectedBalances[account]); | |
| } | |
| function transfer(address recipient, uint256 amount) external override returns (bool){ | |
| _transfer(_msgSender(), recipient, amount); | |
| return true; | |
| } | |
| function allowance(address owner, address spender) external view override returns (uint256){ | |
| return _allowances[owner][spender]; | |
| } | |
| function approve(address spender, uint256 amount) external override returns (bool) { | |
| _approve(_msgSender(), spender, amount); | |
| return true; | |
| } | |
| function transferFrom(address sender, address recipient, uint256 amount) external override returns (bool){ | |
| _transfer(sender, recipient, amount); | |
| _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); | |
| return true; | |
| } | |
| /** Functions required by IERC20 - END **/ | |
| /** | |
| * @dev this is really a "soft" burn (total supply is not reduced). RFI holders | |
| * get two benefits from burning tokens: | |
| * | |
| * 1) Tokens in the burn address increase the % of tokens held by holders not | |
| * excluded from rewards (assuming the burn address is excluded) | |
| * 2) Tokens in the burn address cannot be sold (which in turn draing the | |
| * liquidity pool) | |
| * | |
| * | |
| * In RFI holders already get % of each transaction so the value of their tokens | |
| * increases (in a way). Therefore there is really no need to do a "hard" burn | |
| * (reduce the total supply). What matters (in RFI) is to make sure that a large | |
| * amount of tokens cannot be sold = draining the liquidity pool = lowering the | |
| * value of tokens holders own. For this purpose, transfering tokens to a (vanity) | |
| * burn address is the most appropriate way to "burn". | |
| * | |
| * There is an extra check placed into the `transfer` function to make sure the | |
| * burn address cannot withdraw the tokens is has (although the chance of someone | |
| * having/finding the private key is virtually zero). | |
| */ | |
| function burn(uint256 amount) external { | |
| address sender = _msgSender(); | |
| require(sender != address(0), "BaseRfiToken: burn from the zero address"); | |
| require(sender != address(burnAddress), "BaseRfiToken: burn from the burn address"); | |
| uint256 balance = balanceOf(sender); | |
| require(balance >= amount, "BaseRfiToken: burn amount exceeds balance"); | |
| uint256 reflectedAmount = amount.mul(_getCurrentRate()); | |
| // remove the amount from the sender's balance first | |
| _reflectedBalances[sender] = _reflectedBalances[sender].sub(reflectedAmount); | |
| if (_isExcludedFromRewards[sender]) | |
| _balances[sender] = _balances[sender].sub(amount); | |
| _burnTokens( sender, amount, reflectedAmount ); | |
| } | |
| /** | |
| * @dev "Soft" burns the specified amount of tokens by sending them | |
| * to the burn address | |
| */ | |
| function _burnTokens(address sender, uint256 tBurn, uint256 rBurn) internal { | |
| /** | |
| * @dev Do not reduce _totalSupply and/or _reflectedSupply. (soft) burning by sending | |
| * tokens to the burn address (which should be excluded from rewards) is sufficient | |
| * in RFI | |
| */ | |
| _reflectedBalances[burnAddress] = _reflectedBalances[burnAddress].add(rBurn); | |
| if (_isExcludedFromRewards[burnAddress]) | |
| _balances[burnAddress] = _balances[burnAddress].add(tBurn); | |
| /** | |
| * @dev Emit the event so that the burn address balance is updated (on bscscan) | |
| */ | |
| emit Transfer(sender, burnAddress, tBurn); | |
| } | |
| function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { | |
| _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); | |
| return true; | |
| } | |
| 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; | |
| } | |
| function isExcludedFromReward(address account) external view returns (bool) { | |
| return _isExcludedFromRewards[account]; | |
| } | |
| /** | |
| * @dev Calculates and returns the reflected amount for the given amount with or without | |
| * the transfer fees (deductTransferFee true/false) | |
| */ | |
| function reflectionFromToken(uint256 tAmount, bool deductTransferFee) external view returns(uint256) { | |
| require(tAmount <= TOTAL_SUPPLY, "Amount must be less than supply"); | |
| if (!deductTransferFee) { | |
| (uint256 rAmount,,,,) = _getValues(tAmount,0); | |
| return rAmount; | |
| } else { | |
| (,uint256 rTransferAmount,,,) = _getValues(tAmount,_getSumOfFees(_msgSender(), tAmount)); | |
| return rTransferAmount; | |
| } | |
| } | |
| /** | |
| * @dev Calculates and returns the amount of tokens corresponding to the given reflected amount. | |
| */ | |
| function tokenFromReflection(uint256 rAmount) internal view returns(uint256) { | |
| require(rAmount <= _reflectedSupply, "Amount must be less than total reflections"); | |
| uint256 currentRate = _getCurrentRate(); | |
| return rAmount.div(currentRate); | |
| } | |
| function excludeFromReward(address account) external onlyOwner() { | |
| require(!_isExcludedFromRewards[account], "Account is not included"); | |
| _exclude(account); | |
| } | |
| function _exclude(address account) internal { | |
| if(_reflectedBalances[account] > 0) { | |
| _balances[account] = tokenFromReflection(_reflectedBalances[account]); | |
| } | |
| _isExcludedFromRewards[account] = true; | |
| _excluded.push(account); | |
| } | |
| function includeInReward(address account) external onlyOwner() { | |
| require(_isExcludedFromRewards[account], "Account is not excluded"); | |
| for (uint256 i = 0; i < _excluded.length; i++) { | |
| if (_excluded[i] == account) { | |
| _excluded[i] = _excluded[_excluded.length - 1]; | |
| _balances[account] = 0; | |
| _isExcludedFromRewards[account] = false; | |
| _excluded.pop(); | |
| break; | |
| } | |
| } | |
| } | |
| function setExcludedFromFee(address account, bool value) external onlyOwner { _isExcludedFromFee[account] = value; } | |
| function isExcludedFromFee(address account) public view returns(bool) { return _isExcludedFromFee[account]; } | |
| function _approve(address owner, address spender, uint256 amount) internal { | |
| require(owner != address(0), "BaseRfiToken: approve from the zero address"); | |
| require(spender != address(0), "BaseRfiToken: approve to the zero address"); | |
| _allowances[owner][spender] = amount; | |
| emit Approval(owner, spender, amount); | |
| } | |
| /** | |
| */ | |
| function _isUnlimitedSender(address account) internal view returns(bool){ | |
| // the owner should be the only whitelisted sender | |
| return (account == owner()); | |
| } | |
| /** | |
| */ | |
| function _isUnlimitedRecipient(address account) internal view returns(bool){ | |
| // the owner should be a white-listed recipient | |
| // and anyone should be able to burn as many tokens as | |
| // he/she wants | |
| return (account == owner() || account == burnAddress); | |
| } | |
| function _transfer(address sender, address recipient, uint256 amount) private { | |
| require(sender != address(0), "BaseRfiToken: transfer from the zero address"); | |
| require(recipient != address(0), "BaseRfiToken: transfer to the zero address"); | |
| require(sender != address(burnAddress), "BaseRfiToken: transfer from the burn address"); | |
| require(amount > 0, "Transfer amount must be greater than zero"); | |
| // indicates whether or not feee should be deducted from the transfer | |
| bool takeFee = true; | |
| if ( isInPresale ){ takeFee = false; } | |
| else { | |
| /** | |
| * Check the amount is within the max allowed limit as long as a | |
| * unlimited sender/recepient is not involved in the transaction | |
| */ | |
| if ( amount > maxTransactionAmount && !_isUnlimitedSender(sender) && !_isUnlimitedRecipient(recipient) ){ | |
| revert("Transfer amount exceeds the maxTxAmount."); | |
| } | |
| /** | |
| * The pair needs to excluded from the max wallet balance check; | |
| * selling tokens is sending them back to the pair (without this | |
| * check, selling tokens would not work if the pair's balance | |
| * was over the allowed max) | |
| * | |
| * Note: This does NOT take into account the fees which will be deducted | |
| * from the amount. As such it could be a bit confusing | |
| */ | |
| if ( maxWalletBalance > 0 && !_isUnlimitedSender(sender) && !_isUnlimitedRecipient(recipient) && !_isV2Pair(recipient) ){ | |
| uint256 recipientBalance = balanceOf(recipient); | |
| require(recipientBalance + amount <= maxWalletBalance, "New balance would exceed the maxWalletBalance"); | |
| } | |
| } | |
| // if any account belongs to _isExcludedFromFee account then remove the fee | |
| if(_isExcludedFromFee[sender] || _isExcludedFromFee[recipient]){ takeFee = false; } | |
| _beforeTokenTransfer(sender, recipient, amount, takeFee); | |
| _transferTokens(sender, recipient, amount, takeFee); | |
| } | |
| function _transferTokens(address sender, address recipient, uint256 amount, bool takeFee) private { | |
| /** | |
| * We don't need to know anything about the individual fees here | |
| * (like Safemoon does with `_getValues`). All that is required | |
| * for the transfer is the sum of all fees to calculate the % of the total | |
| * transaction amount which should be transferred to the recipient. | |
| * | |
| * The `_takeFees` call will/should take care of the individual fees | |
| */ | |
| uint256 sumOfFees = _getSumOfFees(sender, amount); | |
| if ( !takeFee ){ sumOfFees = 0; } | |
| (uint256 rAmount, uint256 rTransferAmount, uint256 tAmount, uint256 tTransferAmount, uint256 currentRate ) = _getValues(amount, sumOfFees); | |
| /** | |
| * Sender's and Recipient's reflected balances must be always updated regardless of | |
| * whether they are excluded from rewards or not. | |
| */ | |
| _reflectedBalances[sender] = _reflectedBalances[sender].sub(rAmount); | |
| _reflectedBalances[recipient] = _reflectedBalances[recipient].add(rTransferAmount); | |
| /** | |
| * Update the true/nominal balances for excluded accounts | |
| */ | |
| if (_isExcludedFromRewards[sender]){ _balances[sender] = _balances[sender].sub(tAmount); } | |
| if (_isExcludedFromRewards[recipient] ){ _balances[recipient] = _balances[recipient].add(tTransferAmount); } | |
| _takeFees( amount, currentRate, sumOfFees ); | |
| emit Transfer(sender, recipient, tTransferAmount); | |
| } | |
| function _takeFees(uint256 amount, uint256 currentRate, uint256 sumOfFees ) private { | |
| if ( sumOfFees > 0 && !isInPresale ){ | |
| _takeTransactionFees(amount, currentRate); | |
| } | |
| } | |
| function _getValues(uint256 tAmount, uint256 feesSum) internal view returns (uint256, uint256, uint256, uint256, uint256) { | |
| uint256 tTotalFees = tAmount.mul(feesSum).div(FEES_DIVISOR); | |
| uint256 tTransferAmount = tAmount.sub(tTotalFees); | |
| uint256 currentRate = _getCurrentRate(); | |
| uint256 rAmount = tAmount.mul(currentRate); | |
| uint256 rTotalFees = tTotalFees.mul(currentRate); | |
| uint256 rTransferAmount = rAmount.sub(rTotalFees); | |
| return (rAmount, rTransferAmount, tAmount, tTransferAmount, currentRate); | |
| } | |
| function _getCurrentRate() internal view returns(uint256) { | |
| (uint256 rSupply, uint256 tSupply) = _getCurrentSupply(); | |
| return rSupply.div(tSupply); | |
| } | |
| function _getCurrentSupply() internal view returns(uint256, uint256) { | |
| uint256 rSupply = _reflectedSupply; | |
| uint256 tSupply = TOTAL_SUPPLY; | |
| /** | |
| * The code below removes balances of addresses excluded from rewards from | |
| * rSupply and tSupply, which effectively increases the % of transaction fees | |
| * delivered to non-excluded holders | |
| */ | |
| for (uint256 i = 0; i < _excluded.length; i++) { | |
| if (_reflectedBalances[_excluded[i]] > rSupply || _balances[_excluded[i]] > tSupply) return (_reflectedSupply, TOTAL_SUPPLY); | |
| rSupply = rSupply.sub(_reflectedBalances[_excluded[i]]); | |
| tSupply = tSupply.sub(_balances[_excluded[i]]); | |
| } | |
| if (tSupply == 0 || rSupply < _reflectedSupply.div(TOTAL_SUPPLY)) return (_reflectedSupply, TOTAL_SUPPLY); | |
| return (rSupply, tSupply); | |
| } | |
| /** | |
| * @dev Hook that is called before any transfer of tokens. | |
| */ | |
| function _beforeTokenTransfer(address sender, address recipient, uint256 amount, bool takeFee) internal virtual; | |
| /** | |
| * @dev Returns the total sum of fees to be processed in each transaction. | |
| * | |
| * To separate concerns this contract (class) will take care of ONLY handling RFI, i.e. | |
| * changing the rates and updating the holder's balance (via `_redistribute`). | |
| * It is the responsibility of the dev/user to handle all other fees and taxes | |
| * in the appropriate contracts (classes). | |
| */ | |
| function _getSumOfFees(address sender, uint256 amount) internal view virtual returns (uint256); | |
| /** | |
| * @dev A delegate which should return true if the given address is the V2 Pair and false otherwise | |
| */ | |
| function _isV2Pair(address account) internal view virtual returns(bool); | |
| /** | |
| * @dev Redistributes the specified amount among the current holders via the reflect.finance | |
| * algorithm, i.e. by updating the _reflectedSupply (_rSupply) which ultimately adjusts the | |
| * current rate used by `tokenFromReflection` and, in turn, the value returns from `balanceOf`. | |
| * This is the bit of clever math which allows rfi to redistribute the fee without | |
| * having to iterate through all holders. | |
| * | |
| * Visit our discord at https://discord.gg/dAmr6eUTpM | |
| */ | |
| function _redistribute(uint256 amount, uint256 currentRate, uint256 fee, uint256 index) internal { | |
| uint256 tFee = amount.mul(fee).div(FEES_DIVISOR); | |
| uint256 rFee = tFee.mul(currentRate); | |
| _reflectedSupply = _reflectedSupply.sub(rFee); | |
| _addFeeCollectedAmount(index, tFee); | |
| } | |
| /** | |
| * @dev Hook that is called before the `Transfer` event is emitted if fees are enabled for the transfer | |
| */ | |
| function _takeTransactionFees(uint256 amount, uint256 currentRate) internal virtual; | |
| } | |
| abstract contract Liquifier is Ownable, Manageable { | |
| using SafeMath for uint256; | |
| uint256 private withdrawableBalance; | |
| enum Env {Testnet, MainnetV1, MainnetV2} | |
| Env private _env; | |
| // PancakeSwap V1 | |
| address private _mainnetRouterV1Address = 0x05fF2B0DB69458A0750badebc4f9e13aDd608C7F; | |
| // PancakeSwap V2 | |
| address private _mainnetRouterV2Address = 0x10ED43C718714eb63d5aA57B78B54704E256024E; | |
| // Testnet | |
| // address private _testnetRouterAddress = 0xD99D1c33F9fC3444f8101754aBC46c52416550D1; | |
| // PancakeSwap Testnet = https://pancake.kiemtienonline360.com/ | |
| address private _testnetRouterAddress = 0x9Ac64Cc6e4415144C455BD8E4837Fea55603e5c3; | |
| IPancakeV2Router internal _router; | |
| address internal _pair; | |
| bool private inSwapAndLiquify; | |
| bool private swapAndLiquifyEnabled = true; | |
| uint256 private maxTransactionAmount; | |
| uint256 private numberOfTokensToSwapToLiquidity; | |
| modifier lockTheSwap { | |
| inSwapAndLiquify = true; | |
| _; | |
| inSwapAndLiquify = false; | |
| } | |
| event RouterSet(address indexed router); | |
| event SwapAndLiquify(uint256 tokensSwapped, uint256 ethReceived, uint256 tokensIntoLiquidity); | |
| event SwapAndLiquifyEnabledUpdated(bool enabled); | |
| event LiquidityAdded(uint256 tokenAmountSent, uint256 ethAmountSent, uint256 liquidity); | |
| receive() external payable {} | |
| function initializeLiquiditySwapper(Env env, uint256 maxTx, uint256 liquifyAmount) internal { | |
| _env = env; | |
| if (_env == Env.MainnetV1){ _setRouterAddress(_mainnetRouterV1Address); } | |
| else if (_env == Env.MainnetV2){ _setRouterAddress(_mainnetRouterV2Address); } | |
| else /*(_env == Env.Testnet)*/{ _setRouterAddress(_testnetRouterAddress); } | |
| maxTransactionAmount = maxTx; | |
| numberOfTokensToSwapToLiquidity = liquifyAmount; | |
| } | |
| /** | |
| * NOTE: passing the `contractTokenBalance` here is preferred to creating `balanceOfDelegate` | |
| */ | |
| function liquify(uint256 contractTokenBalance, address sender) internal { | |
| if (contractTokenBalance >= maxTransactionAmount) contractTokenBalance = maxTransactionAmount; | |
| bool isOverRequiredTokenBalance = ( contractTokenBalance >= numberOfTokensToSwapToLiquidity ); | |
| /** | |
| * - first check if the contract has collected enough tokens to swap and liquify | |
| * - then check swap and liquify is enabled | |
| * - then make sure not to get caught in a circular liquidity event | |
| * - finally, don't swap & liquify if the sender is the uniswap pair | |
| */ | |
| if ( isOverRequiredTokenBalance && swapAndLiquifyEnabled && !inSwapAndLiquify && (sender != _pair) ){ | |
| // TODO check if the `(sender != _pair)` is necessary because that basically | |
| // stops swap and liquify for all "buy" transactions | |
| _swapAndLiquify(contractTokenBalance); | |
| } | |
| } | |
| /** | |
| * @dev sets the router address and created the router, factory pair to enable | |
| * swapping and liquifying (contract) tokens | |
| */ | |
| function _setRouterAddress(address router) private { | |
| IPancakeV2Router _newPancakeRouter = IPancakeV2Router(router); | |
| _pair = IPancakeV2Factory(_newPancakeRouter.factory()).createPair(address(this), _newPancakeRouter.WETH()); | |
| _router = _newPancakeRouter; | |
| emit RouterSet(router); | |
| } | |
| function _swapAndLiquify(uint256 amount) private lockTheSwap { | |
| // split the contract balance into halves | |
| uint256 half = amount.div(2); | |
| uint256 otherHalf = amount.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); // <- 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] = _router.WETH(); | |
| _approveDelegate(address(this), address(_router), tokenAmount); | |
| // make the swap | |
| _router.swapExactTokensForETHSupportingFeeOnTransferTokens( | |
| tokenAmount, | |
| // The minimum amount of output tokens that must be received for the transaction not to revert. | |
| // 0 = accept any amount (slippage is inevitable) | |
| 0, | |
| path, | |
| address(this), | |
| block.timestamp | |
| ); | |
| } | |
| function _addLiquidity(uint256 tokenAmount, uint256 ethAmount) private { | |
| // approve token transfer to cover all possible scenarios | |
| _approveDelegate(address(this), address(_router), tokenAmount); | |
| // add tahe liquidity | |
| (uint256 tokenAmountSent, uint256 ethAmountSent, uint256 liquidity) = _router.addLiquidityETH{value: ethAmount}( | |
| address(this), | |
| tokenAmount, | |
| // Bounds the extent to which the WETH/token price can go up before the transaction reverts. | |
| // Must be <= amountTokenDesired; 0 = accept any amount (slippage is inevitable) | |
| 0, | |
| // Bounds the extent to which the token/WETH price can go up before the transaction reverts. | |
| // 0 = accept any amount (slippage is inevitable) | |
| 0, | |
| // this is a centralized risk if the owner's account is ever compromised (see Certik SSL-04) | |
| owner(), | |
| block.timestamp | |
| ); | |
| // fix the forever locked BNBs as per the certik's audit | |
| /** | |
| * The swapAndLiquify function converts half of the contractTokenBalance SafeMoon tokens to BNB. | |
| * For every swapAndLiquify function call, a small amount of BNB remains in the contract. | |
| * This amount grows over time with the swapAndLiquify function being called throughout the life | |
| * of the contract. The Safemoon contract does not contain a method to withdraw these funds, | |
| * and the BNB will be locked in the Safemoon contract forever. | |
| */ | |
| withdrawableBalance = address(this).balance; | |
| emit LiquidityAdded(tokenAmountSent, ethAmountSent, liquidity); | |
| } | |
| /** | |
| * @dev Sets the uniswapV2 pair (router & factory) for swapping and liquifying tokens | |
| */ | |
| function setRouterAddress(address router) external onlyManager() { | |
| _setRouterAddress(router); | |
| } | |
| /** | |
| * @dev Sends the swap and liquify flag to the provided value. If set to `false` tokens collected in the contract will | |
| * NOT be converted into liquidity. | |
| */ | |
| function setSwapAndLiquifyEnabled(bool enabled) external onlyManager { | |
| swapAndLiquifyEnabled = enabled; | |
| emit SwapAndLiquifyEnabledUpdated(swapAndLiquifyEnabled); | |
| } | |
| /** | |
| * @dev The owner can withdraw ETH(BNB) collected in the contract from `swapAndLiquify` | |
| * or if someone (accidentally) sends ETH/BNB directly to the contract. | |
| * | |
| * Note: This addresses the contract flaw pointed out in the Certik Audit of Safemoon (SSL-03): | |
| * | |
| * The swapAndLiquify function converts half of the contractTokenBalance SafeMoon tokens to BNB. | |
| * For every swapAndLiquify function call, a small amount of BNB remains in the contract. | |
| * This amount grows over time with the swapAndLiquify function being called | |
| * throughout the life of the contract. The Safemoon contract does not contain a method | |
| * to withdraw these funds, and the BNB will be locked in the Safemoon contract forever. | |
| * https://www.certik.org/projects/safemoon | |
| */ | |
| function withdrawLockedEth(address payable recipient) external onlyManager(){ | |
| require(recipient != address(0), "Cannot withdraw the ETH balance to the zero address"); | |
| require(withdrawableBalance > 0, "The ETH balance must be greater than 0"); | |
| // prevent re-entrancy attacks | |
| uint256 amount = withdrawableBalance; | |
| withdrawableBalance = 0; | |
| recipient.transfer(amount); | |
| } | |
| /** | |
| * @dev Use this delegate instead of having (unnecessarily) extend `BaseRfiToken` to gained access | |
| * to the `_approve` function. | |
| */ | |
| function _approveDelegate(address owner, address spender, uint256 amount) internal virtual; | |
| } | |
| ////////////////////////////////////////////////////////////////////////// | |
| abstract contract Antiwhale is Tokenomics { | |
| /** | |
| * @dev Returns the total sum of fees (in percents / per-mille - this depends on the FEES_DIVISOR value) | |
| * | |
| * NOTE: Currently this is just a placeholder. The parameters passed to this function are the | |
| * sender's token balance and the transfer amount. An *antiwhale* mechanics can use these | |
| * values to adjust the fees total for each tx | |
| */ | |
| // function _getAntiwhaleFees(uint256 sendersBalance, uint256 amount) internal view returns (uint256){ | |
| function _getAntiwhaleFees(uint256, uint256) internal view returns (uint256){ | |
| return sumOfFees; | |
| } | |
| } | |
| ////////////////////////////////////////////////////////////////////////// | |
| abstract contract SafeToken is BaseRfiToken, Liquifier, Antiwhale { | |
| using SafeMath for uint256; | |
| // constructor(string memory _name, string memory _symbol, uint8 _decimals){ | |
| constructor(Env _env){ | |
| initializeLiquiditySwapper(_env, maxTransactionAmount, numberOfTokensToSwapToLiquidity); | |
| // exclude the pair address from rewards - we don't want to redistribute | |
| // tx fees to these two; redistribution is only for holders, dah! | |
| _exclude(_pair); | |
| _exclude(burnAddress); | |
| } | |
| function _isV2Pair(address account) internal view override returns(bool){ | |
| return (account == _pair); | |
| } | |
| function _getSumOfFees(address sender, uint256 amount) internal view override returns (uint256){ | |
| return _getAntiwhaleFees(balanceOf(sender), amount); | |
| } | |
| // function _beforeTokenTransfer(address sender, address recipient, uint256 amount, bool takeFee) internal override { | |
| function _beforeTokenTransfer(address sender, address , uint256 , bool ) internal override { | |
| if ( !isInPresale ){ | |
| uint256 contractTokenBalance = balanceOf(address(this)); | |
| liquify( contractTokenBalance, sender ); | |
| } | |
| } | |
| function _takeTransactionFees(uint256 amount, uint256 currentRate) internal override { | |
| if( isInPresale ){ return; } | |
| uint256 feesCount = _getFeesCount(); | |
| for (uint256 index = 0; index < feesCount; index++ ){ | |
| (FeeType name, uint256 value, address recipient,) = _getFee(index); | |
| // no need to check value < 0 as the value is uint (i.e. from 0 to 2^256-1) | |
| if ( value == 0 ) continue; | |
| if ( name == FeeType.Rfi ){ | |
| _redistribute( amount, currentRate, value, index ); | |
| } | |
| else if ( name == FeeType.Burn ){ | |
| _burn( amount, currentRate, value, index ); | |
| } | |
| else if ( name == FeeType.Antiwhale){ | |
| // TODO | |
| } | |
| else if ( name == FeeType.ExternalToETH){ | |
| _takeFeeToETH( amount, currentRate, value, recipient, index ); | |
| } | |
| else { | |
| _takeFee( amount, currentRate, value, recipient, index ); | |
| } | |
| } | |
| } | |
| function _burn(uint256 amount, uint256 currentRate, uint256 fee, uint256 index) private { | |
| uint256 tBurn = amount.mul(fee).div(FEES_DIVISOR); | |
| uint256 rBurn = tBurn.mul(currentRate); | |
| _burnTokens(address(this), tBurn, rBurn); | |
| _addFeeCollectedAmount(index, tBurn); | |
| } | |
| function _takeFee(uint256 amount, uint256 currentRate, uint256 fee, address recipient, uint256 index) private { | |
| uint256 tAmount = amount.mul(fee).div(FEES_DIVISOR); | |
| uint256 rAmount = tAmount.mul(currentRate); | |
| _reflectedBalances[recipient] = _reflectedBalances[recipient].add(rAmount); | |
| if(_isExcludedFromRewards[recipient]) | |
| _balances[recipient] = _balances[recipient].add(tAmount); | |
| _addFeeCollectedAmount(index, tAmount); | |
| } | |
| /** | |
| * @dev When implemented this will convert the fee amount of tokens into ETH/BNB | |
| * and send to the recipient's wallet. Note that this reduces liquidity so it | |
| * might be a good idea to add a % into the liquidity fee for % you take our through | |
| * this method (just a suggestions) | |
| */ | |
| function _takeFeeToETH(uint256 amount, uint256 currentRate, uint256 fee, address recipient, uint256 index) private { | |
| _takeFee(amount, currentRate, fee, recipient, index); | |
| } | |
| function _approveDelegate(address owner, address spender, uint256 amount) internal override { | |
| _approve(owner, spender, amount); | |
| } | |
| } | |
| contract SafeTokenV1Beta is SafeToken{ | |
| constructor() SafeToken(Env.Testnet){ | |
| // pre-approve the initial liquidity supply (to safe a bit of time) | |
| _approve(owner(),address(_router), ~uint256(0)); | |
| } | |
| } | |
| /** | |
| * Todo (beta): | |
| * | |
| * - reorganize the sol file(s) to make put everything editable in a single .sol file | |
| * and keep all other code in other .sol file(s) | |
| * - move variable values initialized in the contract to be constructor parameters | |
| * - add/remove setters/getter where appropriate | |
| * - add unit tests (via ganache-cli + truffle) | |
| * - add full dev evn (truffle) folders & files | |
| * | |
| * Todo: | |
| * | |
| * - implement `_takeFeeToETH` (currently just calls `_takeFee`) | |
| * - implement anti whale mechanics (via different pre-created libraries?), eg progressive tax | |
| * - implement anti sell mechanics | |
| * - address SSL-04 | Centralized risk in addLiquidity - https://www.certik.org/projects/safemoon | |
| * change the recipient to `address(this)` or implement a decentralized mechanism or | |
| * smart-contract solution | |
| * - change Uniswap to PancakeSwap in contract/interface names and local var names | |
| * - change ETH to BNB in names and comments | |
| */ | |
| /** | |
| * Tests to pass: | |
| * | |
| * - Tokenomics fees can be added/removed/edited | |
| * - Tokenomics fees are correctly taken from each (qualifying) transaction | |
| * - The RFI fee is correctly distributed among holders (which are not excluded from rewards) | |
| * - `swapAndLiquify` works correctly when the threshold balance is reached | |
| * - `maxTransactionAmount` works correctly and *unlimited* accounts are not subject to the limit | |
| * - `maxWalletBalance` works correctly and *unlimited* accounts are not subject to the limit | |
| * - accounts excluded from fees are not subjecto tx fees | |
| * - accounts excluded from rewards do not share in rewards | |
| * - ETH/BNB collected/stuck in the contract can be withdrawn (see) | |
| */ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * SPDX-License-Identifier: MIT | |
| */ | |
| pragma solidity ^0.8.4; | |
| interface IERC20 { | |
| function totalSupply() external view returns (uint256); | |
| function balanceOf(address account) external view returns (uint256); | |
| function transfer(address recipient, uint256 amount) external returns (bool); | |
| function allowance(address owner, address spender) external view returns (uint256); | |
| function approve(address spender, uint256 amount) external returns (bool); | |
| function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); | |
| event Transfer(address indexed from, address indexed to, uint256 value); | |
| event Approval(address indexed owner, address indexed spender, uint256 value); | |
| } | |
| interface IERC20Metadata is IERC20 { | |
| function name() external view returns (string memory); | |
| function symbol() external view returns (string memory); | |
| function decimals() external view returns (uint8); | |
| } | |
| abstract contract Context { | |
| function _msgSender() internal view virtual returns (address) {return msg.sender;} | |
| function _msgData() internal view virtual returns (bytes calldata) {this; return msg.data;} | |
| } | |
| library SafeMath { | |
| function add(uint256 a, uint256 b) internal pure returns (uint256) {return a + b;} | |
| function sub(uint256 a, uint256 b) internal pure returns (uint256) {return a - b;} | |
| function mul(uint256 a, uint256 b) internal pure returns (uint256) {return a * b;} | |
| function div(uint256 a, uint256 b) internal pure returns (uint256) {return a / b;} | |
| function mod(uint256 a, uint256 b) internal pure returns (uint256) {return a % b;} | |
| function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
| unchecked { require(b <= a, errorMessage); return a - b; } | |
| } | |
| } | |
| library Address { | |
| function isContract(address account) internal view returns (bool) { uint256 size; assembly { size := extcodesize(account) } return size > 0;} | |
| function sendValue(address payable 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"); | |
| } | |
| function functionCall(address target, bytes memory data) internal returns (bytes memory) {return functionCall(target, data, "Address: low-level call failed");} | |
| function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {return functionCallWithValue(target, data, 0, errorMessage);} | |
| function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {return functionCallWithValue(target, data, value, "Address: low-level call with value failed");} | |
| function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { | |
| require(address(this).balance >= value, "Address: insufficient balance for call"); | |
| require(isContract(target), "Address: call to non-contract"); | |
| (bool success, bytes memory returndata) = target.call{ value: value }(data); | |
| return _verifyCallResult(success, returndata, errorMessage); | |
| } | |
| function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { | |
| return functionStaticCall(target, data, "Address: low-level static call failed"); | |
| } | |
| function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) { | |
| require(isContract(target), "Address: static call to non-contract"); | |
| (bool success, bytes memory returndata) = target.staticcall(data); | |
| return _verifyCallResult(success, returndata, errorMessage); | |
| } | |
| function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { | |
| return functionDelegateCall(target, data, "Address: low-level delegate call failed"); | |
| } | |
| function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { | |
| require(isContract(target), "Address: delegate call to non-contract"); | |
| (bool success, bytes memory returndata) = target.delegatecall(data); | |
| return _verifyCallResult(success, returndata, errorMessage); | |
| } | |
| function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) { | |
| if (success) { return returndata; } else { | |
| if (returndata.length > 0) { | |
| assembly { | |
| let returndata_size := mload(returndata) | |
| revert(add(32, returndata), returndata_size) | |
| } | |
| } else {revert(errorMessage);} | |
| } | |
| } | |
| } | |
| abstract contract Ownable is Context { | |
| address private _owner; | |
| address private _previousOwner; | |
| uint256 private _lockTime; | |
| event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); | |
| constructor () { | |
| address msgSender = _msgSender(); | |
| _owner = msgSender; | |
| emit OwnershipTransferred(address(0), msgSender); | |
| } | |
| function owner() public view returns (address) { | |
| return _owner; | |
| } | |
| modifier onlyOwner() { | |
| require(_owner == _msgSender(), "Ownable: caller is not the owner"); | |
| _; | |
| } | |
| function renounceOwnership() public virtual onlyOwner { | |
| emit OwnershipTransferred(_owner, address(0)); | |
| _owner = address(0); | |
| } | |
| function transferOwnership(address newOwner) public virtual onlyOwner { | |
| require(newOwner != address(0), "Ownable: new owner is the zero address"); | |
| emit OwnershipTransferred(_owner, newOwner); | |
| _owner = newOwner; | |
| } | |
| function getUnlockTime() public view returns (uint256) { | |
| return _lockTime; | |
| } | |
| function lock(uint256 time) public virtual onlyOwner { | |
| _previousOwner = _owner; | |
| _owner = address(0); | |
| _lockTime = block.timestamp + time; | |
| emit OwnershipTransferred(_owner, address(0)); | |
| } | |
| function unlock() public virtual { | |
| require(_previousOwner == msg.sender, "Only the previous owner can unlock onwership"); | |
| require(block.timestamp > _lockTime , "The contract is still locked"); | |
| emit OwnershipTransferred(_owner, _previousOwner); | |
| _owner = _previousOwner; | |
| } | |
| } | |
| abstract contract Manageable is Context { | |
| address private _manager; | |
| event ManagementTransferred(address indexed previousManager, address indexed newManager); | |
| constructor(){ | |
| address msgSender = _msgSender(); | |
| _manager = msgSender; | |
| emit ManagementTransferred(address(0), msgSender); | |
| } | |
| function manager() public view returns(address){ return _manager; } | |
| modifier onlyManager(){ | |
| require(_manager == _msgSender(), "Manageable: caller is not the manager"); | |
| _; | |
| } | |
| function transferManagement(address newManager) external virtual onlyManager { | |
| emit ManagementTransferred(_manager, newManager); | |
| _manager = newManager; | |
| } | |
| } | |
| interface IPancakeV2Factory { | |
| event PairCreated(address indexed token0, address indexed token1, address pair, uint); | |
| function createPair(address tokenA, address tokenB) external returns (address pair); | |
| } | |
| interface IPancakeV2Router { | |
| function factory() external pure returns (address); | |
| function WETH() external pure returns (address); | |
| function addLiquidityETH( | |
| address token, | |
| uint amountTokenDesired, | |
| uint amountTokenMin, | |
| uint amountETHMin, | |
| address to, | |
| uint deadline | |
| ) external payable returns (uint amountToken, uint amountETH, uint liquidity); | |
| function swapExactTokensForETHSupportingFeeOnTransferTokens( | |
| uint amountIn, | |
| uint amountOutMin, | |
| address[] calldata path, | |
| address to, | |
| uint deadline | |
| ) external; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * author: 0f0crypto <00ff00crypto@gmail.com> | |
| * discord: https://discord.gg/zn86MDCQcM | |
| * | |
| * Safetoken v1.0beta | |
| * | |
| * This is a rewrite of Safemoon in the hope to: | |
| * | |
| * - make it easier to change the tokenomics | |
| * - make it easier to maintain the code and develop it further | |
| * - remove redundant code | |
| * - fix some of the issues reported in the Safemoon audit (e.g. SSL-03) | |
| * https://www.certik.org/projects/safemoon | |
| * | |
| * | |
| * ░██████╗░█████╗░███████╗███████╗████████╗░█████╗░██╗░░██╗███████╗███╗░░██╗ | |
| * ██╔════╝██╔══██╗██╔════╝██╔════╝╚══██╔══╝██╔══██╗██║░██╔╝██╔════╝████╗░██║ | |
| * ╚█████╗░███████║█████╗░░█████╗░░░░░██║░░░██║░░██║█████═╝░█████╗░░██╔██╗██║ | |
| * ░╚═══██╗██╔══██║██╔══╝░░██╔══╝░░░░░██║░░░██║░░██║██╔═██╗░██╔══╝░░██║╚████║ | |
| * ██████╔╝██║░░██║██║░░░░░███████╗░░░██║░░░╚█████╔╝██║░╚██╗███████╗██║░╚███║ | |
| * ╚═════╝░╚═╝░░╚═╝╚═╝░░░░░╚══════╝░░░╚═╝░░░░╚════╝░╚═╝░░╚═╝╚══════╝╚═╝░░╚══╝ | |
| * | |
| * SPDX-License-Identifier: MIT | |
| */ | |
| pragma solidity ^0.8.4; | |
| /** | |
| * Tokenomics: | |
| * | |
| * Liquidity 5% | |
| * Redistribution 4% | |
| * Burn 1% | |
| * Charity 2% | |
| * Marketing 3% | |
| * Tip to the Dev 0.1% | |
| */ | |
| import "./safetoken-imports.sol"; | |
| /** | |
| * @dev If I did a good job you should not need to change anything apart from the values in the `Tokenomics`, | |
| * the actual name of the contract `SafeTokenV1Beta` at the very bottom **and** the `environment` into which | |
| * you are deploying the contract `SafeToken(Env.Testnet)` or `SafeToken(Env.MainnetV2)` etc. | |
| * | |
| * If you wish to disable a particular tax/fee just set it to zero (or comment it out/remove it). | |
| * | |
| * You can add (in theory) as many custom taxes/fees with dedicated wallet addresses if you want. | |
| * Nevertheless, I do not recommend using more than a few as the contract has not been tested | |
| * for more than the original number of taxes/fees, which is 6 (liquidity, redistribution, burn, | |
| * marketing, charity & tip to the dev). Furthermore, exchanges may impose a limit on the total | |
| * transaction fee (so that, for example, you cannot claim 100%). Usually this is done by limiting the | |
| * max value of slippage, for example, PancakeSwap max slippage is 49.9% and the fees total of more than | |
| * 35% will most likely fail there. | |
| * | |
| * NOTE: You shouldn't really remove the Rfi fee. If you do not wish to use RFI for your token, | |
| * you shouldn't be using this contract at all (you're just wasting gas if you do). | |
| * | |
| * NOTE: ignore the note below (anti-whale mech is not implemented yet) | |
| * If you wish to modify the anti-whale mech (progressive taxation) it will require a bit of coding. | |
| * I tried to make the integration as simple as possible via the `Antiwhale` contract, so the devs | |
| * know exactly where to look and what/how to make the necessary changes. There are many possibilites, | |
| * such as modifying the fees based on the tx amount (as % of TOTAL_SUPPLY), or sender's wallet balance | |
| * (as % of TOTAL_SUPPLY), including (but not limited to): | |
| * - progressive taxation by tax brackets (e.g <1%, 1-2%, 2-5%, 5-10%) | |
| * - progressive taxation by the % over a threshold (e.g. 1%) | |
| * - extra fee (e.g. double) over a threshold | |
| */ | |
| abstract contract Tokenomics { | |
| using SafeMath for uint256; | |
| // --------------------- Token Settings ------------------- // | |
| string internal constant NAME = "SafeToken.V1Beta"; | |
| string internal constant SYMBOL = "STKN.V1Beta"; | |
| uint16 internal constant FEES_DIVISOR = 10**3; | |
| uint8 internal constant DECIMALS = 6; | |
| uint256 internal constant ZEROES = 10**DECIMALS; | |
| uint256 private constant MAX = ~uint256(0); | |
| uint256 internal constant TOTAL_SUPPLY = 299792458 * ZEROES; | |
| uint256 internal _reflectedSupply = (MAX - (MAX % TOTAL_SUPPLY)); | |
| /** | |
| * @dev Set the maximum transaction amount allowed in a transfer. | |
| * | |
| * The default value is 1% of the total supply. | |
| * | |
| * NOTE: set the value to `TOTAL_SUPPLY` to have an unlimited max, i.e. | |
| * `maxTransactionAmount = TOTAL_SUPPLY;` | |
| */ | |
| uint256 internal constant maxTransactionAmount = TOTAL_SUPPLY / 100; // 1% of the total supply | |
| /** | |
| * @dev Set the maximum allowed balance in a wallet. | |
| * | |
| * The default value is 2% of the total supply. | |
| * | |
| * NOTE: set the value to 0 to have an unlimited max. | |
| * | |
| * IMPORTANT: This value MUST be greater than `numberOfTokensToSwapToLiquidity` set below, | |
| * otherwise the liquidity swap will never be executed | |
| */ | |
| uint256 internal constant maxWalletBalance = TOTAL_SUPPLY / 50; // 2% of the total supply | |
| /** | |
| * @dev Set the number of tokens to swap and add to liquidity. | |
| * | |
| * Whenever the contract's balance reaches this number of tokens, swap & liquify will be | |
| * executed in the very next transfer (via the `_beforeTokenTransfer`) | |
| * | |
| * If the `FeeType.Liquidity` is enabled in `FeesSettings`, the given % of each transaction will be first | |
| * sent to the contract address. Once the contract's balance reaches `numberOfTokensToSwapToLiquidity` the | |
| * `swapAndLiquify` of `Liquifier` will be executed. Half of the tokens will be swapped for ETH | |
| * (or BNB on BSC) and together with the other half converted into a Token-ETH/Token-BNB LP Token. | |
| * | |
| * See: `Liquifier` | |
| */ | |
| uint256 internal constant numberOfTokensToSwapToLiquidity = TOTAL_SUPPLY / 1000; // 0.1% of the total supply | |
| // --------------------- Fees Settings ------------------- // | |
| /** | |
| * @dev To add/edit/remove fees scroll down to the `addFees` function below | |
| */ | |
| address internal charityAddress = 0x3De92b2308f4acBA823fA58A0C02633380d570eE; | |
| address internal marketingAddress = 0x65b4eF486971839517d6FF08Af90fD69F26FbB1B; | |
| /** | |
| * @dev You can change the value of the burn address to pretty much anything | |
| * that's (clearly) a non-random address, i.e. for which the probability of | |
| * someone having the private key is (virtually) 0. For example, 0x00.....1, | |
| * 0x111...111, 0x12345.....12345, etc. | |
| * | |
| * NOTE: This does NOT need to be the zero address, adress(0) = 0x000...000; | |
| * | |
| * Trasfering tokens to the burn address is good for optics/marketing. Nevertheless | |
| * if the burn address is excluded from rewards (unlike in Safemoon), sending tokens | |
| * to the burn address actually improves redistribution to holders (as they will | |
| * have a larger % of tokens in non-excluded accounts) | |
| * | |
| * p.s. the address below is the speed of light in vacuum in m/s (expressed in decimals), | |
| * the hex value is 0x0000000000000000000000000000000011dE784A; :) | |
| * | |
| * Here are the values of some other fundamental constants to use: | |
| * 0x0000000000000000000000000000000602214076 (Avogardo constant) | |
| * 0x0000000000000000000000000000000001380649 (Boltzmann constant) | |
| * 0x2718281828459045235360287471352662497757 (e) | |
| * 0x0000000000000000000000000000001602176634 (elementary charge) | |
| * 0x0000000000000000000000000200231930436256 (electron g-factor) | |
| * 0x0000000000000000000000000000091093837015 (electron mass) | |
| * 0x0000000000000000000000000000137035999084 (fine structure constant) | |
| * 0x0577215664901532860606512090082402431042 (Euler-Mascheroni constant) | |
| * 0x1618033988749894848204586834365638117720 (golden ratio) | |
| * 0x0000000000000000000000000000009192631770 (hyperfine transition fq) | |
| * 0x0000000000000000000000000000010011659208 (muom g-2) | |
| * 0x3141592653589793238462643383279502884197 (pi) | |
| * 0x0000000000000000000000000000000662607015 (Planck's constant) | |
| * 0x0000000000000000000000000000001054571817 (reduced Planck's constant) | |
| * 0x1414213562373095048801688724209698078569 (sqrt(2)) | |
| */ | |
| address internal burnAddress = 0x0000000000000000000000000000000299792458; | |
| /** | |
| * @dev You can disable this but if you feel generous I'd appreciate the 0.1% | |
| * donation for rewriting Safemoon and making everyone's life a little easier | |
| * | |
| * If you keep this tip enabled, let me know in Discord: https://discord.gg/zn86MDCQcM | |
| * and you'll be added to the partners section to promote your token. | |
| */ | |
| address internal tipToTheDev = 0x2d67D0A35192EB8cE9DF4988686553360A6E424f; | |
| enum FeeType { Antiwhale, Burn, Liquidity, Rfi, External, ExternalToETH } | |
| struct Fee { | |
| FeeType name; | |
| uint256 value; | |
| address recipient; | |
| uint256 total; | |
| } | |
| Fee[] internal fees; | |
| uint256 internal sumOfFees; | |
| constructor() { | |
| _addFees(); | |
| } | |
| function _addFee(FeeType name, uint256 value, address recipient) private { | |
| fees.push( Fee(name, value, recipient, 0 ) ); | |
| sumOfFees += value; | |
| } | |
| function _addFees() private { | |
| /** | |
| * The RFI recipient is ignored but we need to give a valid address value | |
| * | |
| * CAUTION: If you don't want to use RFI this implementation isn't really for you! | |
| * There are much more efficient and cleaner token contracts without RFI | |
| * so you should use one of those | |
| * | |
| * The value of fees is given in part per 1000 (based on the value of FEES_DIVISOR), | |
| * e.g. for 5% use 50, for 3.5% use 35, etc. | |
| */ | |
| _addFee(FeeType.Rfi, 40, address(this) ); | |
| _addFee(FeeType.Burn, 10, burnAddress ); | |
| _addFee(FeeType.Liquidity, 50, address(this) ); | |
| _addFee(FeeType.External, 20, charityAddress ); | |
| _addFee(FeeType.External, 30, marketingAddress ); | |
| // 0.1% as a tip to the dev; feel free to remove this! | |
| _addFee(FeeType.ExternalToETH, 1, tipToTheDev ); | |
| } | |
| function _getFeesCount() internal view returns (uint256){ return fees.length; } | |
| function _getFeeStruct(uint256 index) private view returns(Fee storage){ | |
| require( index >= 0 && index < fees.length, "FeesSettings._getFeeStruct: Fee index out of bounds"); | |
| return fees[index]; | |
| } | |
| function _getFee(uint256 index) internal view returns (FeeType, uint256, address, uint256){ | |
| Fee memory fee = _getFeeStruct(index); | |
| return ( fee.name, fee.value, fee.recipient, fee.total ); | |
| } | |
| function _addFeeCollectedAmount(uint256 index, uint256 amount) internal { | |
| Fee storage fee = _getFeeStruct(index); | |
| fee.total = fee.total.add(amount); | |
| } | |
| // function getCollectedFeeTotal(uint256 index) external view returns (uint256){ | |
| function getCollectedFeeTotal(uint256 index) internal view returns (uint256){ | |
| Fee memory fee = _getFeeStruct(index); | |
| return fee.total; | |
| } | |
| } | |
| abstract contract Presaleable is Manageable { | |
| bool internal isInPresale; | |
| function setPreseableEnabled(bool value) external onlyManager { | |
| isInPresale = value; | |
| } | |
| } | |
| abstract contract BaseRfiToken is IERC20, IERC20Metadata, Ownable, Presaleable, Tokenomics { | |
| using SafeMath for uint256; | |
| using Address for address; | |
| mapping (address => uint256) internal _reflectedBalances; | |
| mapping (address => uint256) internal _balances; | |
| mapping (address => mapping (address => uint256)) internal _allowances; | |
| mapping (address => bool) internal _isExcludedFromFee; | |
| mapping (address => bool) internal _isExcludedFromRewards; | |
| address[] private _excluded; | |
| constructor(){ | |
| _reflectedBalances[owner()] = _reflectedSupply; | |
| // exclude owner and this contract from fee | |
| _isExcludedFromFee[owner()] = true; | |
| _isExcludedFromFee[address(this)] = true; | |
| // exclude the owner and this contract from rewards | |
| _exclude(owner()); | |
| _exclude(address(this)); | |
| emit Transfer(address(0), owner(), TOTAL_SUPPLY); | |
| } | |
| /** Functions required by IERC20Metadat **/ | |
| function name() external pure override returns (string memory) { return NAME; } | |
| function symbol() external pure override returns (string memory) { return SYMBOL; } | |
| function decimals() external pure override returns (uint8) { return DECIMALS; } | |
| /** Functions required by IERC20Metadat - END **/ | |
| /** Functions required by IERC20 **/ | |
| function totalSupply() external pure override returns (uint256) { | |
| return TOTAL_SUPPLY; | |
| } | |
| function balanceOf(address account) public view override returns (uint256){ | |
| if (_isExcludedFromRewards[account]) return _balances[account]; | |
| return tokenFromReflection(_reflectedBalances[account]); | |
| } | |
| function transfer(address recipient, uint256 amount) external override returns (bool){ | |
| _transfer(_msgSender(), recipient, amount); | |
| return true; | |
| } | |
| function allowance(address owner, address spender) external view override returns (uint256){ | |
| return _allowances[owner][spender]; | |
| } | |
| function approve(address spender, uint256 amount) external override returns (bool) { | |
| _approve(_msgSender(), spender, amount); | |
| return true; | |
| } | |
| function transferFrom(address sender, address recipient, uint256 amount) external override returns (bool){ | |
| _transfer(sender, recipient, amount); | |
| _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); | |
| return true; | |
| } | |
| /** Functions required by IERC20 - END **/ | |
| /** | |
| * @dev this is really a "soft" burn (total supply is not reduced). RFI holders | |
| * get two benefits from burning tokens: | |
| * | |
| * 1) Tokens in the burn address increase the % of tokens held by holders not | |
| * excluded from rewards (assuming the burn address is excluded) | |
| * 2) Tokens in the burn address cannot be sold (which in turn draing the | |
| * liquidity pool) | |
| * | |
| * | |
| * In RFI holders already get % of each transaction so the value of their tokens | |
| * increases (in a way). Therefore there is really no need to do a "hard" burn | |
| * (reduce the total supply). What matters (in RFI) is to make sure that a large | |
| * amount of tokens cannot be sold = draining the liquidity pool = lowering the | |
| * value of tokens holders own. For this purpose, transfering tokens to a (vanity) | |
| * burn address is the most appropriate way to "burn". | |
| * | |
| * There is an extra check placed into the `transfer` function to make sure the | |
| * burn address cannot withdraw the tokens is has (although the chance of someone | |
| * having/finding the private key is virtually zero). | |
| */ | |
| function burn(uint256 amount) external { | |
| address sender = _msgSender(); | |
| require(sender != address(0), "BaseRfiToken: burn from the zero address"); | |
| require(sender != address(burnAddress), "BaseRfiToken: burn from the burn address"); | |
| uint256 balance = balanceOf(sender); | |
| require(balance >= amount, "BaseRfiToken: burn amount exceeds balance"); | |
| uint256 reflectedAmount = amount.mul(_getCurrentRate()); | |
| // remove the amount from the sender's balance first | |
| _reflectedBalances[sender] = _reflectedBalances[sender].sub(reflectedAmount); | |
| if (_isExcludedFromRewards[sender]) | |
| _balances[sender] = _balances[sender].sub(amount); | |
| _burnTokens( sender, amount, reflectedAmount ); | |
| } | |
| /** | |
| * @dev "Soft" burns the specified amount of tokens by sending them | |
| * to the burn address | |
| */ | |
| function _burnTokens(address sender, uint256 tBurn, uint256 rBurn) internal { | |
| /** | |
| * @dev Do not reduce _totalSupply and/or _reflectedSupply. (soft) burning by sending | |
| * tokens to the burn address (which should be excluded from rewards) is sufficient | |
| * in RFI | |
| */ | |
| _reflectedBalances[burnAddress] = _reflectedBalances[burnAddress].add(rBurn); | |
| if (_isExcludedFromRewards[burnAddress]) | |
| _balances[burnAddress] = _balances[burnAddress].add(tBurn); | |
| /** | |
| * @dev Emit the event so that the burn address balance is updated (on bscscan) | |
| */ | |
| emit Transfer(sender, burnAddress, tBurn); | |
| } | |
| function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { | |
| _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); | |
| return true; | |
| } | |
| 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; | |
| } | |
| function isExcludedFromReward(address account) external view returns (bool) { | |
| return _isExcludedFromRewards[account]; | |
| } | |
| /** | |
| * @dev Calculates and returns the reflected amount for the given amount with or without | |
| * the transfer fees (deductTransferFee true/false) | |
| */ | |
| function reflectionFromToken(uint256 tAmount, bool deductTransferFee) external view returns(uint256) { | |
| require(tAmount <= TOTAL_SUPPLY, "Amount must be less than supply"); | |
| if (!deductTransferFee) { | |
| (uint256 rAmount,,,,) = _getValues(tAmount,0); | |
| return rAmount; | |
| } else { | |
| (,uint256 rTransferAmount,,,) = _getValues(tAmount,_getSumOfFees(_msgSender(), tAmount)); | |
| return rTransferAmount; | |
| } | |
| } | |
| /** | |
| * @dev Calculates and returns the amount of tokens corresponding to the given reflected amount. | |
| */ | |
| function tokenFromReflection(uint256 rAmount) internal view returns(uint256) { | |
| require(rAmount <= _reflectedSupply, "Amount must be less than total reflections"); | |
| uint256 currentRate = _getCurrentRate(); | |
| return rAmount.div(currentRate); | |
| } | |
| function excludeFromReward(address account) external onlyOwner() { | |
| require(!_isExcludedFromRewards[account], "Account is not included"); | |
| _exclude(account); | |
| } | |
| function _exclude(address account) internal { | |
| if(_reflectedBalances[account] > 0) { | |
| _balances[account] = tokenFromReflection(_reflectedBalances[account]); | |
| } | |
| _isExcludedFromRewards[account] = true; | |
| _excluded.push(account); | |
| } | |
| function includeInReward(address account) external onlyOwner() { | |
| require(_isExcludedFromRewards[account], "Account is not excluded"); | |
| for (uint256 i = 0; i < _excluded.length; i++) { | |
| if (_excluded[i] == account) { | |
| _excluded[i] = _excluded[_excluded.length - 1]; | |
| _balances[account] = 0; | |
| _isExcludedFromRewards[account] = false; | |
| _excluded.pop(); | |
| break; | |
| } | |
| } | |
| } | |
| function setExcludedFromFee(address account, bool value) external onlyOwner { _isExcludedFromFee[account] = value; } | |
| function isExcludedFromFee(address account) public view returns(bool) { return _isExcludedFromFee[account]; } | |
| function _approve(address owner, address spender, uint256 amount) internal { | |
| require(owner != address(0), "BaseRfiToken: approve from the zero address"); | |
| require(spender != address(0), "BaseRfiToken: approve to the zero address"); | |
| _allowances[owner][spender] = amount; | |
| emit Approval(owner, spender, amount); | |
| } | |
| /** | |
| */ | |
| function _isUnlimitedSender(address account) internal view returns(bool){ | |
| // the owner should be the only whitelisted sender | |
| return (account == owner()); | |
| } | |
| /** | |
| */ | |
| function _isUnlimitedRecipient(address account) internal view returns(bool){ | |
| // the owner should be a white-listed recipient | |
| // and anyone should be able to burn as many tokens as | |
| // he/she wants | |
| return (account == owner() || account == burnAddress); | |
| } | |
| function _transfer(address sender, address recipient, uint256 amount) private { | |
| require(sender != address(0), "BaseRfiToken: transfer from the zero address"); | |
| require(recipient != address(0), "BaseRfiToken: transfer to the zero address"); | |
| require(sender != address(burnAddress), "BaseRfiToken: transfer from the burn address"); | |
| require(amount > 0, "Transfer amount must be greater than zero"); | |
| // indicates whether or not feee should be deducted from the transfer | |
| bool takeFee = true; | |
| if ( isInPresale ){ takeFee = false; } | |
| else { | |
| /** | |
| * Check the amount is within the max allowed limit as long as a | |
| * unlimited sender/recepient is not involved in the transaction | |
| */ | |
| if ( amount > maxTransactionAmount && !_isUnlimitedSender(sender) && !_isUnlimitedRecipient(recipient) ){ | |
| revert("Transfer amount exceeds the maxTxAmount."); | |
| } | |
| /** | |
| * The pair needs to excluded from the max wallet balance check; | |
| * selling tokens is sending them back to the pair (without this | |
| * check, selling tokens would not work if the pair's balance | |
| * was over the allowed max) | |
| * | |
| * Note: This does NOT take into account the fees which will be deducted | |
| * from the amount. As such it could be a bit confusing | |
| */ | |
| if ( maxWalletBalance > 0 && !_isUnlimitedSender(sender) && !_isUnlimitedRecipient(recipient) && !_isV2Pair(recipient) ){ | |
| uint256 recipientBalance = balanceOf(recipient); | |
| require(recipientBalance + amount <= maxWalletBalance, "New balance would exceed the maxWalletBalance"); | |
| } | |
| } | |
| // if any account belongs to _isExcludedFromFee account then remove the fee | |
| if(_isExcludedFromFee[sender] || _isExcludedFromFee[recipient]){ takeFee = false; } | |
| _beforeTokenTransfer(sender, recipient, amount, takeFee); | |
| _transferTokens(sender, recipient, amount, takeFee); | |
| } | |
| function _transferTokens(address sender, address recipient, uint256 amount, bool takeFee) private { | |
| /** | |
| * We don't need to know anything about the individual fees here | |
| * (like Safemoon does with `_getValues`). All that is required | |
| * for the transfer is the sum of all fees to calculate the % of the total | |
| * transaction amount which should be transferred to the recipient. | |
| * | |
| * The `_takeFees` call will/should take care of the individual fees | |
| */ | |
| uint256 sumOfFees = _getSumOfFees(sender, amount); | |
| if ( !takeFee ){ sumOfFees = 0; } | |
| (uint256 rAmount, uint256 rTransferAmount, uint256 tAmount, uint256 tTransferAmount, uint256 currentRate ) = _getValues(amount, sumOfFees); | |
| /** | |
| * Sender's and Recipient's reflected balances must be always updated regardless of | |
| * whether they are excluded from rewards or not. | |
| */ | |
| _reflectedBalances[sender] = _reflectedBalances[sender].sub(rAmount); | |
| _reflectedBalances[recipient] = _reflectedBalances[recipient].add(rTransferAmount); | |
| /** | |
| * Update the true/nominal balances for excluded accounts | |
| */ | |
| if (_isExcludedFromRewards[sender]){ _balances[sender] = _balances[sender].sub(tAmount); } | |
| if (_isExcludedFromRewards[recipient] ){ _balances[recipient] = _balances[recipient].add(tTransferAmount); } | |
| _takeFees( amount, currentRate, sumOfFees ); | |
| emit Transfer(sender, recipient, tTransferAmount); | |
| } | |
| function _takeFees(uint256 amount, uint256 currentRate, uint256 sumOfFees ) private { | |
| if ( sumOfFees > 0 && !isInPresale ){ | |
| _takeTransactionFees(amount, currentRate); | |
| } | |
| } | |
| function _getValues(uint256 tAmount, uint256 feesSum) internal view returns (uint256, uint256, uint256, uint256, uint256) { | |
| uint256 tTotalFees = tAmount.mul(feesSum).div(FEES_DIVISOR); | |
| uint256 tTransferAmount = tAmount.sub(tTotalFees); | |
| uint256 currentRate = _getCurrentRate(); | |
| uint256 rAmount = tAmount.mul(currentRate); | |
| uint256 rTotalFees = tTotalFees.mul(currentRate); | |
| uint256 rTransferAmount = rAmount.sub(rTotalFees); | |
| return (rAmount, rTransferAmount, tAmount, tTransferAmount, currentRate); | |
| } | |
| function _getCurrentRate() internal view returns(uint256) { | |
| (uint256 rSupply, uint256 tSupply) = _getCurrentSupply(); | |
| return rSupply.div(tSupply); | |
| } | |
| function _getCurrentSupply() internal view returns(uint256, uint256) { | |
| uint256 rSupply = _reflectedSupply; | |
| uint256 tSupply = TOTAL_SUPPLY; | |
| /** | |
| * The code below removes balances of addresses excluded from rewards from | |
| * rSupply and tSupply, which effectively increases the % of transaction fees | |
| * delivered to non-excluded holders | |
| */ | |
| for (uint256 i = 0; i < _excluded.length; i++) { | |
| if (_reflectedBalances[_excluded[i]] > rSupply || _balances[_excluded[i]] > tSupply) return (_reflectedSupply, TOTAL_SUPPLY); | |
| rSupply = rSupply.sub(_reflectedBalances[_excluded[i]]); | |
| tSupply = tSupply.sub(_balances[_excluded[i]]); | |
| } | |
| if (tSupply == 0 || rSupply < _reflectedSupply.div(TOTAL_SUPPLY)) return (_reflectedSupply, TOTAL_SUPPLY); | |
| return (rSupply, tSupply); | |
| } | |
| /** | |
| * @dev Hook that is called before any transfer of tokens. | |
| */ | |
| function _beforeTokenTransfer(address sender, address recipient, uint256 amount, bool takeFee) internal virtual; | |
| /** | |
| * @dev Returns the total sum of fees to be processed in each transaction. | |
| * | |
| * To separate concerns this contract (class) will take care of ONLY handling RFI, i.e. | |
| * changing the rates and updating the holder's balance (via `_redistribute`). | |
| * It is the responsibility of the dev/user to handle all other fees and taxes | |
| * in the appropriate contracts (classes). | |
| */ | |
| function _getSumOfFees(address sender, uint256 amount) internal view virtual returns (uint256); | |
| /** | |
| * @dev A delegate which should return true if the given address is the V2 Pair and false otherwise | |
| */ | |
| function _isV2Pair(address account) internal view virtual returns(bool); | |
| /** | |
| * @dev Redistributes the specified amount among the current holders via the reflect.finance | |
| * algorithm, i.e. by updating the _reflectedSupply (_rSupply) which ultimately adjusts the | |
| * current rate used by `tokenFromReflection` and, in turn, the value returns from `balanceOf`. | |
| * This is the bit of clever math which allows rfi to redistribute the fee without | |
| * having to iterate through all holders. | |
| * | |
| * Visit our discord at https://discord.gg/dAmr6eUTpM | |
| */ | |
| function _redistribute(uint256 amount, uint256 currentRate, uint256 fee, uint256 index) internal { | |
| uint256 tFee = amount.mul(fee).div(FEES_DIVISOR); | |
| uint256 rFee = tFee.mul(currentRate); | |
| _reflectedSupply = _reflectedSupply.sub(rFee); | |
| _addFeeCollectedAmount(index, tFee); | |
| } | |
| /** | |
| * @dev Hook that is called before the `Transfer` event is emitted if fees are enabled for the transfer | |
| */ | |
| function _takeTransactionFees(uint256 amount, uint256 currentRate) internal virtual; | |
| } | |
| abstract contract Liquifier is Ownable, Manageable { | |
| using SafeMath for uint256; | |
| uint256 private withdrawableBalance; | |
| enum Env {Testnet, MainnetV1, MainnetV2} | |
| Env private _env; | |
| // PancakeSwap V1 | |
| address private _mainnetRouterV1Address = 0x05fF2B0DB69458A0750badebc4f9e13aDd608C7F; | |
| // PancakeSwap V2 | |
| address private _mainnetRouterV2Address = 0x10ED43C718714eb63d5aA57B78B54704E256024E; | |
| // Testnet | |
| // address private _testnetRouterAddress = 0xD99D1c33F9fC3444f8101754aBC46c52416550D1; | |
| // PancakeSwap Testnet = https://pancake.kiemtienonline360.com/ | |
| address private _testnetRouterAddress = 0x9Ac64Cc6e4415144C455BD8E4837Fea55603e5c3; | |
| IPancakeV2Router internal _router; | |
| address internal _pair; | |
| bool private inSwapAndLiquify; | |
| bool private swapAndLiquifyEnabled = true; | |
| uint256 private maxTransactionAmount; | |
| uint256 private numberOfTokensToSwapToLiquidity; | |
| modifier lockTheSwap { | |
| inSwapAndLiquify = true; | |
| _; | |
| inSwapAndLiquify = false; | |
| } | |
| event RouterSet(address indexed router); | |
| event SwapAndLiquify(uint256 tokensSwapped, uint256 ethReceived, uint256 tokensIntoLiquidity); | |
| event SwapAndLiquifyEnabledUpdated(bool enabled); | |
| event LiquidityAdded(uint256 tokenAmountSent, uint256 ethAmountSent, uint256 liquidity); | |
| receive() external payable {} | |
| function initializeLiquiditySwapper(Env env, uint256 maxTx, uint256 liquifyAmount) internal { | |
| _env = env; | |
| if (_env == Env.MainnetV1){ _setRouterAddress(_mainnetRouterV1Address); } | |
| else if (_env == Env.MainnetV2){ _setRouterAddress(_mainnetRouterV2Address); } | |
| else /*(_env == Env.Testnet)*/{ _setRouterAddress(_testnetRouterAddress); } | |
| maxTransactionAmount = maxTx; | |
| numberOfTokensToSwapToLiquidity = liquifyAmount; | |
| } | |
| /** | |
| * NOTE: passing the `contractTokenBalance` here is preferred to creating `balanceOfDelegate` | |
| */ | |
| function liquify(uint256 contractTokenBalance, address sender) internal { | |
| if (contractTokenBalance >= maxTransactionAmount) contractTokenBalance = maxTransactionAmount; | |
| bool isOverRequiredTokenBalance = ( contractTokenBalance >= numberOfTokensToSwapToLiquidity ); | |
| /** | |
| * - first check if the contract has collected enough tokens to swap and liquify | |
| * - then check swap and liquify is enabled | |
| * - then make sure not to get caught in a circular liquidity event | |
| * - finally, don't swap & liquify if the sender is the uniswap pair | |
| */ | |
| if ( isOverRequiredTokenBalance && swapAndLiquifyEnabled && !inSwapAndLiquify && (sender != _pair) ){ | |
| // TODO check if the `(sender != _pair)` is necessary because that basically | |
| // stops swap and liquify for all "buy" transactions | |
| _swapAndLiquify(contractTokenBalance); | |
| } | |
| } | |
| /** | |
| * @dev sets the router address and created the router, factory pair to enable | |
| * swapping and liquifying (contract) tokens | |
| */ | |
| function _setRouterAddress(address router) private { | |
| IPancakeV2Router _newPancakeRouter = IPancakeV2Router(router); | |
| _pair = IPancakeV2Factory(_newPancakeRouter.factory()).createPair(address(this), _newPancakeRouter.WETH()); | |
| _router = _newPancakeRouter; | |
| emit RouterSet(router); | |
| } | |
| function _swapAndLiquify(uint256 amount) private lockTheSwap { | |
| // split the contract balance into halves | |
| uint256 half = amount.div(2); | |
| uint256 otherHalf = amount.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); // <- 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] = _router.WETH(); | |
| _approveDelegate(address(this), address(_router), tokenAmount); | |
| // make the swap | |
| _router.swapExactTokensForETHSupportingFeeOnTransferTokens( | |
| tokenAmount, | |
| // The minimum amount of output tokens that must be received for the transaction not to revert. | |
| // 0 = accept any amount (slippage is inevitable) | |
| 0, | |
| path, | |
| address(this), | |
| block.timestamp | |
| ); | |
| } | |
| function _addLiquidity(uint256 tokenAmount, uint256 ethAmount) private { | |
| // approve token transfer to cover all possible scenarios | |
| _approveDelegate(address(this), address(_router), tokenAmount); | |
| // add tahe liquidity | |
| (uint256 tokenAmountSent, uint256 ethAmountSent, uint256 liquidity) = _router.addLiquidityETH{value: ethAmount}( | |
| address(this), | |
| tokenAmount, | |
| // Bounds the extent to which the WETH/token price can go up before the transaction reverts. | |
| // Must be <= amountTokenDesired; 0 = accept any amount (slippage is inevitable) | |
| 0, | |
| // Bounds the extent to which the token/WETH price can go up before the transaction reverts. | |
| // 0 = accept any amount (slippage is inevitable) | |
| 0, | |
| // this is a centralized risk if the owner's account is ever compromised (see Certik SSL-04) | |
| owner(), | |
| block.timestamp | |
| ); | |
| // fix the forever locked BNBs as per the certik's audit | |
| /** | |
| * The swapAndLiquify function converts half of the contractTokenBalance SafeMoon tokens to BNB. | |
| * For every swapAndLiquify function call, a small amount of BNB remains in the contract. | |
| * This amount grows over time with the swapAndLiquify function being called throughout the life | |
| * of the contract. The Safemoon contract does not contain a method to withdraw these funds, | |
| * and the BNB will be locked in the Safemoon contract forever. | |
| */ | |
| withdrawableBalance = address(this).balance; | |
| emit LiquidityAdded(tokenAmountSent, ethAmountSent, liquidity); | |
| } | |
| /** | |
| * @dev Sets the uniswapV2 pair (router & factory) for swapping and liquifying tokens | |
| */ | |
| function setRouterAddress(address router) external onlyManager() { | |
| _setRouterAddress(router); | |
| } | |
| /** | |
| * @dev Sends the swap and liquify flag to the provided value. If set to `false` tokens collected in the contract will | |
| * NOT be converted into liquidity. | |
| */ | |
| function setSwapAndLiquifyEnabled(bool enabled) external onlyManager { | |
| swapAndLiquifyEnabled = enabled; | |
| emit SwapAndLiquifyEnabledUpdated(swapAndLiquifyEnabled); | |
| } | |
| /** | |
| * @dev The owner can withdraw ETH(BNB) collected in the contract from `swapAndLiquify` | |
| * or if someone (accidentally) sends ETH/BNB directly to the contract. | |
| * | |
| * Note: This addresses the contract flaw pointed out in the Certik Audit of Safemoon (SSL-03): | |
| * | |
| * The swapAndLiquify function converts half of the contractTokenBalance SafeMoon tokens to BNB. | |
| * For every swapAndLiquify function call, a small amount of BNB remains in the contract. | |
| * This amount grows over time with the swapAndLiquify function being called | |
| * throughout the life of the contract. The Safemoon contract does not contain a method | |
| * to withdraw these funds, and the BNB will be locked in the Safemoon contract forever. | |
| * https://www.certik.org/projects/safemoon | |
| */ | |
| function withdrawLockedEth(address payable recipient) external onlyManager(){ | |
| require(recipient != address(0), "Cannot withdraw the ETH balance to the zero address"); | |
| require(withdrawableBalance > 0, "The ETH balance must be greater than 0"); | |
| // prevent re-entrancy attacks | |
| uint256 amount = withdrawableBalance; | |
| withdrawableBalance = 0; | |
| recipient.transfer(amount); | |
| } | |
| /** | |
| * @dev Use this delegate instead of having (unnecessarily) extend `BaseRfiToken` to gained access | |
| * to the `_approve` function. | |
| */ | |
| function _approveDelegate(address owner, address spender, uint256 amount) internal virtual; | |
| } | |
| ////////////////////////////////////////////////////////////////////////// | |
| abstract contract Antiwhale is Tokenomics { | |
| /** | |
| * @dev Returns the total sum of fees (in percents / per-mille - this depends on the FEES_DIVISOR value) | |
| * | |
| * NOTE: Currently this is just a placeholder. The parameters passed to this function are the | |
| * sender's token balance and the transfer amount. An *antiwhale* mechanics can use these | |
| * values to adjust the fees total for each tx | |
| */ | |
| // function _getAntiwhaleFees(uint256 sendersBalance, uint256 amount) internal view returns (uint256){ | |
| function _getAntiwhaleFees(uint256, uint256) internal view returns (uint256){ | |
| return sumOfFees; | |
| } | |
| } | |
| ////////////////////////////////////////////////////////////////////////// | |
| abstract contract SafeToken is BaseRfiToken, Liquifier, Antiwhale { | |
| using SafeMath for uint256; | |
| // constructor(string memory _name, string memory _symbol, uint8 _decimals){ | |
| constructor(Env _env){ | |
| initializeLiquiditySwapper(_env, maxTransactionAmount, numberOfTokensToSwapToLiquidity); | |
| // exclude the pair address from rewards - we don't want to redistribute | |
| // tx fees to these two; redistribution is only for holders, dah! | |
| _exclude(_pair); | |
| _exclude(burnAddress); | |
| } | |
| function _isV2Pair(address account) internal view override returns(bool){ | |
| return (account == _pair); | |
| } | |
| function _getSumOfFees(address sender, uint256 amount) internal view override returns (uint256){ | |
| return _getAntiwhaleFees(balanceOf(sender), amount); | |
| } | |
| // function _beforeTokenTransfer(address sender, address recipient, uint256 amount, bool takeFee) internal override { | |
| function _beforeTokenTransfer(address sender, address , uint256 , bool ) internal override { | |
| if ( !isInPresale ){ | |
| uint256 contractTokenBalance = balanceOf(address(this)); | |
| liquify( contractTokenBalance, sender ); | |
| } | |
| } | |
| function _takeTransactionFees(uint256 amount, uint256 currentRate) internal override { | |
| if( isInPresale ){ return; } | |
| uint256 feesCount = _getFeesCount(); | |
| for (uint256 index = 0; index < feesCount; index++ ){ | |
| (FeeType name, uint256 value, address recipient,) = _getFee(index); | |
| // no need to check value < 0 as the value is uint (i.e. from 0 to 2^256-1) | |
| if ( value == 0 ) continue; | |
| if ( name == FeeType.Rfi ){ | |
| _redistribute( amount, currentRate, value, index ); | |
| } | |
| else if ( name == FeeType.Burn ){ | |
| _burn( amount, currentRate, value, index ); | |
| } | |
| else if ( name == FeeType.Antiwhale){ | |
| // TODO | |
| } | |
| else if ( name == FeeType.ExternalToETH){ | |
| _takeFeeToETH( amount, currentRate, value, recipient, index ); | |
| } | |
| else { | |
| _takeFee( amount, currentRate, value, recipient, index ); | |
| } | |
| } | |
| } | |
| function _burn(uint256 amount, uint256 currentRate, uint256 fee, uint256 index) private { | |
| uint256 tBurn = amount.mul(fee).div(FEES_DIVISOR); | |
| uint256 rBurn = tBurn.mul(currentRate); | |
| _burnTokens(address(this), tBurn, rBurn); | |
| _addFeeCollectedAmount(index, tBurn); | |
| } | |
| function _takeFee(uint256 amount, uint256 currentRate, uint256 fee, address recipient, uint256 index) private { | |
| uint256 tAmount = amount.mul(fee).div(FEES_DIVISOR); | |
| uint256 rAmount = tAmount.mul(currentRate); | |
| _reflectedBalances[recipient] = _reflectedBalances[recipient].add(rAmount); | |
| if(_isExcludedFromRewards[recipient]) | |
| _balances[recipient] = _balances[recipient].add(tAmount); | |
| _addFeeCollectedAmount(index, tAmount); | |
| } | |
| /** | |
| * @dev When implemented this will convert the fee amount of tokens into ETH/BNB | |
| * and send to the recipient's wallet. Note that this reduces liquidity so it | |
| * might be a good idea to add a % into the liquidity fee for % you take our through | |
| * this method (just a suggestions) | |
| */ | |
| function _takeFeeToETH(uint256 amount, uint256 currentRate, uint256 fee, address recipient, uint256 index) private { | |
| _takeFee(amount, currentRate, fee, recipient, index); | |
| } | |
| function _approveDelegate(address owner, address spender, uint256 amount) internal override { | |
| _approve(owner, spender, amount); | |
| } | |
| } | |
| contract SafeTokenV1Beta is SafeToken{ | |
| constructor() SafeToken(Env.Testnet){ | |
| // pre-approve the initial liquidity supply (to safe a bit of time) | |
| _approve(owner(),address(_router), ~uint256(0)); | |
| } | |
| } | |
| /** | |
| * Todo (beta): | |
| * | |
| * - reorganize the sol file(s) to make put everything editable in a single .sol file | |
| * and keep all other code in other .sol file(s) | |
| * - move variable values initialized in the contract to be constructor parameters | |
| * - add/remove setters/getter where appropriate | |
| * - add unit tests (via ganache-cli + truffle) | |
| * - add full dev evn (truffle) folders & files | |
| * | |
| * Todo: | |
| * | |
| * - implement `_takeFeeToETH` (currently just calls `_takeFee`) | |
| * - implement anti whale mechanics (via different pre-created libraries?), eg progressive tax | |
| * - implement anti sell mechanics | |
| * - address SSL-04 | Centralized risk in addLiquidity - https://www.certik.org/projects/safemoon | |
| * change the recipient to `address(this)` or implement a decentralized mechanism or | |
| * smart-contract solution | |
| * - change Uniswap to PancakeSwap in contract/interface names and local var names | |
| * - change ETH to BNB in names and comments | |
| */ | |
| /** | |
| * Tests to pass: | |
| * | |
| * - Tokenomics fees can be added/removed/edited | |
| * - Tokenomics fees are correctly taken from each (qualifying) transaction | |
| * - The RFI fee is correctly distributed among holders (which are not excluded from rewards) | |
| * - `swapAndLiquify` works correctly when the threshold balance is reached | |
| * - `maxTransactionAmount` works correctly and *unlimited* accounts are not subject to the limit | |
| * - `maxWalletBalance` works correctly and *unlimited* accounts are not subject to the limit | |
| * - accounts excluded from fees are not subjecto tx fees | |
| * - accounts excluded from rewards do not share in rewards | |
| * - ETH/BNB collected/stuck in the contract can be withdrawn (see) | |
| */ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| pragma solidity ^0.8.0; | |
| import 'https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol'; | |
| import 'https://github.com/OpenZeppelin/openzeppelin-contracts/blob/f1e92dd184a599f39ce9cc4ec8a5e4a94416f3a2/contracts/utils/math/SafeMath.sol'; | |
| contract SFML is ERC20 { | |
| using SafeMath for uint256; | |
| uint TAX_FEE = 5; | |
| address public owner; | |
| uint BURN_FEE = 5; | |
| mapping (address => bool) public excludedFromTax; | |
| constructor() public ERC20('SafeMoonLike','SFML'){ | |
| _mint(msg.sender, 1000 *10**18); | |
| owner = msg.sender; | |
| excludedFromTax[msg.sender] = true; | |
| } | |
| function transfer(address recipient, uint256 amount) public override returns (bool){ | |
| if(excludedFromTax[msg.sender] == true) { | |
| _transfer(_msgSender(), recipient, amount); | |
| }else{ | |
| uint burnAmount = amount.mul(BURN_FEE) / 100; | |
| uint adminAmount = amount.mul(TAX_FEE) / 100; | |
| _burn(_msgSender(), burnAmount); | |
| _transfer(_msgSender(), owner, adminAmount); | |
| _transfer(_msgSender(),recipient,amount.sub(burnAmount).sub(adminAmount)); | |
| } | |
| return true; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // SPDX-License-Identifier: MIT | |
| pragma solidity ^0.8.0; | |
| import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; | |
| contract Token is ERC20 { | |
| //minter variable | |
| address public minter; | |
| //minter changed event | |
| event MinterChanged(address indexed from, address to); | |
| constructor() public payable ERC20("Lugashs DBank Currency", "LDBC") { | |
| //asigning initial minter | |
| minter = msg.sender; | |
| } | |
| //pass minter role function | |
| function passMinterRole(address dBank) public returns (bool) { | |
| require( | |
| msg.sender == minter, | |
| "Error, only owner can change pass minter role" | |
| ); | |
| minter = dBank; | |
| emit MinterChanged(msg.sender, dBank); | |
| return true; | |
| } | |
| function mint(address account, uint256 amount) public { | |
| //check if msg.sender have minter role | |
| require( | |
| msg.sender == minter, | |
| "Error, msg.sender doest not have minter role" | |
| ); | |
| _mint(account, amount); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Right click on the script name and hit "Run" to execute | |
| (async () => { | |
| try { | |
| console.log('Running deployWithEthers script...') | |
| const contractName = 'Storage' // Change this for other contract | |
| const constructorArgs = [] // Put constructor args (if any) here for your contract | |
| // Note that the script needs the ABI which is generated from the compilation artifact. | |
| // Make sure contract is compiled and artifacts are generated | |
| const artifactsPath = `browser/contracts/artifacts/${contractName}.json` // Change this for different path | |
| const metadata = JSON.parse(await remix.call('fileManager', 'getFile', artifactsPath)) | |
| // 'web3Provider' is a remix global variable object | |
| const signer = (new ethers.providers.Web3Provider(web3Provider)).getSigner() | |
| let factory = new ethers.ContractFactory(metadata.abi, metadata.data.bytecode.object, signer); | |
| let contract = await factory.deploy(...constructorArgs); | |
| console.log('Contract Address: ', contract.address); | |
| // The contract is NOT deployed yet; we must wait until it is mined | |
| await contract.deployed() | |
| console.log('Deployment successful.') | |
| } catch (e) { | |
| console.log(e.message) | |
| } | |
| })() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Right click on the script name and hit "Run" to execute | |
| (async () => { | |
| try { | |
| console.log('Running deployWithWeb3 script...') | |
| const contractName = 'Storage' // Change this for other contract | |
| const constructorArgs = [] // Put constructor args (if any) here for your contract | |
| // Note that the script needs the ABI which is generated from the compilation artifact. | |
| // Make sure contract is compiled and artifacts are generated | |
| const artifactsPath = `browser/contracts/artifacts/${contractName}.json` // Change this for different path | |
| const metadata = JSON.parse(await remix.call('fileManager', 'getFile', artifactsPath)) | |
| const accounts = await web3.eth.getAccounts() | |
| let contract = new web3.eth.Contract(metadata.abi) | |
| contract = contract.deploy({ | |
| data: metadata.data.bytecode.object, | |
| arguments: constructorArgs | |
| }) | |
| const newContractInstance = await contract.send({ | |
| from: accounts[0], | |
| gas: 1500000, | |
| gasPrice: '30000000000' | |
| }) | |
| console.log('Contract deployed at address: ', newContractInstance.options.address) | |
| } catch (e) { | |
| console.log(e.message) | |
| } | |
| })() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // SPDX-License-Identifier: GPL-3.0 | |
| pragma solidity >=0.7.0 <0.9.0; | |
| import "remix_tests.sol"; // this import is automatically injected by Remix. | |
| import "../contracts/3_Ballot.sol"; | |
| contract BallotTest { | |
| bytes32[] proposalNames; | |
| Ballot ballotToTest; | |
| function beforeAll () public { | |
| proposalNames.push(bytes32("candidate1")); | |
| ballotToTest = new Ballot(proposalNames); | |
| } | |
| function checkWinningProposal () public { | |
| ballotToTest.vote(0); | |
| Assert.equal(ballotToTest.winningProposal(), uint(0), "proposal at index 0 should be the winning proposal"); | |
| Assert.equal(ballotToTest.winnerName(), bytes32("candidate1"), "candidate1 should be the winner name"); | |
| } | |
| function checkWinninProposalWithReturnValue () public view returns (bool) { | |
| return ballotToTest.winningProposal() == 0; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // SPDX-License-Identifier: GPL-3.0 | |
| pragma solidity >=0.4.22 <0.9.0; | |
| // This import is automatically injected by Remix | |
| import "remix_tests.sol"; | |
| // This import is required to use custom transaction context | |
| // Although it may fail compilation in 'Solidity Compiler' plugin | |
| // But it will work fine in 'Solidity Unit Testing' plugin | |
| import "remix_accounts.sol"; | |
| import "../contracts/pokedx-token.sol"; | |
| // File name has to end with '_test.sol', this file can contain more than one testSuite contracts | |
| contract testSuite { | |
| /// 'beforeAll' runs before all other tests | |
| /// More special functions are: 'beforeEach', 'beforeAll', 'afterEach' & 'afterAll' | |
| function beforeAll() public { | |
| // <instantiate contract> | |
| Assert.equal(uint(1), uint(1), "1 should be equal to 1"); | |
| } | |
| function checkSuccess() public { | |
| // Use 'Assert' methods: https://remix-ide.readthedocs.io/en/latest/assert_library.html | |
| Assert.ok(2 == 2, 'should be true'); | |
| Assert.greaterThan(uint(2), uint(1), "2 should be greater than to 1"); | |
| Assert.lesserThan(uint(2), uint(3), "2 should be lesser than to 3"); | |
| } | |
| function checkSuccess2() public pure returns (bool) { | |
| // Use the return value (true or false) to test the contract | |
| return true; | |
| } | |
| function checkFailure() public { | |
| Assert.notEqual(uint(1), uint(1), "1 should not be equal to 1"); | |
| } | |
| /// Custom Transaction Context: https://remix-ide.readthedocs.io/en/latest/unittesting.html#customization | |
| /// #sender: account-1 | |
| /// #value: 100 | |
| function checkSenderAndValue() public payable { | |
| // account index varies 0-9, value is in wei | |
| Assert.equal(msg.sender, TestsAccounts.getAccount(1), "Invalid sender"); | |
| Assert.equal(msg.value, 100, "Invalid value"); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| pragma solidity ^0.8.6; | |
| interface IUniswap { | |
| function swapExactTokensForETH( | |
| uint amountIn, | |
| uint amountOutMin, | |
| address[] calldata path, | |
| address to, | |
| uint deadline) | |
| external | |
| returns (uint[] memory amounts); | |
| function WETH() external pure returns (address); | |
| } | |
| interface IERC20 { | |
| function transferFrom( | |
| address sender, | |
| address recipient, | |
| uint256 amount | |
| ) external returns (bool); | |
| function approve( | |
| address spender, | |
| uint256 amount | |
| ) external returns (bool); | |
| } | |
| contract UniSwapTokens{ | |
| IUniswap uniswap; | |
| constructor(address _uniswap){ | |
| uniswap = IUniswap(_uniswap); | |
| } | |
| function swapExactTokensForETH( | |
| address token, | |
| uint amountIn, | |
| uint amountOutMin, | |
| uint deadline) | |
| external{ | |
| IERC20 (token).transferFrom(msg.sender, address(this), amountIn); | |
| IERC20 (token).approve(address(uniswap)amountIn); | |
| address[] memory path = new address[](2); | |
| path[0] = token; | |
| path[1] = uniswap.WETH(); | |
| uniswap.swapExactTokensForETH( | |
| amountIn, | |
| amountOutMin, | |
| path, | |
| msg.sender, | |
| deadlin | |
| ); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment