ETH Price: $2,524.28 (-0.39%)

Transaction Decoder

Block:
19062429 at Jan-22-2024 12:59:35 PM +UTC
Transaction Fee:
0.001924309561878702 ETH $4.86
Gas Used:
129,587 Gas / 14.849557146 Gwei

Account State Difference:

  Address   Before After State Difference Code
0x112b0862...41f36C582
0.14234904263469914 Eth0.14236200133469914 Eth0.0000129587
0x267942a8...c9A1e9E37
0.00895652937282738 Eth
Nonce: 155
0.007032219810948678 Eth
Nonce: 156
0.001924309561878702
0x52433781...b633c2aB5

Execution Trace

TokenFarm.claimRewards( _pid=0 )
  • ChaingeWrappedToken.transferFrom( sender=0xb11814F6e0A67a928B2F8A0BAE32871dCf73d835, recipient=0x267942a89bD2ED9d31E7ae25E83Bfd8c9A1e9E37, amount=52631464692 ) => ( True )
    File 1 of 2: TokenFarm
    // SPDX-License-Identifier: MIT
    
    pragma solidity ^0.8.9;
    
    library SafeMathInt {
        int256 private constant MIN_INT256 = int256(1) << 255;
        int256 private constant MAX_INT256 = ~(int256(1) << 255);
    
        function mul(int256 a, int256 b) internal pure returns (int256) {
            int256 c = a * b;
    
            require(c != MIN_INT256 || (a & MIN_INT256) != (b & MIN_INT256));
            require((b == 0) || (c / b == a), 'mul overflow');
            return c;
        }
    
        function div(int256 a, int256 b) internal pure returns (int256) {
            require(b != -1 || a != MIN_INT256);
    
            return a / b;
        }
    
        function sub(int256 a, int256 b) internal pure returns (int256) {
            int256 c = a - b;
            require((b >= 0 && c <= a) || (b < 0 && c > a),
                'sub overflow');
            return c;
        }
    
        function add(int256 a, int256 b) internal pure returns (int256) {
            int256 c = a + b;
            require((b >= 0 && c >= a) || (b < 0 && c < a),
                'add overflow');
            return c;
        }
    
        function abs(int256 a) internal pure returns (int256) {
            require(a != MIN_INT256,
                'abs overflow');
            return a < 0 ? -a : a;
        }
    
        function max(uint256 a, uint256 b) internal pure returns (uint256) {
            return a >= b ? a : b;
        }
    
        function min(uint256 a, uint256 b) internal pure returns (uint256) {
            return a < b ? a : b;
        }
    }
    
    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) {
            require(b > 0, errorMessage);
            uint256 c = a / b;
    
            return c;
        }
    
        function mod(uint256 a, uint256 b) internal pure returns (uint256) {
            require(b != 0,
                'parameter 2 can not be 0');
            return a % b;
        }
    
        function max(uint256 a, uint256 b) internal pure returns (uint256) {
            return a >= b ? a : b;
        }
    
        function min(uint256 a, uint256 b) internal pure returns (uint256) {
            return a < b ? a : b;
        }
    }
    
    interface IBEP20 {
    
        function name() external view returns (string memory);
        function symbol() external view returns (string memory);
        function decimals() external view returns (uint8);
    
        function totalSupply() external view returns (uint256);
    
        function balanceOf(address who) external view returns (uint256);
    
        function allowance(address owner, address spender)
        external
        view
        returns (uint256);
    
        function transfer(address to, uint256 value) external returns (bool);
    
        function approve(address spender, uint256 value) external returns (bool);
    
        function transferFrom(
            address from,
            address to,
            uint256 value
        ) external returns (bool);
    
        event Transfer(address indexed from, address indexed to, uint256 value);
    
        event Approval(
            address indexed owner,
            address indexed spender,
            uint256 value
        );
    }
    
    contract Ownable {
        address private _owner;
    
        event OwnershipRenounced(address indexed previousOwner);
        event TransferOwnerShip(address indexed previousOwner);
    
        event OwnershipTransferred(
            address indexed previousOwner,
            address indexed newOwner
        );
    
        constructor() {
            _owner = msg.sender;
        }
    
        function owner() public view returns (address) {
            return _owner;
        }
    
        modifier onlyOwner() {
            require(msg.sender == _owner, 'Not owner');
            _;
        }
    
        function renounceOwnership() public onlyOwner {
            emit OwnershipRenounced(_owner);
            _owner = address(0);
        }
    
        function transferOwnership(address newOwner) public onlyOwner {
            emit TransferOwnerShip(newOwner);
            _transferOwnership(newOwner);
        }
    
        function _transferOwnership(address newOwner) internal {
            require(newOwner != address(0),
                'Owner can not be 0');
            emit OwnershipTransferred(_owner, newOwner);
            _owner = newOwner;
        }
    }
    
    contract TokenFarm is Ownable {
    
        using SafeMath for uint256;
        using SafeMathInt for int256;
    
        address public tokenWallet;
    
        struct UserInfo {
            uint256 amount;     // How many tokens the user has provided.
            uint256 stakingTime; // The time at which the user staked tokens.
            uint256 rewardClaimed; // The amount of reward claimed by the user.
        }
    
        struct PoolInfo {
            address tokenAddress;
            address rewardTokenAddress;
            uint256 maxPoolSize; 
            uint256 currentPoolSize;
            uint256 maxContribution;
            uint256 minContribution;
            uint256 apy; // it is in 1000 times, so 1000 means 100%
            uint256 emergencyFees; // it is the fees in percentage, final fees is emergencyFees/1000
            uint256 minLockDays;
            uint256 totalRewardsClaimed; // total rewards claimed by the users
            bool poolType; // true for public staking, false for whitelist staking
            bool poolActive;
        }
    
        // Info of each pool.
        PoolInfo[] public poolInfo;
        uint256 [] public rewardTimes;
        bool lock_= false;
    
        uint256 public totalRewardsClaimed = 0;
        // Info of each user that stakes tokens.
        mapping (uint256 => mapping (address => UserInfo)) public userInfo;
        mapping (uint256 => mapping (address => bool)) public whitelistedAddress;
        mapping (uint256 => uint256) public rewardAmount;
        mapping (uint256 => uint256) public rewardCurrentPoolSize;
    
        event Deposit(address indexed user, uint256 indexed pid, uint256 amount);
        event Withdraw(address indexed user, uint256 indexed pid, uint256 amount);
        event EmergencyWithdraw(address indexed user, uint256 indexed pid, uint256 amount);
    
    
        constructor (address _wallet) {
            require(_wallet != address(0), "Invalid wallet address");
            tokenWallet = _wallet;
        }
    
    
        modifier lock {
            require(!lock_, "Process is locked");
            lock_ = true;
            _;
            lock_ = false;
        }
    
        function poolLength() public view returns (uint256) {
            return poolInfo.length;
        }
    
        function addPool (address _tokenAddress, address _rewardTokenAddress, uint256 _maxPoolSize, uint256 _maxContribution,uint256 _emergencyFee, uint256 _minContribution, uint256 _apy, uint256 _minLockDays, bool _poolType, bool _poolActive) public onlyOwner {
            poolInfo.push(PoolInfo({
                tokenAddress: _tokenAddress,
                rewardTokenAddress: _rewardTokenAddress,
                maxPoolSize: _maxPoolSize,
                currentPoolSize: 0,
                minContribution: _minContribution,
                maxContribution: _maxContribution,
                apy: _apy,
                emergencyFees: _emergencyFee,
                minLockDays: _minLockDays,
                poolType: _poolType,
                poolActive: _poolActive,
                totalRewardsClaimed: 0
            }));
        }
    
        function updateMaxPoolSize (uint256 _pid, uint256 _maxPoolSize) public onlyOwner{
            require (_pid < poolLength(), "Invalid pool ID");
            require (_maxPoolSize >= poolInfo[_pid].currentPoolSize, "Cannot reduce the max size below the current pool size");
            poolInfo[_pid].maxPoolSize = _maxPoolSize;
        }
    
        function updateMaxContribution (uint256 _pid, uint256 _maxContribution) public onlyOwner{
            require (_pid < poolLength(), "Invalid pool ID");
            poolInfo[_pid].maxContribution = _maxContribution;
        }
    
        function updateEmergencyFees (uint256 _pid, uint256 _emergencyFees) public onlyOwner {
            require (_pid < poolLength(), "Invalid pool ID");
            if (poolInfo[_pid].currentPoolSize > 0){
                require (_emergencyFees <= poolInfo[_pid].emergencyFees, "You can't increase the emergency fees when people started staking");
            }
            poolInfo[_pid].emergencyFees = _emergencyFees;
        }
    
        function updateRewardToken(address _rewardTokenAddress, uint256 _pid) public onlyOwner {
            require (_pid < poolLength(), "Invalid pool ID");
            poolInfo[_pid].rewardTokenAddress = _rewardTokenAddress;
        }
    
        function updateToken(address _tokenAddress, uint256 _pid) public onlyOwner {
            require (_pid < poolLength(), "Invalid pool ID");
            poolInfo[_pid].tokenAddress = _tokenAddress;
        }
    
        function updateTokenWallet(address _wallet) public onlyOwner {
            require (_wallet != address(0), "Invalid wallet address");
            tokenWallet = _wallet;
        }
    
        function updateMinLockDays (uint256 _pid, uint256 _lockDays) public onlyOwner {
            require (_pid < poolLength(), "Invalid pool ID");
            require (poolInfo[_pid].currentPoolSize == 0, "Cannot change lock time after people started staking");
            poolInfo[_pid].minLockDays = _lockDays;
        }
    
        function updateApy (uint256 _pid, uint256 _apy) public onlyOwner {
            require (_pid < poolLength(), "Invalid pool ID");
            poolInfo[_pid].apy = _apy;
        }
    
        function updatePoolType (uint256 _pid, bool _poolType) public onlyOwner {
            require (_pid < poolLength(), "Invalid pool ID");
            poolInfo[_pid].poolType = _poolType;
        }
    
        function updatePoolActive (uint256 _pid, bool _poolActive) public onlyOwner {
            require (_pid < poolLength(), "Invalid pool ID");
            poolInfo[_pid].poolActive = _poolActive;
        }
    
        function updateMinContribution (uint256 _pid, uint256 _minContribution) public onlyOwner {
            require (_pid < poolLength(), "Invalid pool ID");
            poolInfo[_pid].minContribution = _minContribution;
        }
    
        function addWhitelist (uint256 _pid, address [] memory _whitelistAddresses) public onlyOwner {
            require (_pid < poolLength(), "Invalid pool ID");
            uint256 length = _whitelistAddresses.length;
            require (length<= 200, "Can add only 200 wl at a time");
            for (uint256 i = 0; i < length; i++){
                address _whitelistAddress = _whitelistAddresses[i];
                whitelistedAddress[_pid][_whitelistAddress] = true;
            }
        }
    
        function addReward (uint256 _pid, uint256 _amount) public onlyOwner {
            rewardTimes.push(block.timestamp);
            rewardAmount[block.timestamp] = _amount;
            rewardCurrentPoolSize[block.timestamp] = poolInfo[_pid].currentPoolSize;
            address _rewardTokenAddress = poolInfo[_pid].rewardTokenAddress;
            IBEP20 rewardToken = IBEP20 (_rewardTokenAddress);
            bool success = rewardToken.transferFrom(msg.sender, tokenWallet, _amount);
            require(success, "Transfer failed");
        }
    
        function emergencyLock (bool _lock) public onlyOwner {
            lock_ = _lock;
        }
    
        function stakeTokens (uint256 _pid, uint256 _amount) public lock {
            require (_pid < poolLength(), "Invalid pool ID");
            require (poolInfo[_pid].poolActive, "Pool is not active");
            require (_amount >= (userInfo[_pid][msg.sender].amount).add(poolInfo[_pid].minContribution), "Amount is less than min contribution");
            require (poolInfo[_pid].currentPoolSize.add(_amount) <= poolInfo[_pid].maxPoolSize, "Staking exceeds max pool size");
            require ((userInfo[_pid][msg.sender].amount).add(_amount) <= poolInfo[_pid].maxContribution , "Max Contribution exceeds");
            
            if (poolInfo[_pid].poolType == false){
                require (whitelistedAddress[_pid][msg.sender], "You are not whitelisted for this pool");
            }
    
            // Sending the claimable tokens to the user
            if (claimableRewards(_pid, msg.sender) > 0){
                claimRewards(_pid);
            }
    
            address _tokenAddress = poolInfo[_pid].tokenAddress;
            IBEP20 token = IBEP20 (_tokenAddress);
            bool success = token.transferFrom(msg.sender, tokenWallet, _amount);
            require (success, "Transfer From failed. Please approve the token");
    
            poolInfo[_pid].currentPoolSize = (poolInfo[_pid].currentPoolSize).add(_amount);
            uint256 _stakingTime = block.timestamp; 
            _amount = _amount.add(userInfo[_pid][msg.sender].amount);
            uint256 _rewardClaimed = 0;
            userInfo[_pid][msg.sender] = UserInfo ({
                amount: _amount,
                stakingTime: _stakingTime,
                rewardClaimed: _rewardClaimed
            });
        }
    
        function claimableRewards (uint256 _pid, address _user) public view returns (uint256) {
            require (_pid < poolLength(), "Invalid pool ID");
    
            uint256 _stakingTime = userInfo[_pid][_user].stakingTime;
            uint256 lockDays = (block.timestamp - _stakingTime) / 1 days;
            if(lockDays < poolInfo[_pid].minLockDays) return 0;
            if (userInfo[_pid][_user].amount == 0) return 0;
    
            uint256 _claimableReward = 0;
            for (uint256 i = 0; i < rewardTimes.length; i++){
                uint256 _rewardTime = rewardTimes[i];
                uint256 _rewardAmount = rewardAmount[_rewardTime];
                uint256 _rewardCurrentPoolSize = rewardCurrentPoolSize[_rewardTime];
                if (_rewardTime > _stakingTime){
                    uint256 _refundValue = ((userInfo[_pid][_user].amount * _rewardAmount) / (_rewardCurrentPoolSize));
                    _claimableReward = _claimableReward.add(_refundValue);
                }
            }
            if (userInfo[_pid][_user].rewardClaimed >= _claimableReward) return 0;
            return _claimableReward - userInfo[_pid][_user].rewardClaimed;
        }
    
        function claimableNativeRewards (uint256 _pid, address _user) public view returns (uint256) {
            require (_pid < poolLength(), "Invalid pool ID");
    
            uint256 lockDays = (block.timestamp - userInfo[_pid][_user].stakingTime) / 1 days;
            uint256 _refundValue = ((userInfo[_pid][_user].amount *  poolInfo[_pid].apy * lockDays) / (1000 * 365));
            return _refundValue;
        }
    
        function unstakeTokens (uint256 _pid) public lock {
            require (_pid < poolLength(), "Invalid pool ID");
            require (userInfo[_pid][msg.sender].amount > 0 , "You don't have any staked tokens");
            require (userInfo[_pid][msg.sender].stakingTime > 0 , "You don't have any staked tokens");
            // check the min lock days is passed or not
            uint256 lockDays = (block.timestamp - userInfo[_pid][msg.sender].stakingTime) / 1 days;
            require (lockDays >= poolInfo[_pid].minLockDays, "You can't unstake before min lock days");
            
            address _tokenAddress = poolInfo[_pid].tokenAddress;
            IBEP20 token = IBEP20 (_tokenAddress);
            address _rewardTokenAddress = poolInfo[_pid].rewardTokenAddress;
            IBEP20 rewardToken = IBEP20 (_rewardTokenAddress);
            uint256 _amount = userInfo[_pid][msg.sender].amount;
    
            uint256 _refundValue = claimableRewards(_pid, msg.sender);
            uint256 _nativeReward = claimableNativeRewards(_pid, msg.sender);
            userInfo[_pid][msg.sender].rewardClaimed += _refundValue;
            poolInfo[_pid].currentPoolSize = (poolInfo[_pid].currentPoolSize).sub(userInfo[_pid][msg.sender].amount);
            poolInfo[_pid].totalRewardsClaimed += _refundValue;
            userInfo[_pid][msg.sender].amount = 0;
            userInfo[_pid][msg.sender].rewardClaimed = 0;
    
            bool success1 = token.transferFrom(tokenWallet,msg.sender, _amount);
            bool success2 = token.transferFrom(tokenWallet,msg.sender, _nativeReward);
            bool success3 = rewardToken.transferFrom(tokenWallet,msg.sender, _refundValue);
            require(success1 && success2 && success3, "Transfer failed");
        }
    
        function claimRewards (uint256 _pid) public lock {
            require (_pid < poolLength(), "Invalid pool ID");
            require (userInfo[_pid][msg.sender].amount > 0 , "You don't have any staked tokens");
            require (userInfo[_pid][msg.sender].stakingTime > 0 , "You don't have any staked tokens");
    
            address _rewardTokenAddress = poolInfo[_pid].rewardTokenAddress;
            IBEP20 rewardToken = IBEP20 (_rewardTokenAddress);
            uint256 _refundValue = claimableRewards(_pid, msg.sender);
            require(_refundValue > 0, "No rewards to claim"); // check if there is any reward to claim
            userInfo[_pid][msg.sender].rewardClaimed += _refundValue;
            poolInfo[_pid].totalRewardsClaimed += _refundValue;
            bool success = rewardToken.transferFrom(tokenWallet,msg.sender, _refundValue);
            require(success, "Transfer failed");
        }
    
        // emergency withdraw function
        function emergencyWithdraw (uint256 _pid) public lock {
            require (_pid < poolLength(), "Invalid pool ID");
            require (userInfo[_pid][msg.sender].amount > 0 , "You don't have any staked tokens");
            require (userInfo[_pid][msg.sender].stakingTime > 0 , "You don't have any staked tokens");
    
            address _tokenAddress = poolInfo[_pid].tokenAddress;
            IBEP20 token = IBEP20 (_tokenAddress);
            uint256 _amount = userInfo[_pid][msg.sender].amount;
            userInfo[_pid][msg.sender].amount = 0;
            userInfo[_pid][msg.sender].rewardClaimed = 0;
            poolInfo[_pid].currentPoolSize = (poolInfo[_pid].currentPoolSize).sub(_amount);
    
            uint256 afterDeductAmount = _amount.sub((_amount * poolInfo[_pid].emergencyFees) / 1000);
            bool success = token.transferFrom(tokenWallet,msg.sender, afterDeductAmount);
            require(success, "Transfer failed");
        }
    
        // this function is to withdraw BNB sent to this address by mistake
        function withdrawEth () external onlyOwner returns (bool) {
            uint256 balance = address(this).balance;
            (bool success, ) = payable(msg.sender).call{
                value: balance
            }("");
            return success;
        }
    
        // this function is to withdraw BEP20 tokens sent to this address by mistake
        function withdrawBEP20 (address _tokenAddress) external onlyOwner returns (bool) {
            IBEP20 token = IBEP20(_tokenAddress);
            uint256 balance = token.balanceOf(address(this));
            bool success = token.transfer(msg.sender, balance);
            return success;
        }
    }

    File 2 of 2: ChaingeWrappedToken
    //SPDX-License-Identifier: MIT
    
    pragma solidity =0.6.6;
    
    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) {
            require(b > 0, errorMessage);
            uint256 c = a / b;
            return c;
        }
    
    
        function mod(uint256 a, uint256 b) internal pure returns (uint256) {
            return mod(a, b, "SafeMath: modulo by zero");
        }
    
    
        function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
            require(b != 0, errorMessage);
            return a % b;
        }
    }
    
    
    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);
    }
    
    abstract contract Context {
        function _msgSender() internal view virtual returns (address payable) {
            return msg.sender;
        }
    
        function _msgData() internal view virtual returns (bytes memory) {
            this;
            return msg.data;
        }
    }
    
    abstract contract Pausable is Context {
    
        event Paused(address account);
    
    
        event Unpaused(address account);
    
        bool private _paused;
    
        constructor () internal {
            _paused = false;
        }
    
    
        function paused() public view returns (bool) {
            return _paused;
        }
    
    
        modifier whenNotPaused() {
            require(!_paused, "Pausable: paused");
            _;
        }
    
    
        modifier whenPaused() {
            require(_paused, "Pausable: not paused");
            _;
        }
    
    
        function _pause() internal virtual whenNotPaused {
            _paused = true;
            emit Paused(_msgSender());
        }
    
    
        function _unpause() internal virtual whenPaused {
            _paused = false;
            emit Unpaused(_msgSender());
        }
    }
    
    contract ERC20 is Context, IERC20 {
        using SafeMath for uint256;
    
        mapping (address => uint256) private _balances;
    
        mapping (address => mapping (address => uint256)) private _allowances;
    
        uint256 private _totalSupply;
    	
        string private _name;
        string private _symbol;
        uint8 private _decimals;
    
        constructor (string memory name_, string memory symbol_, uint8 decimals_) public {
            _name = name_;
            _symbol = symbol_;
            _decimals = decimals_;
        }
    
        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 _totalSupply;
        }
    
    
        function balanceOf(address account) public view override returns (uint256) {
            return _balances[account];
        }
    
    
        function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
            _transfer(_msgSender(), recipient, amount);
            return true;
        }
    
    
        function allowance(address owner, address spender) public view virtual override returns (uint256) {
            return _allowances[owner][spender];
        }
    
    
        function approve(address spender, uint256 amount) public virtual override returns (bool) {
            _approve(_msgSender(), spender, amount);
            return true;
        }
    
    
        function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {
            _transfer(sender, recipient, amount);
            _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
            return true;
        }
    
    
        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 _transfer(address sender, address recipient, uint256 amount) internal virtual {
            require(sender != address(0), "ERC20: transfer from the zero address");
            require(recipient != address(0), "ERC20: transfer to the zero address");
    
            _beforeTokenTransfer(sender, recipient, amount);
    
            _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
            _balances[recipient] = _balances[recipient].add(amount);
            emit Transfer(sender, recipient, amount);
        }
    
    
        function _mint(address account, uint256 amount) internal virtual {
            require(account != address(0), "ERC20: mint to the zero address");
    
            _beforeTokenTransfer(address(0), account, amount);
    
            _totalSupply = _totalSupply.add(amount);
            _balances[account] = _balances[account].add(amount);
            emit Transfer(address(0), account, amount);
        }
    
    
        function _burn(address account, uint256 amount) internal virtual {
            require(account != address(0), "ERC20: burn from the zero address");
    
            _beforeTokenTransfer(account, address(0), amount);
    
            _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
            _totalSupply = _totalSupply.sub(amount);
            emit Transfer(account, address(0), amount);
        }
    
        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);
        }
    
        function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }
    }
    
    abstract contract ERC20Pausable is ERC20, Pausable {
        function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override {
            super._beforeTokenTransfer(from, to, amount);
    
            require(!paused(), "ERC20Pausable: token transfer while paused");
        }
    }
    
    contract ChaingeWrappedToken is ERC20Pausable {
        address public owner;
        address public controller;
        constructor(string memory name, string memory symbol,uint8 decimal) public ERC20(name,symbol, decimal) {
            owner = msg.sender;
    		controller = msg.sender;
        }
    
        modifier onlyOwner() {
            require(msg.sender == owner,"only owner");
            _;
        }
    
        modifier onlyController() {
            require(msg.sender == controller || msg.sender == owner ,"only controller");
            _;
        }
    
        function pause() public  onlyController {
            _pause();
        }
    
        function unpause() public  onlyController {
            _unpause();
        }
    
        function setOwner(address newOwner) public onlyOwner {
    		owner = newOwner;
        }
    
        function setController(address newController) public onlyOwner {
    		controller = newController;
        }
    
        function mint(address account, uint256 amount) public whenNotPaused onlyController {
            _mint(account, amount);
        }
    	
        function burn(address account , uint256 amount) public whenNotPaused onlyController {
            _burn(account,amount);
        }
    }