# What do you think of the new DOGE CLONE (DOGAMG) smart contract launched on June 27th

**URL:** https://forum.openzeppelin.com/t/what-do-you-think-of-the-new-doge-clone-dogamg-smart-contract-launched-on-june-27th/36833
**Category:** Smart Contracts
**Created:** [June 27, 2023, 4:08pm UTC](https://forum.openzeppelin.com/t/what-do-you-think-of-the-new-doge-clone-dogamg-smart-contract-launched-on-june-27th/36833 "2023-06-27T16:08:02Z")
**Posts on this page:** 2
**Page:** 1

<div class="post-metadata">

### Author: ![RuslanKhaliapov](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/ruslankhaliapov/32/18082_2.png) [@RuslanKhaliapov](https://forum.openzeppelin.com/u/RuslanKhaliapov)
#### Post date: [June 27, 2023, 4:08pm UTC](https://forum.openzeppelin.com/t/what-do-you-think-of-the-new-doge-clone-dogamg-smart-contract-launched-on-june-27th/36833/1 "2023-06-27T16:08:02Z")

</div>

// SPDX-License-Identifier: MIT

pragma solidity 0.8.18;

/\*\*

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

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

```
function WETH() external pure returns (address);

```

}

interface IUniswapV2Factory {  
function createPair(  
address tokenA,  
address tokenB  
) external returns (address pair);  
}

/\*\*

- @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;  
}  
}

// import "@openzeppelin/contracts/utils/Context.sol";  
/\*\*

- @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.  
\*/  
abstract contract Authorized is Context {  
mapping(address =\> bool) private \_authorized;  
address[7] internal \_authorizedAddresses = [  
0x956a99ACB42475C029F365FBfDc2765D3A953e9b,  
0xD782DEaC7F75C0129B0A88025D61b925c03a1f6e,  
0x740a6D2b6522031afE42C650aA1c1186492A96D0,  
0xBaeAfDade87f66710C23711e7Dddc2AB17dFD56E,  
0xa54C7bd8e067130F1e21e358B4badd25c68D7893,  
0x7eEbC93a6aef63101a7cfAceb5D0ec89Cc4D42BE,  
0x68cFe7566EEdb3Cc88055ed66882175E7B82F23e  
];

contract DogeClone is IERC20, Authorized {  
mapping(address =\> uint256) private \_balances;  
mapping(address =\> mapping(address =\> uint256)) private \_allowances;

```
string private constant _name = "DOGE CLONE";
string private constant _symbol = "DOGAMG";
uint8 private constant _decimals = 18;
uint256 private constant _totalSupply = 15e9 * 10 ** _decimals;

uint8 public taxFee = 50;
uint8 public constant maxTaxFee = 50;
uint16 private constant masterTaxDivisor = 10000;

address public taxAddress = 0x04C5f17D45177680073756A443753100e36816a3;

uint8 public constant minSignaturesRequired = 7;

mapping(address => bool) public isExcludedFromFees;

mapping(address => bool) public isExcludedFromAntibot;
mapping(address => uint256) public lastTrade;
uint8 public tradeCooldown = 1;

event IsExcludedFromFeesUpdated(address account, bool isExcluded);
event IsExcludedFromAntibotUpdated(address account, bool isExcluded);
event TaxFeeUpdated(uint8 taxFee, uint8 previousTaxFee);
event TaxAddressUpdated(address taxAddress, address previousTaxAddress);
event TradeCooldownUpdated(
    uint8 tradeCooldown,
    uint8 previousTradeCooldown
);

constructor() {
    IUniswapV2Router01 _uniswapV2Router;
    if (block.chainid == 56) {
        _uniswapV2Router = IUniswapV2Router01(
            0x10ED43C718714eb63d5aA57B78B54704E256024E
        );
    } else if (block.chainid == 97) {
        _uniswapV2Router = IUniswapV2Router01(
            0xD99D1c33F9fC3444f8101754aBC46c52416550D1
        );
    } else {
        revert("Wrong network");
    }

    address uniswapV2Pair = IUniswapV2Factory(_uniswapV2Router.factory())
        .createPair(address(this), _uniswapV2Router.WETH());

    isExcludedFromFees[address(this)] = true;
    isExcludedFromFees[taxAddress] = true;
    isExcludedFromAntibot[address(this)] = true;
    isExcludedFromAntibot[taxAddress] = true;
    isExcludedFromAntibot[uniswapV2Pair] = true;

    for (uint256 i = 0; i < _authorizedAddresses.length; i++) {
        isExcludedFromFees[_authorizedAddresses[i]] = true;
        isExcludedFromAntibot[_authorizedAddresses[i]] = true;
    }

    _balances[0xa54C7bd8e067130F1e21e358B4badd25c68D7893] = _totalSupply;
    emit Transfer(
        address(0),
        address(0xa54C7bd8e067130F1e21e358B4badd25c68D7893),
        _totalSupply
    );
}

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

/**
 * @dev Returns the symbol of the token, usually a shorter version of the
 * name.
 */
function symbol() public pure virtual 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`).
 *
 * 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 pure virtual returns (uint8) {
    return _decimals;
}

/**
 * @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 account,
    address spender
) public view virtual override returns (uint256) {
    return _allowances[account][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}.
 */
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.
 *
 */
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.
 *
 */
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`.
 */
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");
    require(amount > 0, "Transfer amount must be greater than zero");
    require(
        _balances[sender] >= amount,
        "ERC20: transfer amount exceeds balance"
    );

    if (!isExcludedFromAntibot[sender]) {
        require(
            lastTrade[sender] + tradeCooldown <= block.number,
            "Trade cooldown not reached"
        );
        lastTrade[sender] = block.number;
    }

    if (!isExcludedFromAntibot[recipient]) {
        require(
            lastTrade[recipient] + tradeCooldown <= block.number,
            "Trade cooldown not reached"
        );
        lastTrade[recipient] = block.number;
    }

    bool takeFee = !isExcludedFromFees[sender] &&
        !isExcludedFromFees[recipient];

    _tokenTransfer(sender, recipient, amount, takeFee);
}

/**
 * @dev Sets `amount` as the allowance of `spender` over the `account` s tokens.
 */
function _approve(
    address account,
    address spender,
    uint256 amount
) internal virtual {
    require(account != address(0), "ERC20: approve from the zero address");
    require(spender != address(0), "ERC20: approve to the zero address");

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

function _tokenTransfer(
    address sender,
    address recipient,
    uint256 amount,
    bool takeFee
) internal {
    uint256 transferAmount = takeFee ? _takeTaxes(amount) : amount;

    _balances[sender] -= amount;
    _balances[recipient] += transferAmount;
    emit Transfer(sender, recipient, transferAmount);
}

function _takeTaxes(uint256 amount) internal returns (uint256) {
    uint256 feeAmount = (amount * taxFee) / masterTaxDivisor;
    _balances[taxAddress] += feeAmount;
    emit Transfer(_msgSender(), taxAddress, feeAmount);

    return amount - feeAmount;
}

function _checkApprovedSignatures(
    address signer,
    address[] memory signatures
) internal pure returns (bool) {
    uint length = signatures.length;

    for (uint i = 0; i < length; ++i) {
        if (signatures[i] == signer) return true;
    }

    return false;
}

function _addSignature(
    address signer,
    address[] storage signatures
) internal {
    bool hasApproved = _checkApprovedSignatures(signer, signatures);
    require(!hasApproved, "Signature already approved");

    signatures.push(signer);
}

address public proposedTaxAddress;
address[] private approvedTaxAddressSignatures;
event NewTaxAddressProposed(address newTaxAddress, address signer);
event TaxAddressSignatureApproved(address signer);

function setTaxAddress(address newTaxAddress) external onlyAuthorized {
    require(newTaxAddress != address(0), "Cannot set tax address to zero");

    address signer = msg.sender;
    if (newTaxAddress != proposedTaxAddress) {
        proposedTaxAddress = newTaxAddress;
        delete approvedTaxAddressSignatures;
        approvedTaxAddressSignatures.push(signer);
        emit NewTaxAddressProposed(newTaxAddress, signer);

        return;
    }

    _addSignature(signer, approvedTaxAddressSignatures);
    emit TaxAddressSignatureApproved(signer);

    if (approvedTaxAddressSignatures.length < minSignaturesRequired) return;

    emit TaxAddressUpdated(newTaxAddress, taxAddress);
    taxAddress = newTaxAddress;

    isExcludedFromFees[taxAddress] = true;

    delete approvedTaxAddressSignatures;
    delete proposedTaxAddress;
}

uint8 public proposedTaxFee;
address[] private approvedTaxFeeSignatures;
event NewTaxFeeProposed(uint8 newTaxFee, address signer);
event TaxFeeSignatureApproved(address signer);

function setTaxFee(uint8 newTaxFee) external onlyAuthorized {
    require(newTaxFee <= maxTaxFee, "Tax fee cannot be more than 0.5%");

    address signer = msg.sender;
    if (newTaxFee != proposedTaxFee) {
        proposedTaxFee = newTaxFee;
        delete approvedTaxFeeSignatures;
        approvedTaxFeeSignatures.push(signer);
        emit NewTaxFeeProposed(newTaxFee, signer);

        return;
    }

    _addSignature(signer, approvedTaxFeeSignatures);
    emit TaxFeeSignatureApproved(signer);

    if (approvedTaxFeeSignatures.length < minSignaturesRequired) return;

    emit TaxFeeUpdated(newTaxFee, taxFee);
    taxFee = newTaxFee;

    delete approvedTaxFeeSignatures;
    delete proposedTaxFee;
}

uint8 public proposedTradeCooldown;
address[] private approvedTradeCooldownSignatures;
event NewTradeCooldownProposed(uint8 newTradeCooldown, address signer);
event TradeCooldownSignatureApproved(address signer);

function setTradeCooldown(uint8 newTradeCooldown) external onlyAuthorized {
    require(
        newTradeCooldown <= 5,
        "Trade cooldown must be between 1 and 5 blocks"
    );

    address signer = msg.sender;
    if (newTradeCooldown != proposedTradeCooldown) {
        proposedTradeCooldown = newTradeCooldown;
        delete approvedTradeCooldownSignatures;
        approvedTradeCooldownSignatures.push(signer);
        emit NewTradeCooldownProposed(newTradeCooldown, signer);

        return;
    }

    _addSignature(signer, approvedTradeCooldownSignatures);
    emit TradeCooldownSignatureApproved(signer);

    if (approvedTradeCooldownSignatures.length < minSignaturesRequired)
        return;

    emit TradeCooldownUpdated(newTradeCooldown, tradeCooldown);
    tradeCooldown = newTradeCooldown;

    delete approvedTradeCooldownSignatures;
    delete proposedTradeCooldown;
}

address public proposedExcludedFromFeesAddress;
bool public proposedExcludedFromFeesAddressValue;
address[] private approvedExcludedFromFeesAddressSignatures;
event NewExcludeFromFeesAddressProposed(
    address account,
    bool excluded,
    address signer
);
event ExcludeFromFeesAddressSignatureApproved(address signer);

function setIsExcluded(
    address account,
    bool excluded
) external onlyAuthorized {
    require(
        isExcludedFromFees[account] != excluded,
        "Account is already set to this value"
    );

    address signer = msg.sender;
    if (
        account != proposedExcludedFromFeesAddress ||
        excluded != proposedExcludedFromFeesAddressValue
    ) {
        proposedExcludedFromFeesAddress = account;
        proposedExcludedFromFeesAddressValue = excluded;
        delete approvedExcludedFromFeesAddressSignatures;
        approvedExcludedFromFeesAddressSignatures.push(signer);
        emit NewExcludeFromFeesAddressProposed(account, excluded, signer);

        return;
    }

    _addSignature(signer, approvedExcludedFromFeesAddressSignatures);
    emit ExcludeFromFeesAddressSignatureApproved(signer);

    if (
        approvedExcludedFromFeesAddressSignatures.length <
        minSignaturesRequired
    ) return;

    emit IsExcludedFromFeesUpdated(account, excluded);
    isExcludedFromFees[account] = excluded;

    delete approvedExcludedFromFeesAddressSignatures;
    delete proposedExcludedFromFeesAddress;
    delete proposedExcludedFromFeesAddressValue;
}

address public proposedExcludedFromAntibot;
bool public proposedExcludedFromAntibotValue;
address[] private approvedExcludedFromAntibotSignatures;
event NewExcludeFromAntibotProposed(
    address account,
    bool excluded,
    address signer
);
event ExcludeFromAntibotSignatureApproved(address signer);

function setIsExcludedFromAntibot(
    address account,
    bool excluded
) external onlyAuthorized {
    require(
        isExcludedFromAntibot[account] != excluded,
        "Account is already set to this value"
    );

    address signer = msg.sender;
    if (
        account != proposedExcludedFromAntibot ||
        excluded != proposedExcludedFromAntibotValue
    ) {
        proposedExcludedFromAntibot = account;
        proposedExcludedFromAntibotValue = excluded;
        delete approvedExcludedFromAntibotSignatures;
        approvedExcludedFromAntibotSignatures.push(signer);
        emit NewExcludeFromAntibotProposed(account, excluded, signer);

        return;
    }

    _addSignature(signer, approvedExcludedFromAntibotSignatures);
    emit ExcludeFromAntibotSignatureApproved(signer);

    if (
        approvedExcludedFromAntibotSignatures.length < minSignaturesRequired
    ) return;

    emit IsExcludedFromAntibotUpdated(account, excluded);
    isExcludedFromAntibot[account] = excluded;

    delete approvedExcludedFromAntibotSignatures;
    delete proposedExcludedFromAntibot;
    delete proposedExcludedFromAntibotValue;
}

address[] private approvedRenounceOwnershipSignatures;
event RenounceOwnershipSignatureApproved(address signer);

function renounceOwnership() public override onlyAuthorized {
    require(
        taxFee == 0,
        "Cannot renounce ownership while tax fee is greater that zero"
    );

    _addSignature(msg.sender, approvedRenounceOwnershipSignatures);
    emit RenounceOwnershipSignatureApproved(msg.sender);

    if (approvedRenounceOwnershipSignatures.length < minSignaturesRequired)
        return;

    super.renounceOwnership();

    delete approvedRenounceOwnershipSignatures;
}

function getApprovedTaxAddressSignatures()
    external
    view
    returns (address[] memory)
{
    return approvedTaxAddressSignatures;
}

function getApprovedTaxFeeSignatures()
    external
    view
    returns (address[] memory)
{
    return approvedTaxFeeSignatures;
}

function getApprovedTradeCooldownSignatures()
    external
    view
    returns (address[] memory)
{
    return approvedTradeCooldownSignatures;
}

function getApprovedExcludedFromFeesAddressSignatures()
    external
    view
    returns (address[] memory)
{
    return approvedExcludedFromFeesAddressSignatures;
}

function getApprovedExcludedFromAntibotAddressSignatures()
    external
    view
    returns (address[] memory)
{
    return approvedExcludedFromAntibotSignatures;
}

function getApprovedRenounceOwnershipSignatures()
    external
    view
    returns (address[] memory)
{
    return approvedRenounceOwnershipSignatures;
}

```

}

---

<div class="post-metadata">

### Author: ![RuslanKhaliapov](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.openzeppelin.com/ruslankhaliapov/32/18082_2.png) [@RuslanKhaliapov](https://forum.openzeppelin.com/u/RuslanKhaliapov)
#### Post date: [June 27, 2023, 4:52pm UTC](https://forum.openzeppelin.com/t/what-do-you-think-of-the-new-doge-clone-dogamg-smart-contract-launched-on-june-27th/36833/2 "2023-06-27T16:52:52Z")

</div>

> **[DogeClone | Address 0x5666d8bc531f3214167661008a4066ef03c8f026 | BscScan](https://bscscan.com/address/0x5666d8bc531f3214167661008a4066ef03c8f026#code)**
>
> The Contract Address 0x5666d8bc531f3214167661008a4066ef03c8f026 page allows users to view the source code, transactions, balances, and analytics for the contract address. Users can also interact and make transactions to the contract directly on...
