Навіщо потрібен Tenderly Fork у продакшн-тестуванні?
Уявіть: ви розробляєте DeFi-протокол, і потрібно відтворити складний flash loan attack, який стався на певному блоці mainnet. Локальний anvil --fork-url вимагає налаштування у кожного розробника, а стан не зберігається між перезапусками. Ми використовуємо Tenderly Fork для створення ізольованої копії основної мережі з повним контролем стану. Це хмарний форк, доступний за RPC URL, який можна передати команді або аудитору. На відміну від локального anvil --fork-url, форк Tenderly живе в хмарі і не помирає при закритті терміналу. Наш досвід роботи з DeFi-протоколами показує, що такий підхід скорочує час на відтворення багів на 80%, а витрати на інфраструктуру тестування знижуються вдвічі. Tenderly Fork підтримує Ethereum mainnet, Arbitrum, Polygon та інші мережі, що дозволяє тестувати міжмережеві сценарії без розгортання власних нод.
Чому Tenderly Fork перевершує anvil для командної роботи?
anvil --fork-url запускається локально і вмирає разом з процесом. Tenderly Fork створюється через API, живе поки не видалений, його RPC URL можна передати фронтенду або мобільному додатку. Реальний кейс: контракт vault проходить аудит. Аудиторська команда хоче відтворити конкретний attack scenario — drain через flash loan у конкретному стані протоколу. Замість того, щоб налаштовувати локальне середовище у кожного аудитора, створюється Tenderly Fork, закріплюється на блоці з потрібним станом, виставляється потрібний баланс атакуючого. Аудитор отримує один RPC URL. Замовте налаштування Tenderly Fork — і ваша команда заощадить до 70% часу на підготовку тестових середовищ.
Як створити Tenderly Fork через API?
const response = await fetch("https://api.tenderly.co/api/v1/account/MY_ACCOUNT/project/MY_PROJECT/fork", { method: "POST", headers: { "X-Access-Key": process.env.TENDERLY_API_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ network_id: "1", // Ethereum mainnet block_number: 19500000, // конкретний блок transaction_index: 0, initial_balance: 100, chain_config: { chain_id: 1 } }) }); const { simulation_fork } = await response.json(); const forkRpcUrl = `https://rpc.tenderly.co/fork/${simulation_fork.id}`; Маніпуляція станом через JSON-RPC
Tenderly Fork підтримує нестандартні методи:
// Встановити баланс адреси await provider.send("tenderly_setBalance", [ ["0xUserAddress"], "0x56BC75E2D63100000" // 100 ETH в hex ]); // Імперсонувати акаунт (підписувати від його імені) await provider.send("tenderly_addBalance", [ ["0xWhaleAddress"], "0xDE0B6B3A7640000" ]); // Встановити значення в storage напряму await provider.send("tenderly_setStorageAt", [ contractAddress, storageSlot, // keccak256 slot newValue ]); // Змінити timestamp await provider.send("evm_setNextBlockTimestamp", [futureTimestamp]); await provider.send("evm_mine", []); Прямий запис у storage — потужний інструмент для тестування: виставити paused = true в контракті без виклику pause(), симулювати що користувач уже вклав $1M, обійти cooldown period.
Інтеграція з Foundry
# Запуск тестів проти Tenderly Fork forge test --fork-url $TENDERLY_FORK_RPC --fork-block-number 19500000 -vvv У тестах Foundry можна використовувати vm.prank(whale) та vm.deal(attacker, 1000 ether) — вони працюють через Tenderly Fork так само як через anvil. Різниця: стан зберігається між запусками, якщо форк не перестворено.
Як симулювати складний сценарій атаки за допомогою Tenderly Fork?
Tenderly Simulate API дозволяє симулювати транзакцію та отримати детальний trace до відправки на mainnet:
const simulation = await fetch(`https://api.tenderly.co/api/v1/account/${account}/project/${project}/simulate`, { method: "POST", headers: { "X-Access-Key": apiKey }, body: JSON.stringify({ network_id: "1", from: senderAddress, to: contractAddress, input: calldata, gas: 500000, value: "0", save: true // зберегти для перегляду в dashboard }) }); Результат — повний call trace з газом на кожен виклик, storage changes, events. Це дешевше реального деплою на mainnet для налагодження складних сценаріїв. Ми гарантуємо, що симуляції будуть точними та відтворюваними.
Типові сценарії
Тестування апгрейду на mainnet-стані. Fork на блок перед апгрейдом, виконуємо upgrade транзакцію, перевіряємо що всі користувацькі позиції читаються коректно новою імплементацією.
Відтворення інциденту. Fork на блок до злому, відтворюємо вектор атаки. Знаходимо root cause. Патчимо. Перевіряємо що пропатчена версія стійка.
Демо для інвесторів. Створюємо Fork з потрібним початковим станом (користувачі, позиції, баланси), передаємо RPC URL. Інвестор взаємодіє з протоколом як з mainnet, але без реальних коштів.
Порівняння інструментів для форку
| Параметр | Tenderly Fork | anvil | Hardhat fork |
|---|---|---|---|
| Розміщення | Хмара | Локально | Локально |
| Доступність | Постійний RPC URL | Тільки локально | Тільки локально |
| Поширюване посилання | Так | Ні | Ні |
| Маніпуляція станом | REST API + JSON-RPC | JSON-RPC (вбудовані) | JSON-RPC (вбудовані) |
| Інтеграція з CI | Через API | Через скрипти | Через скрипти |
| Ціна (оплата за використання) | Є | Безкоштовно | Безкоштовно |
Етапи налаштування Tenderly Fork
| Етап | Тривалість | Результат |
|---|---|---|
| Створення форка та налаштування API | 1 день | Робочий RPC URL з потрібним станом |
| Інтеграція з CI/CD | 1 день | Автоматичне створення/видалення форків при тестах |
| Написання скриптів сценаріїв | 1-2 дні | Відтворювані тести атак та апгрейдів |
| Документація та навчання команди | 0.5 дня | Гайд з використання та API |
Що входить у налаштування Tenderly Fork?
- Створення форка з прив'язкою до блоку та потрібною мережею
- Налаштування JSON-RPC методів для маніпуляції станом (баланси, storage, час)
- Інтеграція з CI/CD для автоматичного створення та видалення форків
- Написання скриптів для відтворення тестових сценаріїв
- Документація з використання форка та API
- Підтримка протягом місяця після здачі
Приклад: відтворення злому через flash loan
1. Створюємо форк на блок за годину до атаки. 2. Встановлюємо баланс атакуючого: 1000 ETH. 3. Імперсонуємо контракт пулу ліквідності. 4. Викликаємо функцію `flashLoan` з довільними даними. 5. Перевіряємо, що баланс протоколу зменшився на суму атаки.Джерело: Tenderly Documentation
Отримайте консультацію з налаштування Tenderly Fork — наші інженери допоможуть підібрати оптимальну конфігурацію для вашого проекту.







