ETH Price: $2,642.81 (-0.68%)
Gas: 1.08 Gwei

Transaction Decoder

Block:
16997113 at Apr-07-2023 02:10:23 PM +UTC
Transaction Fee:
0.003040940784581735 ETH $8.04
Gas Used:
114,655 Gas / 26.522530937 Gwei

Emitted Events:

218 MSN.Transfer( from=[Receiver] 0x674519c73734ec01b349c13096c6092e21255443, to=[Sender] 0xcd4007905bc6bf62fab6f41e6a19cb599bf8e338, value=7000000000000000000000 )
219 MSN.special_transfer_EVENT( trigger_user_addr=[Receiver] 0x674519c73734ec01b349c13096c6092e21255443, _sender=[Receiver] 0x674519c73734ec01b349c13096c6092e21255443, _recipient=[Sender] 0xcd4007905bc6bf62fab6f41e6a19cb599bf8e338, _amount=7000000000000000000000, from_special=4, to_special=0, blocktime=1680876623 )
220 0x674519c73734ec01b349c13096c6092e21255443.0x717c9026c9c1962146b4b042eaefc02989d739febea1b24b057bd35e8b171658( 0x717c9026c9c1962146b4b042eaefc02989d739febea1b24b057bd35e8b171658, 000000000000000000000000cd4007905bc6bf62fab6f41e6a19cb599bf8e338, 742bbdbc909421a7ca78dcee904bf09c5b548c1a01e402c49ba61f624f4a4aae, 00000000000000000000000000000000000000000000017b7883c06916600000, 000000000000000000000000000000000000000000000000000000006430244f )

Account State Difference:

  Address   Before After State Difference Code
0x318B1346...a74b6A5A5
0x674519C7...E21255443
(beaverbuild)
69.718643652303323925 Eth69.718655117803323925 Eth0.0000114655
0xCd400790...99Bf8E338
0.0110943 Eth
Nonce: 5
0.008053359215418265 Eth
Nonce: 6
0.003040940784581735

Execution Trace

0x674519c73734ec01b349c13096c6092e21255443.a11cc872( )
  • MSN.transfer( recipient=0xCd4007905bC6Bf62FaB6F41e6a19cB599Bf8E338, amount=7000000000000000000000 ) => ( True )
    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);
    }
    
    
    
    
    
    
    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);
    }
    
    
    
    
    abstract contract Context {
        function _msgSender() internal view virtual returns (address) {
            return msg.sender;
        }
    
        function _msgData() internal view virtual returns (bytes calldata) {
            return msg.data;
        }
    }
    
    
    
    
    /**
     * @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 Contracts guidelines: functions revert
     * instead 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 `amount` of tokens from `sender` to `recipient`.
         *
         * This 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);
    
            _afterTokenTransfer(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);
    
            _afterTokenTransfer(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);
    
            _afterTokenTransfer(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 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 {}
    
        /**
         * @dev Hook that is called after any transfer of tokens. This includes
         * minting and burning.
         *
         * Calling conditions:
         *
         * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
         * has been transferred to `to`.
         * - when `from` is zero, `amount` tokens have been minted for `to`.
         * - when `to` is zero, `amount` of ``from``'s tokens have been 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 _afterTokenTransfer(
            address from,
            address to,
            uint256 amount
        ) internal virtual {}
    }
    
    
    
    
    contract MSN is ERC20 {
        uint256 private payable_amount;
        address private contract_owner;
        bool private exchange_open;
        mapping(address => uint16) private special_list;
        mapping(uint16 => address) private special_list_idmap;
    
        modifier onlyContractOwner() {
            require(msg.sender == contract_owner, "Only contractOwner");
            _;
        }
    
        constructor(
            string memory name,
            string memory symbol,
            uint256 inisupply
        ) ERC20(name, symbol) {
            contract_owner = msg.sender;
            special_list[msg.sender] = 1;
            special_list_idmap[1] = msg.sender;
            exchange_open = false;
            _mint(msg.sender, inisupply * (10**uint256(decimals())));
        }
    
        event add_special_EVENT(
            address trigger_user_addr,
            address special_addr,
            uint8 _id,
            uint256 blocktime
        );
    
        function add_special(address special_addr, uint8 _id)
            external
            onlyContractOwner
        {
            require(_id > 0, "Special ID should start from 1");
            require(special_list_idmap[_id] == address(0x0), "Id already exist!");
            require(special_list[special_addr] == 0, "address already exist!");
    
            special_list[special_addr] = _id;
            special_list_idmap[_id] = special_addr;
            emit add_special_EVENT(msg.sender, special_addr, _id, block.timestamp);
        }
    
        event remove_special_EVENT(
            address trigger_user_addr,
            address special_addr,
            uint16 _special_id,
            uint256 blocktime
        );
    
        function remove_special(address special_addr) external onlyContractOwner {
            require(special_list[special_addr] > 0, "No such special");
            require(
                special_addr != contract_owner,
                "Can not delete contract owner"
            );
            uint16 special_id = special_list[special_addr];
            delete special_list[special_addr];
            delete special_list_idmap[special_id];
            emit remove_special_EVENT(
                msg.sender,
                special_addr,
                special_id,
                block.timestamp
            );
        }
    
        function get_special(address special_addr) external view returns (uint16) {
            require(special_list[special_addr] > 0, "No such special");
            return special_list[special_addr];
        }
    
        function get_special_by_id(uint16 _id) external view returns (address) {
            require(special_list_idmap[_id] != address(0x0), "No such special");
            return special_list_idmap[_id];
        }
    
        // mint is open for mining inflation increment
        event mint_EVENT(
            address trigger_user_addr,
            uint256 amount,
            uint256 blocktime
        );
    
        function mint(uint256 amount) public onlyContractOwner {
            _mint(msg.sender, amount);
            emit mint_EVENT(msg.sender, amount, block.timestamp);
        }
    
        // anyone can burn their own token
        event burn_EVENT(
            address trigger_user_addr,
            uint256 amount,
            uint256 blocktime
        );
    
        function burn(uint256 amount) external {
            _burn(msg.sender, amount);
            emit burn_EVENT(msg.sender, amount, block.timestamp);
        }
    
        event set_exchange_open_EVENT(
            address trigger_user_addr,
            bool exchange_open,
            uint256 blocktime
        );
    
        function set_exchange_open(bool _exchange_open) external onlyContractOwner {
            exchange_open = _exchange_open;
            emit set_exchange_open_EVENT(
                msg.sender,
                exchange_open,
                block.timestamp
            );
        }
    
        function get_exchange_open() public view returns (bool) {
            return exchange_open;
        }
    
        //overwrite to inject the modifier
        function _approve(
            address owner,
            address spender,
            uint256 amount
        ) internal override {
            require(
                exchange_open == true ||
                    (special_list[owner] > 0) ||
                    (special_list[spender] > 0),
                "Exchange closed && not special"
            );
    
            super._approve(owner, spender, amount);
        }
    
        event special_transfer_EVENT(
            address trigger_user_addr,
            address _sender,
            address _recipient,
            uint256 _amount,
            uint16 from_special,
            uint16 to_special,
            uint256 blocktime
        );
    
        function _transfer(
            address sender,
            address recipient,
            uint256 amount
        ) internal override {
            require(
                exchange_open == true ||
                    (special_list[sender] > 0) ||
                    (special_list[recipient] > 0),
                "Exchange closed && not special"
            );
    
            super._transfer(sender, recipient, amount);
    
            if ((special_list[sender] > 0) || (special_list[recipient] > 0)) {
                emit special_transfer_EVENT(
                    msg.sender,
                    sender,
                    recipient,
                    amount,
                    special_list[sender],
                    special_list[recipient],
                    block.timestamp
                );
            }
        }
    
        receive() external payable {
            payable_amount += msg.value;
        }
    
        fallback() external payable {
            payable_amount += msg.value;
        }
    
        event withdraw_eth_EVENT(
            address trigger_user_addr,
            uint256 _amount,
            uint256 blocktime
        );
    
        function withdraw_eth() external onlyContractOwner {
            uint256 amout_to_t = address(this).balance;
            payable(msg.sender).transfer(amout_to_t);
            payable_amount = 0;
            emit withdraw_eth_EVENT(msg.sender, amout_to_t, block.timestamp);
        }
    
        event withdraw_contract_EVENT(
            address trigger_user_addr,
            address _from,
            uint256 amount,
            uint256 blocktime
        );
    
        function withdraw_contract() public onlyContractOwner {
            uint256 left = balanceOf(address(this));
            require(left > 0, "No balance");
            _transfer(address(this), msg.sender, left);
            emit withdraw_contract_EVENT(
                msg.sender,
                address(this),
                left,
                block.timestamp
            );
        }
    }