Solidity Playground
Пишите, запускайте и делитесь фрагментами кода — без установки.
Нажмите «Запустить», чтобы увидеть вывод здесь.
Попробуйте Solidity в браузере
Solidity — язык смарт-контрактов Ethereum. Он исполняется на EVM — той же виртуальной машине, которая защищает сотни миллиардов долларов в mainnet и питает большинство L2. Этот playground даёт вам Monaco-редактор, подключённый к sandbox-ной связке solc + geth EVM, так что вы можете написать контракт, нажать Run и увидеть в точности, что произошло бы on-chain: вывод console.log, emit-нутые события и конечное состояние ваших storage-переменных — без деплоя, без оплаты gas и без использования wallet.
У Solidity есть несколько особенностей, которые стоит держать в голове на старте. Storage по умолчанию постоянный — всё, что вы присваиваете state-переменной, сохраняется; всё, что находится внутри функции, исчезает, как только вызов возвращается. События — это то, как контракты разговаривают с внешним миром (вашим фронтендом, индексером, The Graph) — они стоят gas, пишутся в логи транзакции и фильтруются по indexed-параметрам. И каждая external-функция получает входные данные через ABI encoding, а не через stdin — поэтому playground даёт вам типизированную панель Args, которая напрямую подключается к параметрам вашего main(...).
Что этот Solidity playground умеет хорошо
- Настоящее исполнение solc + EVM, не симуляция через транспайлер. console.log идёт через forge-std, а пути emit / storage проходят настоящую семантику EVM — opcodes, gas, всё как есть.
- Вкладка Events показывает каждый
emitиз вашего запуска, сindexed-параметрами, помеченными отдельно, так что вы видите ровно то, что получил бы фронтенд или subgraph. - Вкладка Storage показывает конечное значение каждой state-переменной, к которой обращался контракт, — включая записи в mapping (например,
balances[0xabc...]). Переменные, в которые вы не писали, не появляются. - Типизированная панель Args передаёт значения в параметрический
main(uint256 n, string memory name, ...). Runner ABI-кодирует их по сигнатуре функции, так что42становитсяuint256, а"hello"—string.
Что можно построить в Solidity playground
- Счётчики / increment-decrement-контракты, чтобы прочувствовать, как state-переменные сохраняются между вызовами — запишите в
count, запустите и посмотрите, как значение появляется во вкладке Storage. - Паттерны передачи токенов — emit-ните
Transfer(from indexed, to indexed, value)и увидите, как indexed и не-indexed поля рендерятся по-разному во вкладке Events, ровно так же, как они выглядят в реальных log topics EVM. - Случаи провала с
require/revert— напишите guard, который падает на плохом входе, и увидите сообщение revert в stdout — вместо того чтобы сжечь gas на упавшей транзакции в mainnet.
Частые вопросы о Solidity
Что такое Solidity?
Нужен ли мне wallet или testnet ETH, чтобы это использовать?
main(...) с переданными args и показывает вам stdout, события и storage этого одного вызова. После Run всё выбрасывается.Как передать входные данные в контракт?
main(...) с теми типизированными параметрами, которые вам нужны — function main(uint256 n) external или function main(string memory name, uint256 age, bool active) external view. Затем впишите значения в панель Args под редактором. Runner смотрит на сигнатуру функции и ABI-кодирует ваши строки в нужные типы — точно так же, как это делает cast call в командной строке. Для address пишите 0x...; для bool — true или false; для uint — десятичное значение.В чём разница между вкладками Output, Events и Storage?
console.log(...) из forge-std/console.sol, плюс сообщение об ошибке revert / require, если оно было. Events показывает каждое событие, которое контракт emit-нул во время запуска, по порядку, со значением каждого параметра (и небольшой пометкой "indexed" для indexed-параметров — это те, которые попадают в log topics EVM и могут фильтроваться инструментами вроде The Graph). Storage показывает значение после запуска для каждой state-переменной, в которую была запись, включая отдельные записи mapping — переменные, к которым вы не обращались, в списке не появляются.Почему в некоторых туториалах по Solidity нет main()?
main() как соглашение, чтобы было очевидно, что запускать, и куда класть аргументы. Вне playground ваш контракт обычно выставляет несколько функций (mint, transfer, withdraw, ...), и ваш фронтенд или инструмент вроде cast / ethers / viem выбирает, какую вызвать.