Еще один день, еще одна статья

Сегодня мы продолжим изучать модульное тестирование Anonymice, над которым я работаю.

Музыка!

Больше спокойной музыки. Сегодня пятница, давайте повеселимся.

Отладка функции tokenURI

Давайте рассмотрим на секунду. Во-первых, тестовый скрипт:

И ошибка, на которой мы остановились:

Error: VM Exception while processing transaction: reverted with panic code 0x32 (Array accessed at an out-of-bounds or negative index)
      at Anonymice.hashToSVG (contracts/Anonymice.sol:288)
      at Anonymice.tokenURI (contracts/Anonymice.sol:393)
      at processTicksAndRejections (node:internal/process/task_queues:96:5)
      at runNextTicks (node:internal/process/task_queues:65:3)
      at listOnTimeout (node:internal/timers:536:9)
      at processTimers (node:internal/timers:510:7)
      at async HardhatNode.runCall (node_modules/hardhat/src/internal/hardhat-network/provider/node.ts:534:20)
      at async EthModule._callAction (node_modules/hardhat/src/internal/hardhat-network/provider/modules/eth.ts:353:9)
      at async HardhatNetworkProvider.request (node_modules/hardhat/src/internal/hardhat-network/provider/provider.ts:117:18)

Немного покопавшись и позвонив другу, я узнал, что эта ошибка означает, что искомое нами значение не существует. Мы знаем, что tokenId существует, поэтому давайте посмотрим на трассировку стека, чтобы найти, где мы умерли:

at Anonymice.hashToSVG (contracts/MathHat.sol:288)

Итак, давайте посмотрим на эту функцию и, в частности, на эту строку.

hashToSVG

Большая функция, и цифры в приведенном выше Gist не говорят вам, что мы ищем, так что вот она:

for (
     uint16 j = 0;
     j < traitTypes[i][thisTraitIndex].pixelCount;
     j++
)

Конкретно,

j < traitTypes[i][thisTraitIndex].pixelCount;

Это относится к traitType и количеству пикселей в [thisTraitIndex]. [thisTraitIndex] генерируется из нашего tokenId ранее в функции, так что мне остается только гадать, откуда берутся traitTypes. Давайте искать.

В разделе сопоставление у нас есть:

mapping(uint256 => Trait[]) public traitTypes;
mapping(string => bool) hashToMinted;
mapping(uint256 => string) internal tokenIdToHash;

Таким образом, uint сопоставляются со структурой Trait[].

struct Trait {
   string traitName;
   string traitType;
   string pixels;
   uint256 pixelCount;
}

Быстрый поиск контракта на «Черту». и «типы черт». говорит мне, что нет функций, которые автоматически добавляют признаки или типы признаков. В любом случае это не имело бы особого смысла, так откуда берутся наши черты?

Для этого есть функция addTraitType:

Итак, похоже, нам нужно вызвать эту функцию, чтобы добавить трейты, которые будут использоваться в нашем контракте. Добавим это в наш скрипт:

await mathHatContract.addTraitType(0, [{"traitName": "test1", "traitType": "face", "pixels": "40", "pixelCount": 40}]);

Сначала мы добавляем _traitTypeIndex со значением 0, затем передаем строку JSON с переменными массива. Теперь снова запустим тест.

Mint a mouse!
Contract Address: 0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0
Deployer Address: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
Balance of deployer before mint: 0
Balance of deployer after mint: 1
Balance of deployer after mint: 2
Token Owner: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
    1) Minting a mouse!
2 passing (6s)
  1 failing
1) Mint a mouse!
       Minting a mouse!:
     Error: VM Exception while processing transaction: reverted with panic code 0x32 (Array accessed at an out-of-bounds or negative index)
      at Anonymice.substring (contracts/AnonymiceLibrary.sol:130)
      at Anonymice.hashToSVG (contracts/Anonymice.sol:291)

Блин, опять не получилось. НО… мы потерпели неудачу в другом месте, что для меня означает, что мы добились прогресса. На этот раз мы провалили 130-ю строку контракта AnonymiceLibrary.sol. Это функция, вызываемая функцией hashToSVG ​​контракта Anonymice.sol.

Потерпите меня, это будет ужасно.

Эта функция создает подстроку на основе startIndex и endIndex. Что такое подстрока? Хороший вопрос, не знаю. Время обратиться к всемогущему Google. Хвала. По сути, это просто способ захвата фрагментов строки.

Читать про подстроки здесь

result[i - startIndex] = strBytes[i];

Итак, после долгих копаний и дополнительных инструкций во время сеанса телефонного разговора с другом, я узнал, что проблема заключается в переменных, которые я передаю в функцию addTraitType.

Эта функция подстроки перебирает «пиксели» «pixelCount» за раз. Это сбивает с толку. Например, если для параметра «пиксели» установлено значение «1600», а для параметра «pixelCount» установлено значение «4», то наш hashToSVG ​​будет перебирать 1600 пикселей, по 4 пикселя за раз. То, что я отправил, плохо, потому что я сказал ему перебирать 40 пикселей по 40 пикселей за раз. Итак, давайте обновим этот вызов:

await mathHatContract.addTraitType(0, [{"traitName": "mouse1", "traitType": "face", "pixels": "1600", "pixelCount": 4}]);

Теперь посмотрим, что у нас получится!

1) Mint a mouse!
       Minting a mouse!:
     Error: Transaction reverted without a reason string
      at MathHat.letterToNumber (contracts/Anonymice.sol:267)
      at MathHat.hashToSVG (contracts/Anonymice.sol:297)
      at MathHat.tokenURI (contracts/Anonymice.sol:393)

Отказ. Снова. Иногда так и бывает — бьешься головой о стену. Но опять провал на новом месте. Это означает, что мы добились прогресса и можем продолжать двигаться вперед.

Тем не менее, на данный момент мой мозг поджарился, так что пора отложить его на сегодня. Спасибо, что присоединились ко мне.