function bleach(uint128 skinId, uint128 attributes) external payable whenNotPaused {
        require(isBleachAllowed);

        
        if (bleachLastClearTime[msg.sender] == uint256(0)) {
            
            bleachLastClearTime[msg.sender] = now;
        } else {
            if (bleachLastClearTime[msg.sender] < levelClearTime && now > levelClearTime) {
                accountToBleachNum[msg.sender] = 0;
                bleachLastClearTime[msg.sender] = now;
            }
        }

        require(accountToBleachNum[msg.sender] < bleachDailyLimit);
        accountToBleachNum[msg.sender] += 1;

        
        require(msg.sender == skinIdToOwner[skinId]);

        
        require(isOnSale[skinId] == false);

        uint256 bleachNum = 0;
        for (uint256 i = 0; i < 8; i++) {
            if ((attributes & (uint128(1) << i)) > 0) {
                if (freeBleachNum[msg.sender] > 0) {
                    freeBleachNum[msg.sender]--;
                } else {
                    bleachNum++;
                }
            }
        }
        
        require(msg.value >= bleachNum * bleachPrice);

        Skin storage originSkin = skins[skinId];
        
        require(originSkin.mixingWithId == 0);

        uint128 newAppearance = mixFormula.bleachAppearance(originSkin.appearance, attributes);
        originSkin.appearance = newAppearance;

        
        emit Bleach(skinId, newAppearance);
    }