ETH Price: $2,009.87 (+1.92%)

Transaction Decoder

Block:
22188481 at Apr-03-2025 12:48:11 PM +UTC
Transaction Fee:
0.000184354905810754 ETH $0.37
Gas Used:
94,129 Gas / 1.958534626 Gwei

Emitted Events:

624 ChaingeWrappedToken.Transfer( from=0x0000000000000000000000000000000000000000, to=0x6a01dD8e6384Fe7835Cb5cf124201bBd8A670056, value=1002128353729 )
625 MinterProxyV2.LogVaultIn( token=ChaingeWrappedToken, orderID=10000017299, receiver=0x6a01dD8e6384Fe7835Cb5cf124201bBd8A670056, amount=1002128353729, serviceFee=0, gasFee=0 )

Account State Difference:

  Address   Before After State Difference Code
0x112b0862...41f36C582
(MEV Builder: 0x3B...436)
231.40781963764600395 Eth231.40782058834890395 Eth0.0000009507029
0x4c5F5301...E6fA185A5
0xc1474a68...aE58CE2E0
0.270900950526751906 Eth
Nonce: 8121
0.270716595620941152 Eth
Nonce: 8122
0.000184354905810754

Execution Trace

MinterProxyV2.vaultIn( orderID=10000017299, receiveToken=0x112b08621E27e10773ec95d250604a041f36C582, receiver=0x6a01dD8e6384Fe7835Cb5cf124201bBd8A670056, burnable=True, amount=1002128353729 )
  • ChaingeWrappedToken.balanceOf( account=0x6a01dD8e6384Fe7835Cb5cf124201bBd8A670056 ) => ( 0 )
  • ChaingeWrappedToken.mint( account=0x6a01dD8e6384Fe7835Cb5cf124201bBd8A670056, amount=1002128353729 )
  • ChaingeWrappedToken.balanceOf( account=0x6a01dD8e6384Fe7835Cb5cf124201bBd8A670056 ) => ( 1002128353729 )
    File 1 of 2: MinterProxyV2
    // SPDX-License-Identifier: UNLICENSED
    pragma solidity ^0.8.9;
    
    abstract contract Context {
        function _msgSender() internal view virtual returns (address) {
            return msg.sender;
        }
    
        function _msgData() internal view virtual returns (bytes calldata) {
            return msg.data;
        }
    }
    
    abstract contract Ownable is Context {
        address private _owner;
    
        event OwnershipTransferred(
            address indexed previousOwner,
            address indexed newOwner
        );
    
        constructor() {
            _transferOwnership(_msgSender());
        }
    
        function owner() public view virtual returns (address) {
            return _owner;
        }
    
        modifier onlyOwner() {
            require(owner() == _msgSender(), "Ownable: caller is not the owner");
            _;
        }
    
        function transferOwnership(address newOwner) public virtual onlyOwner {
            require(
                newOwner != address(0),
                "Ownable: new owner is the zero address"
            );
            _transferOwnership(newOwner);
        }
    
        function _transferOwnership(address newOwner) internal virtual {
            address oldOwner = _owner;
            _owner = newOwner;
            emit OwnershipTransferred(oldOwner, newOwner);
        }
    }
    
    abstract contract Controller is Ownable {
        event ControllerAdded(address controller);
        event ControllerRemoved(address controller);
        mapping(address => bool) controllers;
        uint8 public controllerCnt = 0;
    
        modifier onlyController() {
            require(isController(_msgSender()), "no controller rights");
            _;
        }
    
        function isController(address _controller) public view returns (bool) {
            return _controller == owner() || controllers[_controller];
        }
    
        function addController(address _controller) public onlyOwner {
            if (controllers[_controller] == false) {
                controllers[_controller] = true;
                controllerCnt++;
            }
            emit ControllerAdded(_controller);
        }
    
        function removeController(address _controller) public onlyOwner {
            if (controllers[_controller] == true) {
                controllers[_controller] = false;
                controllerCnt--;
            }
            emit ControllerRemoved(_controller);
        }
    }
    
    abstract contract ReentrancyGuard {
        uint256 private constant _NOT_ENTERED = 1;
        uint256 private constant _ENTERED = 2;
    
        uint256 private _status;
    
        constructor() {
            _status = _NOT_ENTERED;
        }
    
        modifier nonReentrant() {
            _nonReentrantBefore();
            _;
            _nonReentrantAfter();
        }
    
        function _nonReentrantBefore() private {
            require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
            _status = _ENTERED;
        }
    
        function _nonReentrantAfter() private {
            _status = _NOT_ENTERED;
        }
    
        function _reentrancyGuardEntered() internal view returns (bool) {
            return _status == _ENTERED;
        }
    }
    
    interface IERC20 {
        event Transfer(address indexed from, address indexed to, uint256 value);
    
        event Approval(
            address indexed owner,
            address indexed spender,
            uint256 value
        );
    
        function totalSupply() external view returns (uint256);
    
        function balanceOf(address account) external view returns (uint256);
    
        function transfer(address to, 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 from,
            address to,
            uint256 amount
        ) external returns (bool);
    }
    
    interface IERC20Permit {
        function permit(
            address owner,
            address spender,
            uint256 value,
            uint256 deadline,
            uint8 v,
            bytes32 r,
            bytes32 s
        ) external;
    
        function nonces(address owner) external view returns (uint256);
    
        function DOMAIN_SEPARATOR() external view returns (bytes32);
    }
    
    library Address {
        function isContract(address account) internal view returns (bool) {
            return account.code.length > 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
                functionCallWithValue(
                    target,
                    data,
                    0,
                    "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"
            );
            (bool success, bytes memory returndata) = target.call{value: value}(
                data
            );
            return
                verifyCallResultFromTarget(
                    target,
                    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) {
            (bool success, bytes memory returndata) = target.staticcall(data);
            return
                verifyCallResultFromTarget(
                    target,
                    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) {
            (bool success, bytes memory returndata) = target.delegatecall(data);
            return
                verifyCallResultFromTarget(
                    target,
                    success,
                    returndata,
                    errorMessage
                );
        }
    
        function verifyCallResultFromTarget(
            address target,
            bool success,
            bytes memory returndata,
            string memory errorMessage
        ) internal view returns (bytes memory) {
            if (success) {
                if (returndata.length == 0) {
                    // only check isContract if the call was successful and the return data is empty
                    // otherwise we already know that it was a contract
                    require(isContract(target), "Address: call to non-contract");
                }
                return returndata;
            } else {
                _revert(returndata, errorMessage);
            }
        }
    
        function verifyCallResult(
            bool success,
            bytes memory returndata,
            string memory errorMessage
        ) internal pure returns (bytes memory) {
            if (success) {
                return returndata;
            } else {
                _revert(returndata, errorMessage);
            }
        }
    
        function _revert(
            bytes memory returndata,
            string memory errorMessage
        ) private pure {
            // 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
                /// @solidity memory-safe-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
    
    interface IWrapToken {
        function deposit() external payable;
        function withdraw(uint256) external;
    }
    
    library SafeERC20 {
        using Address for address;
    
        function safeTransfer(IERC20 token, address to, uint256 value) internal {
            _callOptionalReturn(
                token,
                abi.encodeWithSelector(token.transfer.selector, to, value)
            );
        }
    
        function safeTransferFrom(
            IERC20 token,
            address from,
            address to,
            uint256 value
        ) internal {
            _callOptionalReturn(
                token,
                abi.encodeWithSelector(token.transferFrom.selector, from, to, value)
            );
        }
    
        function safeApprove(
            IERC20 token,
            address spender,
            uint256 value
        ) internal {
            require(
                (value == 0) || (token.allowance(address(this), spender) == 0),
                "SafeERC20: approve from non-zero to non-zero allowance"
            );
            _callOptionalReturn(
                token,
                abi.encodeWithSelector(token.approve.selector, spender, value)
            );
        }
    
        function safeIncreaseAllowance(
            IERC20 token,
            address spender,
            uint256 value
        ) internal {
            uint256 oldAllowance = token.allowance(address(this), spender);
            _callOptionalReturn(
                token,
                abi.encodeWithSelector(
                    token.approve.selector,
                    spender,
                    oldAllowance + value
                )
            );
        }
    
        function safeDecreaseAllowance(
            IERC20 token,
            address spender,
            uint256 value
        ) internal {
            unchecked {
                uint256 oldAllowance = token.allowance(address(this), spender);
                require(
                    oldAllowance >= value,
                    "SafeERC20: decreased allowance below zero"
                );
                _callOptionalReturn(
                    token,
                    abi.encodeWithSelector(
                        token.approve.selector,
                        spender,
                        oldAllowance - value
                    )
                );
            }
        }
    
        function forceApprove(
            IERC20 token,
            address spender,
            uint256 value
        ) internal {
            bytes memory approvalCall = abi.encodeWithSelector(
                token.approve.selector,
                spender,
                value
            );
    
            if (!_callOptionalReturnBool(token, approvalCall)) {
                _callOptionalReturn(
                    token,
                    abi.encodeWithSelector(token.approve.selector, spender, 0)
                );
                _callOptionalReturn(token, approvalCall);
            }
        }
    
        function safePermit(
            IERC20Permit token,
            address owner,
            address spender,
            uint256 value,
            uint256 deadline,
            uint8 v,
            bytes32 r,
            bytes32 s
        ) internal {
            uint256 nonceBefore = token.nonces(owner);
            token.permit(owner, spender, value, deadline, v, r, s);
            uint256 nonceAfter = token.nonces(owner);
            require(
                nonceAfter == nonceBefore + 1,
                "SafeERC20: permit did not succeed"
            );
        }
    
        function _callOptionalReturn(IERC20 token, bytes memory data) private {
            bytes memory returndata = address(token).functionCall(
                data,
                "SafeERC20: low-level call failed"
            );
            require(
                returndata.length == 0 || abi.decode(returndata, (bool)),
                "SafeERC20: ERC20 operation did not succeed"
            );
        }
    
        function _callOptionalReturnBool(
            IERC20 token,
            bytes memory data
        ) private returns (bool) {
            (bool success, bytes memory returndata) = address(token).call(data);
            return
                success &&
                (returndata.length == 0 || abi.decode(returndata, (bool))) &&
                Address.isContract(address(token));
        }
    }
    
    library TransferHelper {
        function safeTransferNative(address to, uint256 value) internal {
            (bool success, ) = to.call{value: value}(new bytes(0));
            require(success, "TransferHelper: NATIVE_TRANSFER_FAILED");
        }
    }
    
    interface IMintBurnToken {
        function mint(address to, uint256 amount) external;
    
        function burn(address from, uint256 amount) external;
    }
    
    contract MinterProxyV2 is Controller, ReentrancyGuard {
        using SafeERC20 for IERC20;
        using Address for address;
        using Address for address payable;
    
        address public immutable NATIVE =
            0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
    
        address public wNATIVE;
    
        uint256 MAX_UINT256 =
            0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;
    
        mapping(uint256 => bool) public completedOrder;
    
        address public _liquidpool;
    
        uint256 public _orderID;
    
        bool private _paused;
    
        event Paused(address account);
    
        event Unpaused(address account);
    
        event LogVaultIn(
            address indexed token,
            uint256 indexed orderID,
            address indexed receiver,
            uint256 amount,
            uint256 serviceFee,
            uint256 gasFee
        );
        event LogVaultOut(
            address indexed token,
            address indexed from,
            uint256 indexed orderID,
            uint256 amount,
            address vault,
            bytes order
        );
    
        event LogVaultCall(
            address indexed target,
            uint256 amount,
            bool success,
            bytes reason
        );
    
        constructor(uint256 _id_prefix, address _lp, address _wNative) {
            _liquidpool = _lp;
            _paused = false;
            _orderID = _id_prefix * (10 ** 9);
            wNATIVE = _wNative;
        }
    
        receive() external payable {}
    
        fallback() external payable {}
    
        modifier whenNotPaused() {
            require(!_paused, "MP: paused");
            _;
        }
    
        function chainID() public view returns (uint) {
            return block.chainid;
        }
    
        function setLiquidpool(address _lp) external onlyOwner {
            _liquidpool = _lp;
        }
    
        function setWrapNative(address _wNative) external onlyOwner {
            wNATIVE = _wNative;
        }
    
        function needWrapNative() internal view returns (bool) {
            return wNATIVE != address(0);
        }
    
        function liquidpool() internal view returns (address) {
            if (_liquidpool != address(0)) {
                return _liquidpool;
            }
            return address(this);
        }
    
        function pause() external onlyOwner {
            _paused = true;
            emit Paused(_msgSender());
        }
    
        function unpause() external onlyOwner {
            _paused = false;
            emit Unpaused(_msgSender());
        }
    
        function isUUIDCompleted(uint256 uuid) external view returns (bool) {
            return completedOrder[uuid];
        }
    
        function _registerOrder(uint256 uuid) internal {
            require(!completedOrder[uuid], "MP: already completed");
            completedOrder[uuid] = true;
        }
    
        function _balanceOf(address receiveToken) internal view returns (uint256) {
            uint256 _balance;
            if (receiveToken == NATIVE) {
                if (needWrapNative()) {
                    _balance = IERC20(wNATIVE).balanceOf(liquidpool());
                } else {
                    _balance = address(this).balance;
                }
            } else {
                _balance = IERC20(receiveToken).balanceOf(liquidpool());
            }
            return _balance;
        }
    
        function _balanceOfSelf(
            address receiveToken
        ) internal view returns (uint256) {
            uint256 _balance;
            if (receiveToken == NATIVE) {
                _balance = address(this).balance;
            } else {
                _balance = IERC20(receiveToken).balanceOf(address(this));
            }
            return _balance;
        }
    
        function _checkVaultOut(
            address tokenAddr,
            uint256 amount,
            bytes calldata order
        ) internal pure {
            require(tokenAddr != address(0), "MP: tokenAddress is invalid");
            require(amount > 0, "MP: amount is 0");
            require(order.length > 0, "MP: order is empty");
        }
    
        function vaultOut(
            address tokenAddr,
            uint256 amount,
            bool burnable,
            bytes calldata order
        ) external payable nonReentrant whenNotPaused {
            _checkVaultOut(tokenAddr, amount, order);
    
            if (tokenAddr == NATIVE) {
                require(amount == msg.value, "MP: amount is invalid");
                if (needWrapNative()) {
                    uint256 old = IERC20(wNATIVE).balanceOf(address(this));
                    IWrapToken(wNATIVE).deposit{value: msg.value}();
                    uint256 val = IERC20(wNATIVE).balanceOf(address(this));
                    require(val - old == amount, "MP: warp token dismatch");
                    IERC20(wNATIVE).safeTransfer(_liquidpool, amount);
                } else {
                    TransferHelper.safeTransferNative(_liquidpool, amount);
                }
            } else if (burnable) {
                uint256 old = IERC20(tokenAddr).balanceOf(_msgSender());
                IMintBurnToken(tokenAddr).burn(_msgSender(), amount);
                uint256 val = IERC20(tokenAddr).balanceOf(_msgSender());
                require(val == old - amount, "MP: burn failed");
            } else {
                IERC20(tokenAddr).safeTransferFrom(
                    _msgSender(),
                    liquidpool(),
                    amount
                );
            }
    
            _orderID++;
            emit LogVaultOut(
                tokenAddr,
                _msgSender(),
                _orderID,
                amount,
                burnable ? address(0) : liquidpool(),
                order
            );
        }
    
        function vaultIn(
            uint256 orderID,
            address receiveToken,
            address receiver,
            bool burnable,
            uint256 amount
        ) external onlyController whenNotPaused {
            require(orderID > 0, "MP: orderID empty");
            require(receiver != address(0), "MP: receiver invaild");
            require(amount > 0, "MP: amount is empty");
            if (!burnable) {
                require(
                    _balanceOf(receiveToken) >= amount,
                    "MP: insufficient balance"
                );
            }
            _registerOrder(orderID);
            if (receiveToken == NATIVE) {
                if (needWrapNative()) {
                    IERC20(wNATIVE).safeTransferFrom(
                        liquidpool(),
                        address(this),
                        amount
                    );
                    uint256 old = address(this).balance;
                    IWrapToken(wNATIVE).withdraw(amount);
                    uint256 val = address(this).balance;
                    require(
                        val - old == amount,
                        "MP: native token amount dismatch"
                    );
                }
                TransferHelper.safeTransferNative(receiver, amount);
            } else if (burnable) {
                uint256 old = IERC20(receiveToken).balanceOf(receiver);
                IMintBurnToken(receiveToken).mint(receiver, amount);
                uint256 val = IERC20(receiveToken).balanceOf(receiver);
                require(val == old + amount, "MP: mint failed");
            } else {
                IERC20(receiveToken).safeTransferFrom(
                    liquidpool(),
                    receiver,
                    amount
                );
            }
            emit LogVaultIn(receiveToken, orderID, receiver, amount, 0, 0);
        }
    
        // Fees[] struct
        // 0: uint256 expectAmount
        // 1: uint256 minAmount
        // 2: uint256 feeRate
        // 3: uint256 gasFee
        function vaultInAndCall(
            uint256 orderID,
            address tokenAddr,
            address toAddr,
            bool burnable,
            uint256 amount,
            address receiver,
            address receiveToken,
            uint256[] memory fees,
            bytes calldata data
        ) external onlyController whenNotPaused {
            require(orderID > 0, "MP: orderID empty");
            require(data.length > 0, "MP: data empty");
            require(fees.length == 4, "MP: fees mismatch");
            require(amount > 0, "MP: amount is empty");
            require(fees[1] > 0, "MP: minAmount is empty");
            require(fees[0] > 0, "MP: expectAmount is empty");
            if (!burnable) {
                require(
                    _balanceOf(tokenAddr) >= amount,
                    "MP: insufficient balance"
                );
            }
            require(receiver != address(0), "MP: receiver is empty");
            require(
                toAddr != address(this) && toAddr != address(0),
                "MP: toAddr invaild"
            );
            _registerOrder(orderID);
            bool fromTokenNative = (tokenAddr == NATIVE);
            if (fromTokenNative) {
                if (needWrapNative()) {
                    IERC20(wNATIVE).safeTransferFrom(
                        liquidpool(),
                        address(this),
                        amount
                    );
                    uint256 old = address(this).balance;
                    IWrapToken(wNATIVE).withdraw(amount);
                    uint256 val = address(this).balance;
                    require(
                        val - old == amount,
                        "MP: native token amount dismatch"
                    );
                } else {
                    // the native token in this contract, so ignore
                    require(
                        address(this).balance >= amount,
                        "MP: native token insuffient"
                    );
                }
            } else {
                if (burnable) {
                    uint256 old = IERC20(tokenAddr).balanceOf(address(this));
                    IMintBurnToken(tokenAddr).mint(address(this), amount);
                    uint256 val = IERC20(tokenAddr).balanceOf(address(this));
                    require(val == old + amount, "MP: mint failed");
                } else {
                    IERC20(tokenAddr).safeTransferFrom(
                        _liquidpool,
                        address(this),
                        amount
                    );
                }
                if (IERC20(tokenAddr).allowance(address(this), toAddr) < amount) {
                    IERC20(tokenAddr).safeApprove(toAddr, MAX_UINT256);
                }
            }
    
            (uint256 realOut, uint256 serviceFee) = _callAndTransfer(
                toAddr,
                fromTokenNative ? amount : 0,
                receiveToken,
                fees,
                data
            );
            if (receiver != address(this)) {
                if (receiveToken == NATIVE) {
                    TransferHelper.safeTransferNative(receiver, realOut);
                } else {
                    IERC20(receiveToken).safeTransfer(receiver, realOut);
                }
            }
            uint256 totalfee = serviceFee + fees[3];
            if (totalfee > 0) {
                if (receiveToken == NATIVE) {
                    if (needWrapNative()) {
                        IWrapToken(wNATIVE).deposit{value: totalfee}();
                        IERC20(wNATIVE).safeTransfer(_liquidpool, totalfee);
                    }
                } else {
                    IERC20(receiveToken).safeTransfer(_liquidpool, totalfee);
                }
            }
    
            emit LogVaultIn(
                receiveToken,
                orderID,
                receiver,
                realOut,
                serviceFee,
                fees[3]
            );
        }
    
        // Fees[] struct
        // 0: uint256 expectAmount
        // 1: uint256 minAmount
        // 2: uint256 feeRate
        // 3: uint256 gasFee
        function _callAndTransfer(
            address contractAddr,
            uint256 fromNativeAmount,
            address receiveToken,
            uint256[] memory fees,
            bytes calldata data
        ) internal returns (uint256, uint256) {
            uint256 old_balance = _balanceOfSelf(receiveToken);
    
            if (fromNativeAmount > 0) {
                contractAddr.functionCallWithValue(
                    data,
                    fromNativeAmount,
                    "MP: CallWithValue failed"
                );
            } else {
                contractAddr.functionCall(data, "MP: FunctionCall failed");
            }
            uint256 real = 0;
            uint256 serviceFee = 0;
            {
                uint256 expectAmount = fees[0];
                uint256 minAmount = fees[1];
                uint256 feeRate = fees[2];
                uint256 gasFee = fees[3];
                uint256 new_balance = _balanceOfSelf(receiveToken);
                require(
                    new_balance > old_balance,
                    "MP: receiver should get assets"
                );
                uint256 amountOut = new_balance - old_balance;
                require(amountOut >= minAmount, "MP: receive amount not enough");
                require(amountOut >= minAmount + gasFee, "MP: gasFee not enough");
    
                serviceFee = (amountOut * feeRate) / 10000;
    
                require(
                    amountOut >= minAmount + gasFee + serviceFee,
                    "MP: fee not enough"
                );
                real = amountOut - serviceFee - gasFee;
                if (real > expectAmount) {
                    serviceFee += real - expectAmount;
                    real = expectAmount;
                }
            }
            return (real, serviceFee);
        }
    
        function call(
            address target,
            bytes calldata _data
        ) external payable onlyOwner {
            (bool success, bytes memory result) = target.call{value: msg.value}(
                _data
            );
            emit LogVaultCall(target, msg.value, success, result);
        }
    
        function withdrawFee(
            address token,
            uint256 amount
        ) external onlyController {
            if (token == NATIVE) {
                uint256 balance = address(this).balance;
                uint256 tmp = balance > amount ? amount : balance;
                TransferHelper.safeTransferNative(owner(), tmp);
            } else {
                uint256 balance = IERC20(token).balanceOf(address(this));
                uint256 tmp = balance > amount ? amount : balance;
                IERC20(token).safeTransfer(owner(), tmp);
            }
        }
    }

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