Перейти к основному содержимому

Крафтинг NFT

Описание

Крафтинг представляет собой древовидную систему прокачки NFT путем сжигания NFT более низких уровней и оплаты в UNIT (или других разрешенных токенах).

Модуль интегрирован с контрактом MagnetNftManager и обрабатывается backend сервисом через события.

Логика работы

Механика крафтинга

Для повышения уровня NFT пользователь должен:

  1. Иметь необходимое количество NFT предыдущего уровня
  2. Оплатить комиссию за крафтинг в UNIT (или другом токене)

Конфигурация устанавливается для каждого уровня отдельно:

  • Количество NFT, необходимое для крафтинга
  • Токен для оплаты
  • Стоимость крафтинга

Два сценария крафтинга

Сценарий 1: Прокачка главного NFT

Условие: В списке сжигаемых NFT присутствует root NFT пользователя

Результат:

  • Сжигаются все NFT кроме root
  • Root NFT не минтится заново — обновляется уровень
  • minted = false в событии
  • Backend обновляет уровень существующего root NFT

Пример:

Пользователь крафтит NFT lvl2:
- Имеет: root NFT lvl1 + 2 дополнительных NFT lvl1
- Указывает в списке: [rootId, nft1Id, nft2Id]
- Результат: root NFT → lvl2, nft1 и nft2 сожжены

Сценарий 2: Создание нового NFT

Условие: В списке сжигаемых NFT нет root NFT

Результат:

  • Сжигаются все указанные NFT
  • Минтится новый NFT следующего уровня
  • minted = true в событии
  • Backend создает новую запись NFT

Пример:

Пользователь крафтит NFT lvl2:
- Имеет: root NFT lvl1 + 3 дополнительных NFT lvl1
- Указывает в списке: [nft1Id, nft2Id, nft3Id] (без root)
- Результат: новый NFT lvl2 сминчен, 3 NFT сожжены

Множественный крафтинг (quantity > 1)

Контракт поддерживает крафтинг нескольких NFT за одну транзакцию:

Пример:

craft(product, targetLevel=2, tokenIdsToBurn, paymentToken, quantity=3)

Результат при наличии root в списке:
- root NFT → lvl2
- Дополнительно сминчено 2 новых NFT lvl2
- Все указанные NFT (кроме root) сожжены

Расчет стоимости

Формула расчета цены

Цена для крафтинга уровня N рассчитывается итеративно:

price[N] = (requiredPrevCount × price[N-1]) + craftFee[N]

Где:

  • requiredPrevCount — количество NFT предыдущего уровня
  • price[N-1] — цена предыдущего уровня
  • craftFee[N] — комиссия за крафт уровня N

Пример расчета для lvl3 (при quantity=1):

Конфигурация:
- lvl1: price = 1.5 UNIT
- lvl2: requiredCount = 3, craftFee = 1 UNIT
- lvl3: requiredCount = 3, craftFee = 1 UNIT

Расчет:
price[2] = (3 × 1.5) + 1 = 5.5 UNIT
price[3] = (3 × 5.5) + 1 = 17.5 UNIT

При quantity > 1:

totalPrice = price[N] × quantity

Функция computePrice

apps/contracts-v2/contracts/MagnetNftManager.sol
function computePrice(
address product,
uint256 targetLevel,
address paymentToken,
uint256 quantity
) external view returns (uint256)

Использование на фронтенде:

const price = await nftManager.computePrice(
productAddress,
targetLevel,
unitCoinAddress,
quantity,
);

Интеграция

1. Подготовка к крафтингу (Frontend)

Пользователь выбирает:

  1. Количество NFT для крафтинга (quantity)
  2. NFT предыдущего уровня для сжигания (tokenIdsToBurn[])
    • Опционально включает root NFT
    • Или автоматический выбор на фронтенде

Получение стоимости:

const price = await nftManager.computePrice(
productAddress,
targetLevel,
paymentToken,
quantity,
);

2. Вызов крафтинга

apps/contracts-v2/contracts/MagnetNftManager.sol
function craft(
address product,
uint256 targetLevel,
uint256[] calldata tokenIdsToBurn,
address paymentToken,
uint256 quantity
) external

Параметры:

  • product — адрес контракта MagnetNftProduct
  • targetLevel — целевой уровень крафтинга
  • tokenIdsToBurn — массив ID NFT для сжигания
  • paymentToken — адрес токена оплаты (ZeroAddress для нативной валюты)
  • quantity — количество NFT для крафтинга

3. Обработка события (Backend)

apps/contracts-v2/contracts/MagnetNftManager.sol
event ProductCrafted(
address indexed user,
address indexed product,
uint256[] tokenIds,
uint256 targetLevel,
bool[] minted,
uint256[] burnedTokenIds,
address paymentToken,
uint256 price
);

Алгоритм обработки:

apps/backend/src/nft/nft.service.ts
// Handler: nftService.handleProductCrafted()

1. Удалить все NFT из burnedTokenIds в БД
2. Для каждого i в tokenIds:
if (minted[i] === true) {
// Создать новый NFT
create({
nftId: tokenIds[i],
level: targetLevel,
mainNft: false
})
} else {
// Обновить root NFT
update(rootNft, {
level: targetLevel,
extraOptions: preserveAndUpdate(oldOptions)
})
}
3. Обновить доступы к продуктам (Smartlink/TG-Soft)

Конфигурация крафтинга

Установка конфигурации уровня

apps/contracts-v2/contracts/MagnetNftManager.sol
function setCraftLevelConfig(
address product,
uint256 level,
bool enabled,
uint256 requiredPrevCount
) external onlyRole(DEFAULT_ADMIN_ROLE)

Параметры:

  • level — уровень для настройки (2-15)
  • enabled — доступность крафтинга на этот уровень
  • requiredPrevCount — количество NFT предыдущего уровня

Установка цены крафтинга

apps/contracts-v2/contracts/MagnetNftManager.sol
function setCraftLevelPaymentConfig(
address product,
uint256 level,
address paymentToken,
bool enabled,
uint256 price
) external onlyRole(DEFAULT_ADMIN_ROLE)

Пример настройки:

// Крафт lvl2: 3 NFT lvl1 + 1 UNIT
await nftManager.setCraftLevelConfig(productAddress, 2, true, 3);
await nftManager.setCraftLevelPaymentConfig(
productAddress,
2,
unitCoinAddress,
true,
ethers.parseEther('1'),
);

Ограничения и безопасность

Ограничения

  • Максимальный уровень: 15
  • Пользователь должен быть активирован в Diamond контракте
  • Пользователь должен владеть всеми указанными NFT
  • Достаточно токенов для оплаты
  • Уровень крафта должен быть enabled в конфигурации

Защита

  • ✅ Reentrancy Guard
  • ✅ Проверка владения NFT перед сжиганием
  • ✅ Проверка баланса токенов перед трансфером
  • ✅ Проверка активации пользователя
  • ✅ Валидация конфигурации (enabled, requiredPrevCount > 0)

Деплой и настройка

Скрипт деплоя

Расположение: apps/contracts-v2/deploy/deployNftProductsAndManager.ts

Команда:

pnpm --filter=contract deploy-nft-products-and-manager

Что деплоится:

  1. 2 контракта MagnetNftProduct (Smartlink + TG-Soft)
  2. Контракт MagnetNftManager
  3. Регистрация продуктов в менеджере
  4. Выдача ролей MINTER_ROLE и BURNER_ROLE
  5. Установка адреса Diamond контракта
  6. Настройка тестовой конфигурации (если SHOUD_INIT_TEST_CONFIGS = true)

Тестовая конфигурация

apps/contracts-v2/deploy/deployNftProductsAndManager.ts
// Уровни 2-11 доступны для крафтинга
// Требуется 3 NFT предыдущего уровня
// Цена крафта: 1 UNIT
for (let level = 2; level <= 11; level++) {
await nftManager.setCraftLevelConfig(product, level, true, 3);
await nftManager.setCraftLevelPaymentConfig(
product,
level,
unitCoin,
true,
ethers.parseEther('1'),
);
}

Ссылки