Еще один день, еще одна статья
Сегодня мы продолжим изучать модульное тестирование 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)
Отказ. Снова. Иногда так и бывает — бьешься головой о стену. Но опять провал на новом месте. Это означает, что мы добились прогресса и можем продолжать двигаться вперед.
Тем не менее, на данный момент мой мозг поджарился, так что пора отложить его на сегодня. Спасибо, что присоединились ко мне.