TGViewer
DEV: Рубиновые тона DEV: Рубиновые тона @dev_in_ruby_colors · 3.27K subscribers
Post #360 871
Немного про сигнатуры и селекторы в Solidity.

Сигнатура функции - это, по факту, просто строка, которая содержит имя функции и её аргументы (без указания на место хранения). К примеру, "test(uint256)".

Но вот когда мы обращаемся к этой функции в транзакции, мы не можем просто передать её сигнатуру в виде такой строки. Она должна быть правильно закодирована:

abi.encodeWithSignature("test(uint256)", 42)


В эту же функцию кодирования мы можем сразу добавить передаваемые аргументы (в данном случае, 42).

Но тогда возникает вопрос: а как именно кодируется сама сигнатура? Ответ следующий:

bytes4(keccak256(bytes("test(uint256)")))


То есть мы берём сигнатуру, считаем её хэш и забираем первые 4 байта этого хэша. Получившийся результат называется *селектор* и это именно, что мы используем для указания на вызываемую функцию. К примеру, если в вашем контракте есть функция test, принимающая uint256, то в ABI вы увидите что-то вроде:

"test(uint256)": "29e99f07"


По правую сторону как раз находится селектор этой функции.

При вызове функции первые 4 байта из calldata и будут содержать селектор функции. Это можно проверить либо так:

    function test(uint a) external view returns(bytes4) {
return bytes4(msg.data[0:4]);
}


Либо так:

    function test(uint a) external view returns(bytes4) {
bytes32 temp;
assembly {
temp := calldataload(0)
}
return bytes4(temp);
}


В любом случае результатом и будет тот самый 0x29e99f07. После первых 4 байт будут идти уже сами аргументы, которые передаются в функцию.

    function test(uint a) external view returns(bytes4, bytes32) {
bytes32 temp;
bytes32 _arg1;
assembly {
temp := calldataload(0)
_arg1 := calldataload(4)
}
return (bytes4(temp), _arg1);
}


При вызове функции test с аргументом 1 вернётся

    0:
bytes4: 0x29e99f07
1:
bytes32: 0x0000000000000000000000000000000000000000000000000000000000000001


Эта единичка как раз и видна в bytes32.

Правда всё несколько сложнее, к примеру, с массивами. То есть если у нас есть функция function test(uint[] memory a) и мы вызываем её с аргументом [1,2] то в msg.data будет нечто странное:

0xca1606840000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002


Да, первые 4 байта - это селектор, но зачем там какие-то двойки?

Сделаем следующее:

    function test(uint[] memory a) external view returns(bytes4, bytes32, bytes32, bytes32, bytes32, bytes memory) {
bytes32 temp;
bytes32 _startIn;
bytes32 _elCount;
bytes32 _firstEl;
bytes32 _secondEl;

assembly {
temp := calldataload(0)
_startIn := calldataload(4)
_elCount := calldataload(36)
_firstEl := calldataload(68)
_secondEl := calldataload(100)


}
return (bytes4(temp), _startIn, _elCount, _firstEl, _secondEl, msg.data);
}


Итак, после первых 4 байт идут блоки по bytes32.

* startIn - через сколько байт от начала хранится значение нашего аргумента (массива). Тут вернётся значение 0x20 (нули в начале пропускаю), что равно 32. То есть через 32 байта от начала calldata (плюс ещё 4 байта селектора) начинается наш массив
* elCount - сколько элементов массиве. Вернётся значение 0x00000...02 то есть 2 элемента
* firstEl - первый элемент массива, то есть 0x00000...01
* secondEl - второй элемент, 0x00000...02
  • 🔥 19
  • 👍 1
More from @dev_in_ruby_colors
  1. Oct 4, 2026В этом уроке по абстрактной алгебре говорим про ideals (идеалы), factor (quotient) rings и…
  2. Sep 28, 2026Github буйствует
  3. Sep 26, 2026В этом уроке по абстрактной алгебре говорим про области целостности, делители нуля, характ…
  4. Sep 22, 2026А тем временем сказ о ведьмаке, потерявшем память, уже доступен в виде аудиокниги. Целых 1…
  5. Sep 20, 2026В этом уроке по абстрактной алгебре продолжаем говорить о кольцах: в частности о subrings…
  6. Sep 17, 2026Сделал обзор актуальных библиотек JS для сбора данных, 10 штук бодрых решений на все случа…
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 →