Посібник з оновлення смартконтрактів Rust: від міграції даних до питань безпеки

robot
Генерація анотацій у процесі

Rust смартконтракти养成日记(9)合约升级

Смартконтракти за своєю суттю є програмами, недоліки неможливо уникнути. Навіть після численних тестувань та аудитів смартконтракти можуть мати вразливості. Якщо вразливість контракту буде використана зловмисником, це може призвести до втрати активів користувачів, що матиме серйозні наслідки. Виправлення вразливостей зазвичай потребує оновлення контракту. Окрім виправлення вразливостей, додавання нових функцій також вимагає оновлення контракту. Тому можливість оновлення контракту є дуже важливою. У цій статті буде розглянуто способи оновлення контрактів Rust.

1. Звичні способи оновлення смартконтрактів на Solidity

Ефірні смартконтракти мають незмінність, після розгортання їх не можна змінити. Якщо в контракті є вразливості або потрібні нові функції, можна лише розгорнути новий контракт на блокчейні.

Цей метод стикається з викликами, оскільки після кожного розгортання контракту призначається нова адреса. Усі DApp, що використовують цей контракт, повинні модифікувати адресу контракту, щоб адаптуватися до нового контракту. Крім того, стан старої версії контракту потрібно перенести на нову версію, що робить обсяг роботи з міграції стану складних контрактів великим і схильним до помилок.

Тому зазвичай використовується архітектура, що передбачає розділення даних і логіки, де дані зберігаються в контракті стану, який не обробляє логіку, а вся логіка реалізується в іншому смартконтракті. Таким чином, під час оновлення потрібно лише оновити логічний контракт, не турбуючись про міграцію стану.

Щоб вирішити цю проблему, можна використовувати проксі-контракт (Proxy Contract). Проксі-контракт використовується для зберігання даних і викликає логічний контракт A за допомогою deleGatecall, таким чином дані, які читає і записує контракт A, зберігаються в проксі-контракті. Під час оновлення розгортається новий контракт B, а потім надсилається транзакція, щоб проксі-контракт вказував на новий логічний контракт B.

!

2. Звичайні методи оновлення контрактів NEAR

На прикладі проекту StatusMessage розглянемо поширені методи оновлення контрактів NEAR.

2.1 Структура даних смартконтракту не була змінена

Якщо змінюється лише логіка контракту, без зміни структури даних, можна безпосередньо використовувати near deploy для розгортання нового коду. Дані зі старого контракту можна успішно прочитати.

2.2 Структура даних смартконтракту була змінена

Якщо змінити структуру даних контракту, безпосереднє повторне розгортання призведе до неможливості десеріалізації стану контракту. Це пов'язано з тим, що стан контракту зберігається у формі серіалізованих даних, після повторного розгортання структура даних у коді змінюється, але стан залишається незмінним, нова структура даних не може відповідати старому стану.

2.3 Міграція оновлення смартконтрактів

NEAR надає метод Migrate для допомоги в оновленні контрактів. Додайте метод migrate в новий контракт:

іржа #[private] #[init(ignore_state)] pub fn migrate() -> Self { let old_state: OldStatusMessage = env::state_read().expect('failed'); Сам { слогани: old_state.records, bios: LookupMap::new(b'b'.to_vec()), } }

Під час повторного розгортання смартконтракту викликається метод migrate:

поблизу розгортання
--wasmFile target/wasm32-unknown-unknown/release/status_message.wasm
--initFunction 'migrate'
--initArgs '{}'
--accountId статусповідомлення.blocksec_upgrade.testnet

Таким чином, можна успішно розгорнути новий смартконтракт і перенести старі дані.

!

3. Безпекові міркування щодо оновлення смартконтрактів

Безпека смартконтрактів при оновленні спочатку повинна враховувати контроль доступу, зазвичай смартконтракт може оновлюватися тільки розробником або DAO. Функція оновлення повинна бути функцією only owner, щоб забезпечити її виклик лише власником.

Рекомендується встановити власника контракту як DAO, щоб спільно управляти контрактом через пропозиції та голосування. Особисті рахунки як власники призводять до високої централізації контракту, власник може вільно змінювати дані контракту, а також існує ризик втрати приватного ключа.

Крім того, розробники при міграції контрактів можуть врахувати такі рекомендації:

  • Додайте #[init(ignore_state)] перед функцією міграції, щоб переконатися, що стан не завантажується перед виконанням функції міграції.
  • Після завершення міграції видалити функцію міграції, щоб забезпечити її виклик лише один раз.
  • Нові структури даних ініціалізуються під час міграції.

!

NEAR2.58%
Переглянути оригінал
Ця сторінка може містити контент третіх осіб, який надається виключно в інформаційних цілях (не в якості запевнень/гарантій) і не повинен розглядатися як схвалення його поглядів компанією Gate, а також як фінансова або професійна консультація. Див. Застереження для отримання детальної інформації.
  • Нагородити
  • 6
  • Поділіться
Прокоментувати
0/400
TrustlessMaximalistvip
· 07-19 20:31
Старі традиційні контракти мають занадто багато вразливостей.
Переглянути оригіналвідповісти на0
MetaDreamervip
· 07-19 20:29
Недостатня децентралізація прав є основною небезпекою, я це розумію.
Переглянути оригіналвідповісти на0
YieldChaservip
· 07-19 20:21
Важливе повідомлення рекомендує впровадження поетапно!
Переглянути оригіналвідповісти на0
MevTearsvip
· 07-19 20:17
Шахрайство просто видалити код, просто!
Переглянути оригіналвідповісти на0
PseudoIntellectualvip
· 07-19 20:12
Ну, нормально, просто опанував цей прийом.
Переглянути оригіналвідповісти на0
FarmToRichesvip
· 07-19 20:04
Наскільки важливе виправлення вразливостей, щоб зрозуміти.
Переглянути оригіналвідповісти на0
  • Закріпити