TGViewer
Из Solidity в AI и дальше Из Solidity в AI и дальше @solidityset · 2.47K subscribers
Post #439 201
Объяснение задачи Gatekeeper One от Nekto

В предыдущем посте я попросил участников помочь разобраться с третьим модификатором в задаче, так как я пока не могу понять, что там да как.

Напомню сам модификатор, который требуется пройти:

modifier gateThree(bytes8 _gateKey) {
require(uint32(uint64(_gateKey)) == uint16(uint64(_gateKey)), "GatekeeperOne: invalid gateThree part one");
require(uint32(uint64(_gateKey)) != uint64(_gateKey), "GatekeeperOne: invalid gateThree part two");
require(uint32(uint64(_gateKey)) == uint16(tx.origin), "GatekeeperOne: invalid gateThree part three");
_;
}

Участник сообщества Nekto написал развернутый ответ:

На вход в функцию подается 8 байт (64 бита, 1 байт = 8 бит).

В машинном коде байты хранятся справа налево, те 8 байт можно представить как "(7)(6)(5)(4)(3)(2)(1)(0)" , где (0) - это нулевой байт, (1) - первый байт и т.д.

Теперь uint32 - это число, которое занимает 32 бита или 4 байта. Аналогично uint64 и uint16 - это числа которые занимают 64 бита (8 байт) и 16 бит (2 байта).

Теперь по приведению.

uint64(_gateKey) - переменную _gateKey (8 байт), мы преобразуем в число размером 8 байт, никакой потери информации не происходит так как размер переменных одинаковый.

uint32(uint64(_gateKey)) - мы знаем, что результат uint64(_gateKey) у нас 8 байт, а uint32 - это только 4 байта. Значит будет приведение с потерей информации. Так как байты считаются от нулевого, то фактически мы возьмем байты (3)(2)(1)(0) а остальные выкинем.

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

require(uint32(uint64(_gateKey)) == uint16(uint64(_gateKey)));

чтобы последние 4 байта (uint32) были равны двум последним байтам. Это возможно только в случае, если 2й и 3й байты нулевые, так как 0x0000ABCD = 0xABCD (ABCD это произвольное число в 16й системе).

require(uint32(uint64(_gateKey)) != uint64(_gateKey));

Последние 4 байта (uint32) не равняются 8 байтам исходного числа. Мы уже определили, что 2 и 3й байты нулевые. А из этого условия находим, что байты 4-7 не должны быть нулевыми (пусть будут xFF например).

Т.е. ключ у нас получается 0xFFFFFFFF0000ABCD , осталось найти только ABCD.

require(uint32(uint64(_gateKey)) == uint16(tx.origin));

Нам нужно чтобы последние 4 байта (uint32) от ключа равнялись последним двум байтам (uint16) от tx.origin.

Последние 4 байта от ключа, это у нас 0x0000ABCD, те байт AB и байт CD - это два байта от tx.origin

Итого ключ будет строиться следующим образом

байты (7)-(4) - произвольные данные, но обязательно хоть один не нулевой
байты (3)-(2) - обязательно нулевые
байты (1)-(0) - последние два байта от tx.origin

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

Спасибо Nekto за объяснение!

#ethernaut #gatekeeper #gateone
  • ❤ 1
More from @solidityset
  1. Oct 8, 2026Промо видео для SaaS и других ваших проектов Хочу поделить с вами одним из своих открытий…
  2. Oct 8, 2026video post
  3. Oct 2, 2026Вторая сложность — как доказать, что установилось именно опубликованное. В первом варианте…
  4. Oct 2, 2026Задача с полуоткрытым кодом На днях, в процессе создания одного приложения, столкнулся с и…
  5. Sep 22, 2026Какой язык программирования учить сейчас? На днях в Твиттере увидел небольшой пост о разви…
  6. Sep 18, 2026Интересная модель Jev Буквально пару дней назад в Твиттере многие начали обсуждение новой…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →