Як розробник Solidity, який піклується про безпеку, це ваш знак бути дуже обережним при використанні неперевірених блоків і вбудованої збірки. Починаючи з версії 0.8.0 і пізніше, компілятор автоматично оброблятиме недо/переповнення. Але що станеться, якщо змінна, якій дозволено переповнитися, потім використовується в yul? Насправді EVM не має концепції вузьких типів, тому низькорівневий код yul працює з повним 256-бітним розміром слова. Ви вже розумієте, до чого це призводить? У цьому сильно спрощеному сценарії, з яким я зіткнувся у своєму поточному @CyfrinAudits взаємодії, змінна length непомітно переповнює uint8 у непозначеному блоці та обертається до 254, як і очікувалося. Однак, коли вони використовуються для зміни розміру масиву в наступному вбудованому складальному блоці, брудні верхні біти залишаються так, ніби переливу ніколи не було! Це призводить до того, що довжина масиву значно більша, ніж очікувалося, хоча ми могли б очікувати, що він буде обмежений за модулем максимального значення, представленого змінною length. Використовуючи налагоджувач ливарного виробництва та cast --to-base <0xfe|0x01fe> dec, ми можемо підтвердити, що наші припущення були невірними, а верхні біти дійсно залишаються брудними при записі довжини в пам'ять. Хоча цей приклад можна спростити ще більше, ключовий висновок полягає в тому, щоб завжди бути дуже підозрілим щодо неперевірених/збіркових блоків і враховувати, як верхні біти вузьких типів можуть забруднитися, навіть для чогось такого простого в yul, як завдання. Іноді це може здатися езотеричною помилкою, яку неможливо виявити без глибоких знань внутрішніх компонентів компілятора EVM і Solidity, тому, зрозумівши, що на мене чекає, я знайшов цей конкретний приклад дуже корисним. Напишіть мені коментар нижче, якщо у вас виникли запитання, але, сподіваюся, ви також знайшли його корисним!
7,75K