EIP-1014: CREATE2 — знать адрес до того, как контракт существует
Раньше адрес контракта выводился из nonce развёртывающего аккаунта — счётчика, меняющегося с каждым развёртыванием, так что предсказать, куда попадёт контракт, было невозможно. CREATE2 выводит адрес из развёртывающего, выбранной вами соли и самого кода: без nonce. Теперь можно вычислить адрес, пополнить его и раздать до того, как контракт вообще развёрнут.
- создание контрактов и адреса
- keccak256
Constantinople, февраль 2019. Среди её опкодов был один, читающийся как сноска, — второй способ создать контракт, — но он незаметно открыл контрфактические кошельки, стейт-каналы, детерминированные фабрики и во многом то, как абстракция аккаунтов назначает адреса. Проблема, которую он решает, — загадка курицы и яйца: можно ли узнать адрес контракта до того, как он развёрнут? С исходным CREATE ответ был «нет», и это «нет» блокировало целый класс архитектур. EIP-1014 — это CREATE2, и он превращает это «нет» в «да». Давайте выведем его.
Проблема: адрес CREATE зависит от nonce
Когда контракт (или аккаунт) развёртывает другой с помощью исходного CREATE, адрес нового контракта — это keccak256(rlp(sender, nonce))[12:] — хеш того, кто его развернул, и его nonce Счётчик для каждого аккаунта: для EOA это число отправленных транзакций; для контракта — число созданных им контрактов. Увеличивается с каждым развёртыванием, так что каждый раз он разный и зависит от порядка. . Nonce — вот в чём подвох: он растёт с каждым развёртыванием, так что один и тот же развёртывающий, создавая два контракта, получает два разных, зависящих от порядка адреса. Вычислить адрес заранее нельзя, если только вы точно не знаете, сколько контрактов развёртывающий создаст до этого, — а как только контракт занял адрес, его nonce уже ушёл вперёд, так что поместить туда что-то ещё никогда нельзя.
→ Шаг 2: заменяем nonce на входные данные, которые вы контролируете.
CREATE2: адрес из отправителя, соли и кода
CREATE2 Опкод Constantinople (0xf5), который развёртывает контракт по адресу, выведенному из развёртывающего, выбранной вызывающим соли и init-кода — детерминированно, без какой-либо зависимости от nonce. полностью отбрасывает nonce и выводит адрес из трёх вещей, которые можно решить заранее: развёртывающего, выбранной вами salt 32-байтное значение, которое развёртывающий выбирает свободно и подмешивает в вывод адреса CREATE2. Изменение соли даёт другой адрес для того же кода; фиксация соли делает адрес воспроизводимым. (соли) и init-кода (точного развёртываемого байткода). Поскольку ни одно из них не является движущимся счётчиком, одни и те же входные данные всегда дают один и тот же адрес — и, что важно, вы можете вычислить его, ничего не развёртывая.
- 1 постоянный префикс, не дающий адресам CREATE2 когда-либо столкнуться с адресами CREATE
- 2 развёртывающий и выбранное вами значение — оба известны заранее
- 3 фиксирует точный байткод; измените код — изменится и адрес
→ Шаг 3: используем адрес до того, как контракт стал реальным.
Выигрыш: контрфактическое развёртывание
Вот тот ход, который делает возможным CREATE2. Вы вычисляете адрес, а затем используете его до развёртывания — раздаёте, отправляете на него ETH, обращаетесь с ним как с настоящим, — хотя контракта там ещё нет. Это counterfactual deployment Заранее вычислить CREATE2-адрес контракта и взаимодействовать с ним (пополнять, ссылаться на него) до развёртывания — а развернуть только когда понадобится. Существование контракта «контрфактично» до этого момента. (контрфактическое развёртывание). Адрес можно пополнять и на него можно ссылаться, пока он пуст; позже тот, кому это нужно, запускает CREATE2 с той же солью и init-кодом, и контракт материализуется точно по этому адресу — уже с ожидающими его средствами.