# Remix - Ethereum IDE > Remix IDE documentation — develop, test and deploy Ethereum smart contracts. --- ## Introduction ### [Navigating Remix](https://remix-ide.readthedocs.io/en/latest/layout.html) > Learn how to navigate Remix IDE's layout: Top Bar, Icon Panel, Side Panel, Main Panel, Terminal, and Status Bar. # Navigating Remix Remix's layout consists of the following components: the Top Bar, Icon Panel, Side Panel, Main Panel, Terminal, and the Status Bar. ![Layout for Remix IDE, highlighting the terminal, topbar, and, the side, main, and icon panel.](images/layout/a-layout1c.png) - **Top Bar** - interface for workspace selection, GitHub authentication and associated tools, themes, and the settings panel. - **Icon Panel** - indicates which plugins have been activated and which plugin is currently in the left or Right Side Panel. Click an icon to select that plugin. Go to the Plugin Manager to activate other plugins. - **Left Side Panel** - interface for the File Explorer, Solidity Compiler, Git, Deploy & Run, and many other plugins. Visit the Plugin Manager for a full list of plugins. - **Right Side Panel** - interface for the RemixAI Assistant. - **Main Panel** - contains tabs for editing files, Main Panel plugins (plugins that require more space than Side Panel plugins), and the Home Tab. - **Terminal** - a panel for viewing transaction receipts, various logs, and for executing JavaScript scripts. ## Default tools When the Remix IDE is loaded for the first time - the Icon Panel shows these icons by default. ![Remix IDE default icons with annotations.](images/layout/a-icons-at-load.png) When you load more plugins, that icons automatically appear in the icon panel. To load more plugins go to the **[Plugin Manager](#plugin-manager)** and select a plugin from the list of available plugins. ## Home tab ![Remix IDE Hometab.](images/layout/a-hometab.png) The Home Tab is located in the Main Panel. It can be closed, just like any of the Main Panel tabs. You can also access it (even if closed) by clicking the Remix logo at the top of the icon panel. The home tab contains links to resources, announcements, tutorials, featured plugins and methods for loading files into Remix and shortcuts for connecting Remix to your local filesystem. ## Toggling components By default, Remix opens with the Left and Right Side Panels active. You can toggle the states of these components using the buttons on the Top Bar as shown in the image below. ![Remix toggle components](images/layout/toggle-buttons.png) ## Plugin manager In Remix, you only need to load the functionality you need - and the Plugin Manager is where you manage what plugins are turned off or on. The Plugin Manager is also the place you go when you are creating your own plugin and you want to load your local plugin into Remix. In that case, you'd click on the "Connect to a Local Plugin" link at the top of the Plugin Manager panel. ## Notifications Notifications on Remix are triggered when you perform certain actions like loading workspace dependencies. When triggered, they appear on upper right of the screen. ![Remix notifications](/images/layout/notifications.jpg) ### [Remix Desktop](https://remix-ide.readthedocs.io/en/latest/desktop.html) > Remix Desktop is a standalone app for macOS, Linux, and Windows with direct local filesystem access and all the features of Remix IDE. # Remix Desktop Remix Desktop is a standalone desktop application that provides the same features as Remix IDE, with direct access to the local filesystem. It is available for macOS, Linux, and Windows, and supports running multiple instances simultaneously. ## Why Remix Desktop? The web version of Remix is perfect for prototyping and learning, Remix Desktop is designed for local development workflows. With Remix Desktop, you can: - Work directly with local files and folders - Use Remix offline - Integrate smoothly with local tooling (Git, local nodes, scripts, native terminal) - Maintain the same familiar Remix UI and plugins - Access a local development blockchain - like Anvil ### Remix Desktop vs Remix online | Feature | Remix Online | Remix Desktop | | ----------------------- | ------------ | ------------- | | Local filesystem access | Limited | Full | | Offline support | No | Yes | | Installation required | No | Yes | | Plugin support | Yes | Yes | | User interface | Same | Same | | Git-friendly workflow | Partial | Full | ## Installing Remix Desktop Remix Desktop is available for macOS, Linux, and Windows. To install it for your operating system, visit the [Remix Desktop download page](https://remix.live/desktop) and choose the installer for your operating system. ![Remix Desktop releases page](images/desktop/releases.png) ### macOS Two builds are available on macOS: - The arm64 build for Apple Silicon Chips (M1, M2, ...): If your system matches this build, download the installer named `Remix-Desktop--arm64.dmg`. - The x64 build for Intel-based Macs: If your system matches this build, download the installer named `Remix-Desktop-.dmg`. ### Linux For most Linux distributions, Remix Desktop is provided as an AppImage. If you are on Linux download the file with `Remix-Desktop-.AppImage`. ### Windows On Windows, download the Remix Desktop installer (`.exe`) corresponding to your system architecture. ### Files you do not need to download Some files in the release list are not intended for manual installation: - `latest.yml`, `latest-mac.yml`, `latest-linux.yml`: These are update metadata files used by the auto-updater. You do not need to download this because Remix desktop prompts you to auto-update anytime there is a new update. - `Source code (zip)` and `Source code (tar.gz)`: These are intended for building Remix Desktop from source. There is no need to download them unless you intend to build the desktop app from source. ## Working offline with Remix Desktop Remix Desktop allows you to work offline with low or no internet connectivity. Most features work offline by default, but there are some plugins that require an internet connection. For example, you can't deploy to a public network without the internet. But you can download versions of Solidity Compilers before you go offline. To download a Solidity Compiler version, select it when you're online and Remix Desktop will automatically download it. Downloaded versions will remain available for offline use. ![Solidity Compiler with downloaded versions on Remix Desktop](images/desktop/desktop-compiler.png) The offline/online indicator on the Icon Bar tracks your network and notifies you when you're online/offline. ## Using Remix Desktop with other IDEs Remix Desktop accesses files directly from your file system allowing you to use your preferred IDE to write and edit code and use Remix for compiling, debugging, and testing. ## Using your native terminal in Remix Desktop You can access your system's native terminal inside Remix Desktop. You can open the native terminal from the app’s menu bar by selecting **Terminal**. ![Native Terminal Remix Desktop](/images/desktop/desktop-terminal.png) ## Using a browser wallet in Remix Desktop Remix Desktop does not include a "built-in wallet" but you can use a Browser Wallet. When you select **Injected Provider** (for example, MetaMask) in Remix Desktop, the connection is handled through your web browser: - Remix Desktop opens your default browser automatically - The browser navigates to a special local URL (for example, http://localhost:49589/) - MetaMask displays a connection request in the browser This local URL acts as a bridge between Remix Desktop and the browser wallet. As a result, even though you are working in Remix Desktop, wallet interactions (such as signing transactions) are still performed in your browser via MetaMask. ## Other wallet in Remix Desktop In addition to using a browser wallet, you can also use a node provider like Alchemy or Infura. You can also use WalletConnect. ## Hard drive security and performance Remix Desktop leverages the power of your local hard drive, allowing it to handle larger Solidity contracts and more complex Circom and Noir circuits. By running locally, Remix Desktop takes advantage of your machine’s storage and performance capabilities. ## Working with Hardhat and Foundry Going between Foundry or HardHat and Remix Desktop is seamless because all are running on your hard drive. Please see the {doc}`Working with HardHat or Foundry` page for more information including about using Remix Desktop for deploying a HardHat or Foundry compiled file. Similarly it is easy to use the {doc}`Debugger` in Remix Desktop to untangle Solidity problems in a HardHat or Foundry project. ### [Using Remix Safely](https://remix-ide.readthedocs.io/en/latest/security.html) > Security guidance for Remix IDE users: how to verify the Remix URL, avoid scams, use static analysis and contract verification, protect your code with a private LLM, and learn common Solidity vulnerabilities through hands-on tutorials. # Using Remix Safely Remix is widely used by developers at every level, from first-time smart contract writers to experienced auditors. That accessibility also makes it a target for scams and phishing. This page covers how to verify you are using the real Remix, how to develop safely, and which built-in tools can help you catch vulnerabilities before deployment. ## Verifying the Remix URL Remix is hosted on the [remix.live](https://remix.live) domain. The only valid Remix URLs are: - Stable: [app.remix.live](https://app.remix.live) - Alpha: [alpha.remix.live](https://alpha.remix.live) - Beta: [beta.remix.live](https://beta.remix.live) Remix used to be hosted at `remix.ethereum.org`. That address now redirects to [app.remix.live](https://app.remix.live), so landing on the new URL from an old link or bookmark is expected. Wherever you start from, the address bar should end up showing one of the three URLs above. If you are directed to some site that looks like Remix but has a **similar but different URL** - it is NOT Remix and is likely a phishing scam. Always check that you are loading Remix over `https` unless you have a specific reason for accessing it with `http` (e.g. for using Remix locally or for a connection you trust). Our only social profiles include: - X (formerly Twitter): [Remix on X](https://www.x.com/EthereumRemix) - LinkedIn: [Remix on LinkedIn](https://linkedin.com/company/ethereum-remix) ```{warning} Team members will never DM you on Discord claiming to be support, or ask for your private keys, or ask you to click shady links. Always use the #community channel to ask your questions. ``` ## Safe development practices - Make sure all your imports include the **version number** otherwise you don't know what version of files you are getting and the builds are not reproducible. So **do not** use an import like this: ```solidity import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; ``` Rather, **use one** like this: ```solidity import "@openzeppelin/contracts@5.0.0/token/ERC20/ERC20.sol"; ``` - When connecting a contract to an existing deployment, ensure that the thing you are connecting to is correct AND is the correct version. - Always be sure to address or understand every warning. - Never deploy or send transactions on contracts you don't fully understand, even if it's a get rich quick scheme that you've copied & pasted from a Discord DM or a YouTube video and you really really want to get rich. - If you have pasted code you are unsure about, ask the RemixAI Assistant to review it before deploying. Remix already prompts you to do this every time you paste code in the IDE. ## Scam awareness - Check our [article](https://medium.com/remix-ide/remix-in-youtube-crypto-scams-71c338da32d?source=friends_link&sk=bb6efbbf88bc3e496611943d282ad797) on a known scam promoting "liquidity front runner bots". **Scams lose their effectiveness when potential victims are educated about scams and about how to read and understand code. Learn Solidity and learn it well!** ### Solidity tutorials in Remix These interactive tutorials by WTF Academy are available in the LearnEth plugin. Each one walks through a real vulnerability class with hands-on exercises. ::::{grid} 3 :gutter: 3 :::{grid-item-card} Reentrancy Attack :columns: 12 6 4 4 :link-type: url :link: https://app.remix.live/?#activate=solidityUnitTesting,LearnEth&call=LearnEth//startTutorial//ethereum/remix-workshops//master//reentrancy-attack The classic Ethereum exploit. Learn how recursive external calls can drain contract balances. ::: :::{grid-item-card} Access Control :columns: 12 6 4 4 :link-type: url :link: https://app.remix.live/?#activate=solidityUnitTesting,LearnEth&call=LearnEth//startTutorial//ethereum/remix-workshops//master//access-control-exploit Identify missing or misconfigured access controls that expose privileged functions. ::: :::{grid-item-card} Integer Overflow :columns: 12 6 4 4 :link-type: url :link: https://app.remix.live/?#activate=solidityUnitTesting,LearnEth&call=LearnEth//startTutorial//ethereum/remix-workshops//master//integer-overflow Understand how arithmetic overflows can wrap values unexpectedly and how to prevent them. ::: :::{grid-item-card} tx.origin Phishing :columns: 12 6 4 4 :link-type: url :link: https://app.remix.live/?#activate=solidityUnitTesting,LearnEth&call=LearnEth//startTutorial//ethereum/remix-workshops//master//tx-origin-phishing-attack Understand why using `tx.origin` for authorization is dangerous and how attackers exploit it. ::: :::{grid-item-card} Front-Running :columns: 12 6 4 4 :link-type: url :link: https://app.remix.live/?#activate=solidityUnitTesting,LearnEth&call=LearnEth//startTutorial//ethereum/remix-workshops//master//front-running Learn how transaction ordering can be exploited by miners or bots to extract value. ::: :::{grid-item-card} Oracle Manipulation :columns: 12 6 4 4 :link-type: url :link: https://app.remix.live/?#activate=solidityUnitTesting,LearnEth&call=LearnEth//startTutorial//ethereum/remix-workshops//master//oracle-manipulation Understand how price oracles can be manipulated within a single transaction to exploit DeFi protocols. ::: :::: These are not exhaustive. LearnEth includes additional tutorials covering more vulnerability classes. Open the LearnEth plugin in the Plugin Manager to browse the full list. ## Static analysis Remix includes a Static Analysis plugin that runs security and quality checks on your Solidity code before deployment. It integrates three tools: - **Remix Analysis** — built-in checks that flag common issues such as reentrancy risks, unused variables, and dangerous low-level calls. - **Slither** — a widely-used Solidity static analyzer that detects a broad range of vulnerabilities. You can also prompt the RemixAI Assistant to run a Slither scan directly. - **Solhint** — a linter that enforces Solidity style and security best practices. See {doc}`Static Analysis ` for usage details. ## Contract verification Verifying a contract publishes its source code and makes it auditable by anyone. Remix integrates with [Sourcify](https://sourcify.dev) to make this as frictionless as possible: - A **verify on deployment** checkbox is enabled by default in the Deploy panel — verified source is submitted automatically when you deploy. - For contracts already on-chain, use the **Contract Verification plugin** to verify after the fact. See {doc}`Contract Verification ` for details. ## AI privacy When using the RemixAI Assistant, any code you share is sent to the configured LLM. If your code contains sensitive logic or proprietary algorithms, consider using a private LLM instead: - **Ollama** — run a local LLM entirely on your own machine, with no data leaving your environment. - **Cloud-hosted private LLM** — run Ollama in a private cloud instance for teams that need more compute. See {ref}`Running Ollama in the cloud with Remix ` and {ref}`Using a local LLM for privacy ` for setup instructions. ### [Tutorials in Remix](https://remix-ide.readthedocs.io/en/latest/remix_tutorials_learneth.html) > Learn Ethereum and Solidity development with interactive tutorials through the LearnEth plugin integrated in Remix IDE. # Tutorials in Remix You can do tutorials around blockchain development on Ethereum using the **LearnEth** plugin, a tutorial platform integrated into Remix. Some tutorials contain quizzes run by the Solidity Unit Tests plugin to test how much you learned from the tutorial. ![LearnEth Plugin](images/remix_tutorials/a-learneth.png) The tutorials contain `.md` files for instructions and can also contain example files, Solidity Unit Test files for quizzes, as well as answer files for quizzes and when you finish a tutorial, it will be marked "Completed". ## Using the LearnEth plugin To open LearnEth, you need to activate the LearnEth plugin in the Plugin Manager. Alternatively, you can activate it by clicking the link below which automatically opens the Remix IDE with LearnEth enabled. ```text https://app.remix.live/?#activate=udapp,solidity,LearnEth ``` ```{tip} For other tricks about Remix URLs with parameters, visit {doc}`locations. ` ``` When you open a LearnEth tutorial, the example files associated with it will be loaded into a new Workspace called "LearnEth Tutorials". ![LearnEth Layout](images/remix_tutorials/learneth-layout.png) ### Loading LearnEth with Other Repositories We have a growing set of tutorials on our default LearnEth content source. However, anyone can build tutorials on their own repositories load them in the LearnEth plugin and it would work as it if were our default content source. ![Import Repository into LearnEth](images/remix_tutorials/import-repo.gif) ```{important} Your repository must follow the LearnEth conventions to work on LearnEth. Learn how to [create your own LearnEth tutorials](https://remix-learneth-plugin.readthedocs.io/en/latest/index.html). ``` ### Useful LearnEth Links - LearnEth Plugin source code: [LearnEth Plugin repository](https://github.com/bunsenstraat/remix-learneth-plugin/) - Default LearnEth content source: [Remix Workshops repository](https://github.com/remix-project-org/remix-workshops) ### [Remix URLs & Links with Parameters](https://remix-ide.readthedocs.io/en/latest/locations.html) > Find Remix IDE URLs, deep links, and URL parameters for loading workspaces, files, and plugins directly. # Remix URLs & Links with Parameters ## Main Remix URLs - Remix IDE Online is located at [https://app.remix.live](https://app.remix.live). - The alpha version of Remix is located at [https://alpha.remix.live](https://alpha.remix.live). This is not a stable version. - GitHub repository: [https://github.com/remix-project-org](https://github.com/remix-project-org). The README contains instructions for running Remix-IDE locally. - Remix Desktop is an Electron App. Here is the [download page](https://remix.live/desktop). - The Remix X account is [EthereumRemix](https://x.com/EthereumRemix). - The Remix Project Blog for release notes and articles is: [https://ethereumremix.substack.com](https://ethereumremix.substack.com). - Remix blog used to be: [https://medium.com/remix-ide](https://medium.com/remix-ide). Older release notes are here. - The [Remix Project](https://remix.live) is our info site about the tool and the project. Remix is an open source project. Other projects have forked our codebase. The forked versions of Remix sites will look like Remix but are not Remix. So be careful! Forked sites are not maintained by us nor endorsed by us. ## Remix with URL parameters Using Remix with URL parameters will load the tool in the following ways: Remix URL parameters follow these conventions: - **`?#param=value`**: a query string (`?`) immediately followed by a hash fragment (`#`). `value` can be a plugin name, a comma-separated list of plugin names, a boolean (`true`/`false`), a theme name, a base64-encoded string, or a compiler version string. Used to activate or deactivate plugins, set a theme, minimize panels, load a base64-encoded file, and set a specific compiler build version. - **`#param=value`**: a hash fragment only, with no preceding query string. `value` can be a URL, an Ethereum address, a boolean, or a language name. Used to load a file via URL, load a verified contract from Etherscan, enable auto-compile, select the compiler language, and load a custom compiler from a URL. - **`?param=value`**: a plain query string with no hash fragment. `value` is a Gist ID. Used to load a GitHub Gist into the File Explorer. - **`//`**: a double slash delimiter used within `call` and `calls` values to separate a plugin's name, function, and arguments (e.g. `fileManager//open//contracts/3_Ballot.sol`). - **`///`**: a triple slash delimiter used within `calls` to separate multiple plugin API calls from one another. ### Plugin management #### Activate a list of plugins The following example contains the URL parameter **activate** followed by **a comma separated list of plugins**. ```text https://app.remix.live/?#activate=LearnEth,noir-compiler ``` **The last plugin in the list will gain the focus.** When you use the activate list, all other plugins that a user had loaded will be deactivated. This does not apply to the File Explorer, Solidity Compiler, Deploy & Run, the Plugin Manager, and the Settings modules. ```{note} In a Remix URL parameter, a plugin is referred to by its **name** as specified in its profile in the [Remix Plugins Directory repository](https://github.com/remix-project-org/remix-plugins-directory). To quickly get a plugin's name go to {doc}`Plugin List page ` of the docs and search for the plugin you want. There will be a link with the urls to activate the plugin. ``` To deactivate a list of plugins: ```text https://app.remix.live/?#deactivate=debugger ``` #### Pass commands to a plugin's API via a URL param The URL parameter to issue a command is `call`. Following the `call` is a // (double slash) separated list of arguments. ```text call=plugin_name//function//parameter1//parameter2 ``` The URL below uses `activate` & `call`. It **activates** a number of plugins and **calls** the File Explorer to tell it to load one of the default Remix files: ```text https://app.remix.live/?#activate=defiexplorer,solidity&call=fileManager//open//contracts/3_Ballot.sol ``` To load a specific tutorial in the LearnEth plugin: ```text https://app.remix.live/?#activate=solidityUnitTesting,solidity,LearnEth&call=LearnEth//startTutorial//ethereum/remix-workshops//master//proxycontract ``` #### Make calls to a number of different plugins' APIs Use `calls` instead of `call` when you need to issue commands to multiple plugins in sequence. Where `call` targets a single plugin, `calls` chains multiple commands together, each separated by `///`. For example, the URL below activates a list of plugins, then calls the LearnEth plugin's API and the File Explorer's API in sequence: ```text https://app.remix.live/?#activate=solidityUnitTesting,solidity,LearnEth&calls=LearnEth//startTutorial//ethereum/remix-workshops//master//proxycontract///fileManager//open//contracts/3_Ballot.sol ``` ### Loading content #### Load a file via a URL param into the Editor The `url` parameter takes a URL, loads it into the Editor and saves it in a Workspace called **code-sample**: ```text https://app.remix.live/#url=https://github.com/remix-project-org/remix-project/blob/master/apps/remix-ide/contracts/app/solidity/mode.sol ``` ```{important} The **code-sample** workspaces are ephemeral and will not be persisted on a reload. To save a loaded **code-sample** workspace, rename the workspace. ``` #### Load a Solidity file in the Editor via an encoded base64 string The `code` parameter takes a base64-encoded string of Solidity source code and loads it into the Editor as a `.sol` file, saving it in a Workspace called **code-sample**. To generate the base64 string, use `btoa()` in the browser console or any online base64 encoder. ```text https://app.remix.live/?#code=Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVAoKcHJhZ21hIHNvbGlkaXR5IDAuOC40OwoKLyoqCiAqIEB0aXRsZSBXb25kZXJmdWxDb2RlCiAqIEBkZXYgV2VsY29tZSB0byBSZW1peAogKi8KY29udHJhY3QgWW91IHsKCiAgICBhZGRyZXNzIHByaXZhdGUgb3duZXI7CiAgICAKICAgIC8qKgogICAgICogQGRldiBTZXQgY29udHJhY3QgZGVwbG95ZXIgYXMgeW91QW5kWW91cldvbmRlcmZ1bFNlbGYKICAgICAqLwogICAgY29uc3RydWN0b3IoKSB7CiAgICAgICAgeW91QW5kWW91cldvbmRlcmZ1bFNlbGYgPSBtc2cuc2VuZGVyOwoKICAgIH0KCiAgICAvKioKICAgICAqIEBkZXYgQ2hhbmdlIG1vb2QKICAgICAqIEBwYXJhbSBuZXdPd25lciBhZGRyZXNzIG9mIG5ldyBvd25lcgogICAgICovCiAgICBmdW5jdGlvbiBjaGFuZ2VNb29kKGFkZHJlc3MgbmV3TW9vZEFkZHIpIHB1YmxpYyB7CiAgICAgICAgb3duZXJNb29kID0gbmV3TW9vZEFkZHI7CiAgICB9Cn0= ``` #### Load contracts from Etherscan via address The `address` parameter takes an address and loads the **verified contract** found for the address on Ethereum mainnet and saves it into the `etherscan-code-sample` workspace of the File Explorer: ```text https://app.remix.live/#address=0xdac17f958d2ee523a2206206994597c13d831ec7 ``` #### Load a Solidity contract from GitHub With a GitHub URL of a Solidity contract like this one: ```text https://github.com/remix-project-org/remix-project/blob/master/apps/remix-ide/contracts/app/solidity/mode.sol ``` Then delete the **GitHub** part and type `app.remix.live` in its place, like this: ```text https://app.remix.live/ethereum/remix-project/blob/master/apps/remix-ide/contracts/app/solidity/mode.sol ``` Remix will fetch the Solidity file and open it up in the File Explorer in a Workspace named **code-sample**. #### Load a GIST The `gist` parameter fetches all files from a GitHub Gist and saves them into a workspace named `gist-` in the File Explorer. ```text https://app.remix.live/?gist=0fe90e825327ef313c88aedfe66ec142 ``` To also have the GIST visible in the Editor, use both `gist` & `call`: ```text https://app.remix.live/?#activate=solidity,fileManager&gist=0fe90e825327ef313c88aedfe66ec142&call=fileManager//open//gist-0fe90e825327ef313c88aedfe66ec142/gridMix4.sol ``` To load the GIST, have it visible in the Editor, and activate a list of plugins: ```text https://app.remix.live/?#activate=solidity,LearnEth&gist=0fe90e825327ef313c88aedfe66ec142&call=fileManager//open//gist-0fe90e825327ef313c88aedfe66ec142/gridMix4.sol ``` ### Compiler settings #### Load a specific version of the Solidity Compiler The `version` parameter pins the compiler to a specific build, which is useful for reproducibility or working with contracts that require a particular version. The version string follows the format `soljson-v+commit.`, where both the version number and commit hash are required. ```text https://app.remix.live/?#version=soljson-v0.6.6+commit.6c089d02 ``` ```{note} You need to specify both the Solidity version and the commit. ``` To load a custom compiler from a URL instead: ```text https://app.remix.live/#version=https://solidity-blog.s3.eu-central-1.amazonaws.com/data/08preview/soljson.js ``` To enable autoCompile: ```text https://app.remix.live/#autoCompile=true ``` #### Select the language for the Solidity Compiler The `language` parameter sets the compiler language. Valid values are `Solidity` (the default) and `Yul`. Yul is an intermediate language used for low-level EVM programming and compiler development. ```text https://app.remix.live/#language=Yul ``` ### UI / Appearance #### Minimize Remix panels The following URL will **close everything except the Main Panel & the icon panel** (the side and terminal are minimized). ```text https://app.remix.live/?#embed=true ``` To minimize just the Side Panel, use this URL: ```text https://app.remix.live/?#minimizesidepanel=true ``` To minimize just the terminal, use this URL: ```text https://app.remix.live/?#minimizeterminal=true ``` #### Specify a theme The `theme` parameter accepts `Dark` or `Light`. To link to Remix with a theme specified, use this URL: ```text https://app.remix.live/?#theme=Dark ``` ### Combine multiple parameters Multiple parameters can be combined in a single URL by chaining them with `&`. The example below uses the following parameters: - `activate=solidity,solidityUnitTesting,LearnEth` — activates three plugins; LearnEth gains the Side Panel focus as the last in the list - `theme=Light` — sets the Light theme - `minimizeterminal=true` — minimizes the terminal panel - `optimize=false` — disables compiler optimization - `evmVersion=null` — uses the default EVM version - `version=soljson-v0.6.6+commit.6c089d02.js` — loads a specific compiler version ```text https://app.remix.live/?#activate=solidity,solidityUnitTesting,LearnEth&theme=Light&minimizeterminal=true&optimize=false&evmVersion=null&version=soljson-v0.6.6+commit.6c089d02.js ``` ### [FAQ](https://remix-ide.readthedocs.io/en/latest/FAQ.html) > Frequently asked questions about Remix IDE: supported browsers, file storage, troubleshooting, and common issues. # FAQ ## Supported devices & browsers ```{dropdown} Q: What browsers will Remix work on? :class-title: sd-fs-5 sd-font-weight-bold :class-body: sd-fs-6 We support Firefox, Chrome, and Brave. We do not test or look for errors in Safari, Edge or other browsers. ``` ```{dropdown} Q: Will Remix work on a tablet or mobile device? :class-title: sd-fs-5 sd-font-weight-bold :class-body: sd-fs-6 We do not support the use of Remix on tablets or mobile phones. ``` ## General ```{dropdown} Q: Are there keyboard shortcuts in Remix? :class-title: sd-fs-5 sd-font-weight-bold :class-body: sd-fs-6 Yes - here is the list of keyboard shortcuts: `Ctrl+S`: Compiles the active Solidity file `Ctrl+Shift+S`: Compiles a Solidity file and runs a script when the script is displayed in the editor.
(go {ref}`here ` for more info about this functionality) `Ctrl+Shift+F` : Opens the File Explorer `CTRL+Alt+F` : Formats the code in the current file `Ctrl+Shift+A` : Opens the Plugin Manager ``` ## Solidity compiler ```{dropdown} Q: Error: compiler might be in a non-sane state :class-title: sd-fs-5 sd-font-weight-bold :class-body: sd-fs-6 ~~~text error: "Uncaught JavaScript exception: RangeError: Maximum call stack size exceeded. The compiler might be in a non-sane state, please be careful and do not use further compilation data to deploy to mainnet. It is heavily recommended to use another browser not affected by this issue (Firefox is known to not be affected)." ~~~ Old versions of Solidity Compiler had this problem with Chrome. Please change the compiler version in Solidity Plugin to the newer one or use another browser. ``` ```{dropdown} Q: I’m getting an issue with Maximum call stack exceed and various other errors, can't compile. :class-title: sd-fs-5 sd-font-weight-bold :class-body: sd-fs-6 Try a different browser or a newer Solidity Compiler version. ``` ## Deploy & run ```{dropdown} Q: I am using an Infura endpoint in my app, but when I try to deploy against that endpoint in Remix IDE selecting "External HTTP Provider" and putting my endpoint in, it's telling me that it can't connect :class-title: sd-fs-5 sd-font-weight-bold :class-body: sd-fs-6 If the endpoint you are using is http, it won't work. ``` ```{dropdown} Q: Where is deploy button? :class-title: sd-fs-5 sd-font-weight-bold :class-body: sd-fs-6 It's in the Deploy & Run Transactions module. ``` ```{dropdown} Q: How to pass a tuple to a public function in Remix? :class-title: sd-fs-5 sd-font-weight-bold :class-body: sd-fs-6 Pass it as an array `[]`. ``` ```{dropdown} Q: How to input a struct as input to a parameter of a function in the Deploy & Run module? :class-title: sd-fs-5 sd-font-weight-bold :class-body: sd-fs-6 For inputting a struct, just like a tuple, pass it in as an array `[]`. Also you need to put in the line: `pragma experimental ABIEncoderV2;` at the top of the solidity file. For example, here's a solidity file with a struct as an input parameter. ~~~solidity pragma solidity >=0.4.22 <0.6.0; pragma experimental ABIEncoderV2; contract daPeeps { struct Peep {uint a; uint b;} // declaration of Peep type Peep peep; //declaration of an object of Peep type constructor () public { peep.a = 0; // definition/initialisation of object peep.b = 0; // } function initPeepToPeep(Peep memory i) public payable { peep.a = i.a; peep.b = i.b; } function setPeep(uint a, uint b) public payable { peep.a = a; peep.b = b; } function getPeep() public view returns(Peep memory) { return peep; } } ~~~ The input of initPeepToPeeps takes a struct. If you input `[1,2]` the transaction will go through. ``` ```{dropdown} Q: What should I do if the addresses don't load in the VM? :class-title: sd-fs-5 sd-font-weight-bold :class-body: sd-fs-6 **A:** Try deleting the state folder to refresh the local VM. Note that this resets the local VM, any deployed contracts and account state in the VM will be lost. ``` ## Plugin developers ```{dropdown} Q: Where do plugin developers go with their questions? :class-title: sd-fs-5 sd-font-weight-bold :class-body: sd-fs-6 First, join our [Discord server](https://discord.com/invite/qhpCQGWkmf) and then go to the development-plugin channel. ``` ## Analytics ```{dropdown} Q: What information does Remix save when Matomo Analytics is enabled? :class-title: sd-fs-5 sd-font-weight-bold :class-body: sd-fs-6 We want to know: - Which plugins get activated & deactivated - If users check the box to publish a contract's metadata when deploying - Which themes are used/used most/not used at all - The usage of the links to documentation - On the homepage, which file importing buttons are used ``` ```{dropdown} Q: Is it opt-in or opt-out? :class-title: sd-fs-5 sd-font-weight-bold :class-body: sd-fs-6 We use Matomo as an opt-in analytics platform. ``` ```{dropdown} Q: Where is the info stored? Is the info shared with 3rd parties? :class-title: sd-fs-5 sd-font-weight-bold :class-body: sd-fs-6 All data collected through Matomo is stored on our server. No data is given to third parties. We respect your privacy and do not collect nor store any personally identifiable information (PII). ``` ```{dropdown} Q: What does Remix do with this info? :class-title: sd-fs-5 sd-font-weight-bold :class-body: sd-fs-6 Our goal is to understand how many users we have, what plugins people are using, what is not getting used, what is not being used to its full potential. With this understanding, we can make adjustments to the UI as well as providing more tips and documentation. It's a way of getting constant anonymous feedback from our users. ``` ```{dropdown} Q: After I agree opt-in, can I change my mind? :class-title: sd-fs-5 sd-font-weight-bold :class-body: sd-fs-6 You can turn off or on Matomo in the Settings panel. There are no consequences for not opting-in or opting-out. ``` --- ## Core Modules ### [File Explorer](https://remix-ide.readthedocs.io/en/latest/file_explorer.html) > Manage your smart contract files in Remix IDE using the File Explorer — create, rename, delete, and organize files and folders. # File Explorer The File Explorer is the plugin responsible for managing files. It includes a pop-up menu that is activated when you right-click on a file. ![Remix Side Panel showing the File Explorer and the Icon Panel highlighting the File Explorer icon.](images/file-explorer/a-file-explorer1a.png){.fig--landscape} The green shield icon at the top of the File Explorer page on the Sidebar indicates that the plugin is maintained by Remix Team. When you click the caret next to the icon, the Sidebar will display details about the plugin, including a link to its documentation page. ![Remix Team shield icon and caret.](images/file-explorer/a-fe-top-caret.png){.fig--landscape} ## File storage By default, Remix IDE stores files in **IndexedDB**, a database built into the browser. Your data is only stored locally in your browser and not on an external server. Browser storage is ephemeral and browser crashes might lead to complete loss of data Thus, it is important to have an alternative file backup/saving strategy. **Some recommended strategies include:** - [Enabling Cloud storage](#cloud-storage) - [Using Remix Desktop](#remix-desktop) - Using [remote Git repositories](#connecting-remix-to-remote-git-repositories) ### Cloud storage ```{note} Cloud storage is currently only available to users in our beta program. ``` Enabling cloud storage on Remix web saves your work to your Remix account, auto-syncing every change so nothing is lost to browser crashes. Your files are available on any device when you are logged in. Snapshots of your workspace are taken automatically as you work. Each snapshot captures the workspace state at a single point in time and is not a complete backup; it may be seconds to minutes behind your actual files. Each snapshot is kept for 7 days before being removed. You can download all snapshots currently within that window as a single zip file to inspect locally. To enable cloud storage, click the switch at the top left of the Top Bar as shown in the image below. ![Cloud storage toggle switch highlighted in the Remix Top Bar.](images/file-explorer/cloud-storage.png) When you enable cloud storage, the files saved on your browser do not get moved to cloud automatically. If you want to migrate the files saved to your browser storage to cloud, click the Workspaces dropdown, and click "migrate local workspaces to cloud". ![Open Workspaces dropdown with the migrate local workspaces to cloud option highlighted.](images/file-explorer/move-local-to-cloud.png) You will see a list of all the workspaces in your browser storage, choose the ones you want to migrate and click the "Migrate" button. ![Migrate Workspaces to Cloud dialog listing browser workspaces to select.](images/file-explorer/migrate-workspaces.png) ### Remix Desktop Remix Desktop is a version of the Remix IDE that exists as a native app on your computer instead of a browser app. Since it's a native app on your computer, the files are saved directly to your hard drive. You can download Remix Desktop on [the download page](https://remix.live/desktop). ```{tip} For more information, see the {doc}`Remix Desktop ` documentation. ``` ### Connecting Remix to remote Git repositories Remix IDE supports version control with version control platforms like GitHub (or similar like GitLab) and in the InterPlanetary File System (IPFS), allowing you to store the code you write on remote repositories. The version control operations are managed with Git through the **Git** plugin. Additionally, you can manage your branches on the Remix IDE using the branch icon that appears at the bottom of the File Explorer after you initialize Git. ![Remix IDE Git branches.](images/file-explorer/git-branches.png) Also see this article about [securing your files in Remix](https://medium.com/remix-ide/securing-you-file-in-remix-how-to-clone-and-push-f1350111aa13?source=friends_link&sk=a3dbd0d3b0b44a29a28e8c10f8821fde). ### Publishing to a GitHub gist In addition to these methods, you can also publish your files to a GitHub Gist. This method just takes a snapshot of your project's current state and publishes it to a GitHub gist. Any changes made after publishing it will not update the published Gist. To use this feature, you need to add a GitHub access token with the "**Create Gist**" permission enabled to Remix because the Gist API requires users to be authenticated to be able to publish a gist. To generate a GitHub token, visit the [GitHub Settings page](https://github.com/settings/tokens) and select "**Generate new token**". Ensure you tick the **Create gists** checkbox and generate a new token. Copy the token and paste it in Remix's **Settings** module in the **GitHub Access Token** section. And then click "**Save**". After the initial setup, you can publish a gist by right-clicking on a file (publish the file), folder (publish the folder), or Side Bar (publish the entire workspace) and selecting the "**Publish folder to gist**". ```{tip} You can publish multiple files by select all of them and right-clicking. The resulting pop-up menu will provide an option to publish them to a gist. ``` ## Creating new files There are two ways you can create files on the Remix IDE. The first way involves clicking the **"Create"** dropdown, selecting the **"New file"** option, and entering the name of the file on the input field that appears. ![Remix File Explorer highlighting the create new file icon.](images/file-explorer/a-file-explorer-new-file2.png){.fig--landscape} Another way you can create files in Remix is by right-clicking on the Side Bar (creates the file at the root of your project) or right-clicking on a folder in the Side Bar (creates the file in the folder you clicked) and selecting "**New File**" from the dropdown options. ![Remix IDE File Explorer dropdown.](images/file-explorer/file-explorer-dropdown.png) ```{note} Note that (regardless of the method) when you save a file without providing a file extension, it defaults to the `.sol` extension. ``` ## Right-click popup menu ### Right-Click on a folder Right-clicking on a folder will bring a popup menu for operations you can do on that folder. ![Remix File Explorer extra options.](images/file-explorer/a-fe-rtclick-file.png){.fig--landscape} ### Right-Click on a Solidity file Right-clicking on a file with a .sol extension will bring up a popup menu - which includes options for compiling & flattening, creating UML diagrams, and generating documentation. ![File Explorer right click on .sol file](images/file-explorer/a-fe-rtclick-sol-file.png) ### Right-Click on a Script ![File Explorer right click on script file](images/file-explorer/a-fe-rtclick-script.png) Right-click on any file with a `.js` or `.ts` extension to get the **Run** option in the popup menu to run the script. If the script you want to run is the active file in the Editor, you can also run it by using play button at the top left of the Editor or by inputting the command `remix.exeCurrent()` in the console. ### [Remix Workspaces](https://remix-ide.readthedocs.io/en/latest/workspaces.html) > Remix Workspaces let you separate and manage multiple projects in Remix IDE. Learn how to create, switch, clone, and share workspaces. # Remix Workspaces Workspaces in Remix are special folders that separate projects. Files in one workspace cannot import or access files in different workspace. You can select a workspace from the **Workspaces** dropdown on the Top Bar. ![Remix IDE Workspaces highlighting the dropdown.](images/workspaces/a-fe-workspaces1.png) ## Creating a new Workspace You can create a new workspace by clicking the Workspaces dropdown and click the "**Create a new workspace**" button. ![Workspaces dropdown highlighting the Create new workspace button](images/workspaces/a-fe-workspaces-new.png) When you click the button, Remix takes you to the Workspace Templates page, where you can create a blank workspace or a workspace from a list of available templates. The available templates include but are not limited to the following: - Remix Generic templates - OpenZeppelin contract wizard (ERC20, ERC721, ERC1155) - Cookbook.dev templates - Gnosis Safe MultiSig template - Zero-Knowledge Proof (ZKP) templates (Circom, Noir, and Generic) - Uniswap v4 templates - Solidity CREATE2 templates - Etherscan scripts for verifying contracts - CI scripts for unit tests and security analysis When you click the "**Create**" the button, a modal with customization options will popup. The options differ depending on the template you choose. For example, when you create a Workspace with an OpenZeppelin contract wizard, you can add customize the features of the contract you create. The image below shows the options available for customizing an OpenZeppelin ERC721 contract template. ![OpenZeppelin ERC721 contract template.](images/workspaces/a-fe-modal-oz.png) For other templates, the modal only contains a textbox for editing the Workspace name and an option to initialize it with Git. ![Create Workspace with template modal](images/workspaces/create-workspace-with-template-modal.png) ```{tip} You can describe the workspace you want to create to the RemixAI and it will generate it for you. See the {doc}`RemixAI docs ` to learn more. ``` ### Initializing a Workspace with Git To initialize a new Workspace for Git, check the box at the bottom of the Create Workspace modal. ![Create Workspace with template modal with Initialize Workspace with Git highlighted.](images/workspaces/a-fe-create-ws-modal.png) Git initialized workspaces will have the Git icon next to them in the **Workspaces** selectbox. ![Workspaces initialized with Git](images/workspaces/a-fe-select-git.png) ## Workspace configuration Each Workspace contains a configuration file named `remix.config.json` that keeps track of script dependencies and compiler configurations. The file is located at your the root of each workspace. When you want a new Workspace to have the same configuration as an existing one, copy the `remix.config.json` file from the existing Workspace to the new one. ### [AI Tools](https://remix-ide.readthedocs.io/en/latest/ai.html) > RemixAI is Remix IDE's built-in AI assistant and Copilot for Solidity smart contract development, code completion, and explanation. AI Tools ======== .. meta:: :description: RemixAI is Remix IDE's built-in AI assistant and Copilot for Solidity smart contract development, code completion, and explanation. :keywords: remixai, ai assistant, code completion, solidity ai, remix ide ai Remix has its own AI tool named **RemixAI Assistant**, which appears in the Right Side Panel once you log into your Remix account. Access to RemixAI varies by your Remix plan: - **Free Plan**: This provides access to Basic AI Skills and the QuickDApp Front-end Generator (excluding hosting), with AI model consumption billed on usage-based pricing. - **Starter & Pro Plans**: Subscribing to our `Starter or Pro plans `_ unlocks more AI capabilities and includes an initial gift of RemixAI credits. Users of all levels can either buy credits or can `connect their own API keys from supported providers `_ to utilize tokens from their personal accounts rather than Remix credits. .. image:: images/ai/remix-ai-panel.png :alt: RemixAI Assistant Right Side Panel RemixAI is also integrated into other parts of the IDE including: - `The Code Helper `_ - `Gas optimization audits `_ - `Security audits `_ - `The Explain contract button `_ - The **Explain compiler error** button when an error is thrown in the Solidity Compiler. - **Right-click menu options** in the Editor. - **Code requests in the Editor** by prepending an AI code request in a file with a double slash (``//``). The RemixAI Assistant retains your conversation history within a session, so you can refer back to earlier responses or continue a previous request. .. note:: The chat history is stored in your browser's storage, thus, you will not be able to access it when you log in to your Remix account on another device. Choosing an LLM for code explanations ------------------------------------- In the RemixAI Assistant, there is a choice of LLMs for use in **code explanations** and in the AI Assistant. The default LLM is **Mistral Medium**. Click the MistralAI button and a modal will pop up where you can select models from **Anthropic**, **OpenAI**, **Mistral**, **Local Models (Ollama)**, and Open Weight models. .. image:: images/ai/available-models.png :alt: RemixAI LLM dropdown menu The RemixAI Assistant responds in the language in which it is asked and can answer questions about Solidity, JavaScript/TypeScript, Vyper, and other programming languages. Using a local LLM for privacy ----------------------------- When using an LLM, unless the model is running locally, your inputs may be used by the provider for training or retention. This means the information you submit could be stored or reused. If you want to use AI tools while keeping your information private, you can use a **local LLM**. Remix supports **Ollama**, a local AI model runner that allows you to download and run large language models (LLMs) directly on your own machine. The Ollama LLMs supported by Remix include: - ``codestral:latest`` - ``qwen3-coder:latest`` - ``gpt-oss:latest`` - ``deepseek-coder-v2:latest`` (recommended for code completion) - ``codegemma:7b`` - ``codegemma:2b`` (lightweight option) In addition to privacy, Remix’s Ollama integration provides: - **No API rate throttling** – no usage fees or rate limits - **Offline capability** – works without an internet connection - **Fill-in-the-Middle (FIM) support** – advanced code completion features .. note:: The Ollama integration does not support agentic workflows available in the online RemixAI service, such as Remix MCP or generating and editing Workspaces. Its capabilities are limited to code completion and conversational interactions. Setting up Ollama in Remix ^^^^^^^^^^^^^^^^^^^^^^^^^^ Before using Ollama with Remix, ensure the following requirements are met: - **Ollama is installed** on your system. Visit the `Ollama website `_ to download and install it. - **At least one supported or recommended model** is installed locally. After completing the setup, start the Ollama server by running: .. code-block:: shell ollama serve By default, the Ollama service listens on: :: http://localhost:11434 You can confirm that Ollama is running by visiting the URL above. If it is running, you should see the message below. .. image:: images/ai/ollama-running.png :alt: Ollama is running text in browser. Next, to allow the Remix IDE to communicate with your local Ollama instance, you must configure **CORS**. See `how to setup CORS for Ollama `_ for instructions specific to your operating system. .. important:: Once configured, restart the Ollama service and your terminal instance to apply the changes. You can check if Remix is on your Ollama allowlist by running the command below: .. code-block:: shell curl -X OPTIONS http://localhost:11434 \ -H "Origin: https://app.remix.live" \ -H "Access-Control-Request-Method: GET" \ -I If "app.remix.live" is configured properly, you will get the message below: .. code-block:: shell HTTP/1.1 204 No Content Access-Control-Allow-Headers: Authorization, Content-Type, User-Agent, Accept, X-Requested-With, Openai-Beta, X-Stainless-Arch, X-Stainless-Async, X-Stainless-Custom-Poll-Interval, X-Stainless-Helper-Method, X-Stainless-Lang, X-Stainless-Os, X-Stainless-Package-Version, X-Stainless-Poll-Helper, X-Stainless-Retry-Count, X-Stainless-Runtime, X-Stainless-Runtime-Version, X-Stainless-Timeout Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS Access-Control-Allow-Origin: https://app.remix.live Access-Control-Max-Age: 43200 Allow: HEAD, GET Vary: Origin Vary: Access-Control-Request-Method Vary: Access-Control-Request-Headers Date: Sun, 11 Jan 2026 23:52:32 GMT .. tip:: If you run into any issues check out our `Ollama troubleshooting guide `_. After the setup, select Ollama as the model on RemixAI and it will automatically detect the supported models you have on your device. You can select your preferred model and use it for code completion and assistance. .. image:: images/ai/ollama-remix.png :alt: RemixAI assistant with Ollama as the model Running Ollama in the cloud with Remix -------------------------------------- Large language models (LLMs) are resource-intensive and may not run efficiently on all local machines. If system resources or disk space are a concern, you can run a private LLM on another machine or in the cloud and configure Ollama to connect to it remotely. Remix supports this by allowing you to specify the Ollama server URL. Follow the steps below to configure a remote Ollama instance in Remix: 1. Click the **gear icon** in the top-right corner of Remix to open the **Settings** panel. 2. Navigate to the **RemixAI Assistant** section. 3. Under **Ollama URL Configuration**, enter the URL of the machine running Ollama. .. image:: images/ai/ollama-cloud.png :alt: Remix settings showing the Ollama config Adding AI Skills to RemixAI --------------------------- **Skills** are collections of instructions and reference material that give RemixAI deeper, more specialized knowledge for a particular domain. Remix provides a library of built-in Skills covering verticals such as **Wallets**, **L2s**, **DeFi**, and **Security**, so you can equip the Assistant with focused expertise for the task at hand. You can also upload your own Skills to extend RemixAI with your own instructions and knowledge. To open the Skills modal, type ``/load-skills`` in the RemixAI Assistant chat. From there you can browse and enable the built-in Skills or upload your own. Enabled Skills are loaded into a ``skills`` folder in your workspace, and RemixAI references them for the rest of the conversation. .. image:: images/ai/skills.png :alt: RemixAI Skills library modal .. _code helper: RemixAI Code Helper (Pro & Starter plans) ----------------------------------------- The code helper provides instant code reviews focused on security and gas optimization. To activate the code helper, highlight a piece of code or a function and you will get an instant review. .. image:: images/ai/code-helper.jpg :alt: RemixAI Code Helper analysis popup From the code helper pop up you can ask RemixAI to analyze the entire file instead of that part or open of that part in RemixAI to ask follow up questions about it. .. _gas optimization audits: Gas optimization with RemixAI (Pro & Starter plans) --------------------------------------------------- On Ethereum and other EVM chains, every computation and storage operation your contract performs costs gas, which your users pay for in real money each time they call it. RemixAI supports **Gas optimization audits** to help you find and fix inefficiencies that inflate these costs before you deploy. To start one, enter ``/start-gas-optimization-audit`` in the prompt box, or click the **Tools** pill. RemixAI will ask which contract you want to optimize, then list the focus areas it will check, including: - **Loop optimization** – e.g. ``for`` loops over arrays or mappings - **Storage vs. memory** – e.g. unnecessary storage reads or writes - **Function visibility** – e.g. ``public`` vs. ``external``/``internal`` - **Data packing** – e.g. how structs and variables are packed into storage slots - **Avoiding redundant computations** – e.g. caching values instead of recomputing them This checklist is derived from the `RareSkills Book of Gas Optimization `_. .. warning:: Some of these optimizations change how your contract behaves, not just what it costs, and the compiler won't stop you. Reordering fields breaks storage layout on a proxy upgrade; caching a value that later changes gives a stale read. Re-run Slither and the Cyfrin Audit checklist before deploying, and if you're upgrading, verify storage-layout compatibility separately (Slither won't catch a layout collision on its own). .. _security audits: Security audits with RemixAI ----------------------------- Unlike a regular application, a smart contract can't be patched after it's deployed, so a vulnerability that slips through can mean an irreversible loss of funds. RemixAI can audit your contracts with a **Slither** scan, and you can also select from over 47 **security checklists**, sourced from the Cyfrin Audit Checklists repo, covering a wide range of attack categories, all from within Remix. Auditing with checklists means you know exactly which vulnerabilities RemixAI is checking for, rather than relying on Slither's static analysis alone. Start an audit by opening the **AI Assistant** and typing ``/audit``, or by clicking the **Tools** pill. By default, this runs a Slither scan against your contract. To go beyond the default Slither scan, load one or more checklists before you start the audit: 1. Type ``/load-security-audit-checklist`` into the prompt box, or click the **Tools** pill. 2. Select the checklists that are closely related to your contract. A checklist you've already loaded shows an **in workspace** badge. .. image:: images/ai/audit-checklist.png :alt: RemixAI security audit checklist modal When you then start the audit with ``/audit``, the Checklist Modal opens again. If you've already selected the checklists you want, hit the **X** button to close it and continue with your existing selection. RemixAI will then ask which contract you want to audit. It runs a Slither scan together with a security audit based on the checklists you selected, and saves the result to the ``audit_report`` folder. The checklists themselves are stored in the workspace's ``audit`` folder. .. important:: Loading too many checklists at once can make your audits take a long time to run and use a lot of AI resources. You can access security audits, gas optimization, AI skills, and other AI features from the pills above the AI Assistant, shown in the image below: .. image:: images/ai/pills.png :alt: RemixAI pills .. _provide your own API key: Using external API keys for RemixAI (Pro & Starter plans) --------------------------------------------------------- RemixAI allows you to add your own API keys and use your own available tokens. To add your own API keys, click the **Settings** icon on the top right of the Top Bar, select RemixAI Assistant, and scroll to the bottom. You will find the option under the "Bring Your Own Keys" Section. Currently, we support keys from Anthropic, OpenAI, Mistral, and Moonshot/Kimi. .. image:: images/ai/external-providers.png :alt: RemixAI Assistant Bring Your Own API Keys settings Model Context Protocol (MCP) ----------------------------- Remix supports **Model Context Protocol (MCP)** servers, which give the RemixAI access to external tools and libraries during agentic workflows. You can manage the MCP servers available to you in **Settings > RemixAI Assistant**. Here you can turn the available servers on and off, depending on your preferences. .. image:: images/ai/connected-mcps.png :alt: Remix MCP Connected Services panel The following MCP servers are available in RemixAI: - **Remix IDE Server** (Built-in) – Always connected. Gives the AI direct access to your workspace files and IDE features such as compilation, file management, and Slither static analysis. - **OpenZeppelin Contracts** – Gives the AI access to OpenZeppelin's audited contract library, so it can suggest secure, battle-tested implementations rather than generating patterns from scratch. - **Web Search** – Allows the AI to retrieve up-to-date information such as recent protocol changes, audit reports, and external documentation. - **ethSkills** – A curated Ethereum knowledge base designed specifically for AI agents. It covers production-ready guidance across gas costs, L2s, token standards, DeFi protocols, security patterns, contract auditing, and more, helping the AI avoid stale or hallucinated answers about Ethereum development. - **Alchemy** – Allows the AI to query live on-chain data including account balances, transaction histories, and contract state via Alchemy's infrastructure. - **Etherscan** – Allows the AI to look up deployed contracts, inspect verified source code, and retrieve transaction data directly from the block explorer. - **The Graph API** – Allows the AI to query indexed blockchain data via GraphQL subgraphs, useful for retrieving protocol analytics and historical event data. Sample prompts ^^^^^^^^^^^^^^ The examples below show how to phrase requests to get the most out of the RemixAI Assistant. Each section explains the intent behind the prompt type and gives one example. **Writing contracts** Ask RemixAI to generate a contract from a plain-language description. Be specific about the behaviour you want (access control, token standards, limits) and the AI will produce a starting implementation you can refine. *Write an ERC-20 token contract with a mint function restricted to the owner and a maximum supply of 1 million tokens.* **Security review** Ask RemixAI to analyse a specific contract or the active file for vulnerabilities. You can target a particular class of issue or ask for a general review. Slither static analysis is built into the Remix IDE Server, so the AI can run it and incorporate the results without any additional setup. *Review the active contract for reentrancy vulnerabilities and suggest fixes.* **Using OpenZeppelin** *(OpenZeppelin MCP)* Ask RemixAI to suggest or apply an OpenZeppelin implementation instead of writing custom logic. The AI has access to the full OpenZeppelin library and can recommend the right base contract for your use case. *Replace the access control in this contract with OpenZeppelin's Ownable.* **Querying live on-chain data** *(Alchemy / Etherscan)* Ask RemixAI to look up real-time blockchain data such as balances, transactions, or verified source code. Useful for investigating a deployed contract or checking an address without leaving the IDE. *Fetch the verified source code and recent transactions for this contract address: 0x...* **Querying indexed protocol data** *(The Graph)* Ask RemixAI to query a subgraph for aggregated or historical data. Useful for retrieving protocol-level metrics or event histories that are not available from a single contract call. *Get the total value locked in Aave on Ethereum over the last 7 days using a subgraph query.* **General Solidity and Ethereum questions** Ask RemixAI about language features, best practices, or protocol mechanics. The Web Search MCP server allows it to retrieve up-to-date information, so it can answer questions about recent changes that postdate its training data. *What changed in Solidity 0.8.24 that could affect a contract I wrote for 0.8.20?* Code completion --------------- When you type a space or start a new line, the RemixAI Assistant may propose code suggestions. This feature is known as **code completion**. The suggestions take into account what has already been written in the file. The toggle to enable code completion is located at the bottom-left of the Main Panel when a file is active. Once enabled, code completion uses the **MistralAI** LLM by default. If Ollama is configured as the active model, code completion will use the selected Ollama model instead. .. image:: images/ai/copilot-switch.png :alt: Remix AI Copilot button As you type, RemixAI proposes a suggestion inline. .. image:: images/ai/a-ai-completion-proposal.png :alt: RemixAI completion proposal Press ``Tab`` to accept the suggestion. .. image:: images/ai/a-ai-completion-accepted.png :alt: RemixAI accepted completion .. note:: All other RemixAI tools are always enabled. .. _explain contract: Editor: Explain Contract ------------------------- At the bottom of the Editor, when a ``.sol`` file is active, there is an **Explain contract** button. Click the button to send the active contract to RemixAI. The Assistant will explain what the contract does. Editor: Right-click Menu ------------------------ When you right-click a function in the Editor, a popup menu appears with options powered by RemixAI, including: - **Explain this function** - **Explain this code** - **Generate documentation** .. image:: images/ai/a-ai-editor-popup-menu.png :alt: Remix AI right click menu The **Explain this code** option can be triggered with or without selecting code. If no code is selected, RemixAI considers the code surrounding the cursor. Ask RemixAI with // --------------------------- With the AI Copilot enabled, start a comment with ``//`` to send a code request directly from the Editor. Example: :: // write a function that returns an array with 3 elements from the function's parameters Compilers: Explain Error ------------------------ In the error cards of both the Solidity Compiler and the Vyper Compiler, there is an **Ask RemixAI** button that helps explain compiler errors. Click the button to send the error message to RemixAI. The Assistant will explain the cause of the error and suggest how to fix it. .. image:: images/ai/a-ai-solcomp1.png :alt: Compiler Explain Error ### [Working with Git in Remix](https://remix-ide.readthedocs.io/en/latest/git.html) > Use Git version control in Remix IDE to initialize repositories, connect to GitHub, and manage branches, commits, and pull requests. # Working with Git in Remix In Remix, you can initialize Git for version control in your workspaces. ## Connecting to GitHub Before you can use Git in any of your workspaces, you have to login with GitHub using the "**Login with GitHub**" button on the Top Bar. ![Remix Top Bar showing login with GitHub button.](images/git/login-with-github.png) Alternatively, you can add username and email to the GitHub section of the Git plugin. You can find the Git plugin on the Icon Panel represented by a branch icon. ![Git plugin settings.](images/git/gh-login-manually.png) ## Git operations in Remix ### Initializing Git in a Workspace For information about initializing a workspace, see the section about initializing Git on the {ref}`Remix Workspaces ` page. ### Cloning an existing repository into Remix You can clone an existing repository from GitHub into Remix using "**CLONE**" accordion item in the Git plugin. You can clone a repository by loading it from GitHub using the "**Load from GitHub**" button and selecting one from your list of public repositories. Alternatively, you can clone a repository by providing its URL in the "**CLONE FROM URL**" text box. When you clone a repository, Remix initializes it as a separate Workspace. See {doc}`Remix Workspaces ` to learn more about Workspaces. ```{note} Remix Web stores your files in the browser and browser storage is limited. Cloning a repository that is too large will crash the Remix IDE. This is why you have to manually specify the depth and branches you want to clone. If you are using {doc}`Remix Desktop ` you don't have to worry about cloning large repositories. ``` ![Remix Git plugin clone section.](images/git/gh-clone.png) ### Committing changes to Git You can commit the changes you made to your current Workspace using the "**SOURCE CONTROL**" accordion item in the Git plugin. Stage files individually using the plus icon next to them or all at once using the plus icon on the "**Changes**" dropdown label. Enter commit messages in the text box and commit the staged changes using the "**Commit**" button. ![Remix Git plugin clone section.](images/git/gh-commit.png) ### Adding a remote repository You can add a remote repository to your Workspace on Remix using the "**REMOTE**" accordion item by either loading from GitHub or adding it manually using a remote URL. ![Remix Git plugin highlighting the REMOTE tool.](images/git/gh-remote-repo.png) ### Running common commands The Git plugin has limited support for Git commands, as of Remix v0.70, you can run the following: - `git push` - `git push --force` - `git fetch` - `git pull` You can run these commands through the "**COMMANDS**" accordion item in the Git plugin. ![Remix Git plugin showing common Git commands.](images/git/gh-git-commands.png) ```{tip} You can view the output of some of these commands on the "**LOGS**" accordion item. ``` ### Managing multiple branches You can manage the multiple branches associated with your Workspace initialized with Git or cloned from GitHub from the "**BRANCHES**" accordion item. ![Remix Git plugin showing multiple branches](images/git/gh-git-branches.png) You can view the current branch from the Footer. ![Remix IDE branch indicator.](images/git/a-fe-branch-man1.png) ### [Search in Files](https://remix-ide.readthedocs.io/en/latest/search_in_fe.html) > Search and replace text across your Remix IDE workspace files with support for regular expressions. # Search in Files The **Search in Files** plugin is loaded by default. It also includes functionality to search & replace as well as searching with regular expressions. ![Search in Files plugin panel](images/search-in-fe/a-search.png) This plugin searches through text in the files of the current workspace. It does not search across workspaces. ## Search and replace Clicking on the caret to the left of the text input box will reveal the **replace** functionality. ![Search in Files panel with replace field expanded](images/search-in-fe/a-search-open.png) ### [Plugin Manager](https://remix-ide.readthedocs.io/en/latest/plugin_manager.html) > Activate, deactivate, and manage plugins in Remix IDE using the Plugin Manager to customize your development environment. # Plugin Manager In Remix IDE you only load the functionality you need. Controlling which plugins are active or inactive happens in the **Plugin Manager**. This plugin architecture has made it possible to integrate tools made by the Remix team with tools made by external teams. This architecture also allows Remix or just parts of Remix to be integrated into other projects. ![Remix Plugin Manager page.](images/plugin-manager/a-plugin-man-overview.png) ## Manage permissions When plugins need to access other plugins for their operation, a modal will appear to ask you for permission. ![Remix permission modal](images/plugin-manager/a-permission-modal.png) Often, the same plugin will want to do the same action multiple times. So when granting permission, it's helpful to click the **Remember this choice** box. If you don't, you might get this modal repeatedly popping up. ## View permissions You can view the permissions that you have granted to plugins by clicking on the **Permissions** button at the bottom of the **Plugin Manager**. A modal will appear like the one below where you can view and erase the granted permission. ![Plugin Manager permissions modal showing granted plugin permissions](images/plugin-manager/a-plugin-manager-modal.png) ## Plugin devs: load a local plugin A plugin in development can be loaded into Remix IDE by clicking the "Connect to a Local Plugin" link at the top of the Plugin Manager panel. To learn more about how to create your own plugin, go to [the README of remix-plugin repo](https://github.com/remix-project-org/remix-plugin). ### [Settings](https://remix-ide.readthedocs.io/en/latest/settings.html) > Configure Remix IDE settings including themes, compiler options, gas limits, and editor preferences. # Settings You can access **Settings** for Remix by clicking the gear icon at the top right of Remix. ## General settings ![Remix General Settings Page](images/settings/a-settings-general.png) - **Generate contract metadata** is used for deploying with libraries. See our blog post on the subject: [Deploying with Libraries](https://medium.com/remix-ide/deploying-with-libraries-on-remix-ide-24f5f7423b60?sk=68f9c2bf318e85e129e46fe44683a730) - **Always use Remix VM at Load** will make the Remix VM the selected **environment** when Remix loads. - **Word wrap** controls if word wrap is enabled in the Editor. - **Enable code completion in editor** controls code completion. Autocompleting Solidity code happens when you type in the Editor. This option has the Compiler run in the background. For more information about autocomplete, see the {ref}`Editor docs `. - **Display gas estimates in editor** controls if gas estimates are shown. The gas estimates only works when a compilation is successful. - **Display errors in editor while typing** - **Enable Personal Mode for web3 provider** can be used when one is connecting to a **local node**. It is used to have Remix temporarily save the passphrase - so that you don't need to **unlock** the account in Geth. Remix will not persist the passphrase - so if you refresh your browser the passphrase will be gone. - **Save environment state** controls if state of the Remix VM (Remix's simulated blockchain) is saved in a file in the File Explorer. With this option enabled, the Remix VM's state will be saved, so if the browser is closed, the state of the VM will be preserved when you return. This is true as long as the storage in your browser does not get cleared or corrupted. ### Appearance The Appearance subsection allows you to customize the look of Remix. You can choose between the Dark and Light themes. ## Analytics **Matomo Analytics** is our "opt-in" analytics platform. The option to turn on Matomo is offered when you first come to Remix. You can disable or enable Matomo here in the Settings panel. We do not collect any personally identifiable information (PII) and our reports are public. See our [blog post on the subject](https://medium.com/remix-ide/help-us-improve-remix-ide-66ef69e14931?source=friends_link&sk=cf9c62fbe1270543eb4bd912e567e2d6). ![Remix Analytics Page.](images/settings/remix-analytics.png) ## RemixAI Assistant ![RemixAI Assistant Settings Page](images/settings/a-settings-ai1.png) The RemixAI Assistant section allows you to configure RemixAI, manage LLM selections, and control **Model Context Protocol (MCP)** connections. - **LLM Configuration**: Select your preferred AI model (OpenAI, Anthropic, MistralAI, or local Ollama). - **MCP Connections**: Enable or disable connected MCPs (Remix IDE, Workspace, Terminal) and manage their permissions. This allows the AI to perform agentic tasks within your environment. - **Privacy & Data**: Configure data retention and privacy settings for your AI interactions. For more information about using AI in Remix, see the {doc}`AI documentation `. ## Connected services The Connected Services section allows you to configure credentials and access tokens for external services that integrate with Remix. These connections enable features like Git operations, contract verification, circuit compilation, and decentralized storage. ![Connected Services](images/settings/connected-services.png) ### GitHub credentials When performing Git operations on GitHub and when creating GISTs, it may be necessary to input an access token. This token has the specific permissions for your Git commands. Depending on the operation, you may also need to input your GitHub username & email address. Remix does not save your password info outside of your browser's localstorage. ![Remix GitHub Credentials page.](images/settings/a-settings-gh-token.png) ### Etherscan Access Token **The Etherscan Access token is used in three operations in Remix:** 1. When using the Deploy & Verify button, the token can be saved either in the Settings panel or in the Contract Verification plugin's Settings tab. 2. When using the Contract Verification plugin, the Etherscan Access token must be placed in the Contract Verification plugin's Settings tab. 3. When debugging verified contracts with the Remix Debugger, the token must be input in the Settings panel. See the {doc}`Contract Verification plugin Docs ` for more info. ```{tip} Visit the [Etherscan API page](https://etherscan.io/api) to get your Etherscan API key. ``` ![Remix Etherscan Access Token page.](images/settings/a-settings-etherscan.png) _Adding Etherscan Access Token on the Settings Page_ ![Contract Verification plugin settings page.](images/settings/etherscan-token-cv-plugin.png) _Adding Etherscan Access Token on the Contract Verification plugin Settings Page_ ### Sindri Credentials The access token is used to compile ZKP circuits and generate proofs with Sindri. To generate the token go to [Sindri](https://sindri.app). ![Remix Sindri settings page.](images/settings/a-settings-sindri.png) ### Swarm Settings In the Solidity Compiler, after the compilation is completed, there is a button to publish to Swarm. ![Remix Solidity Compiler highlighting Publish on Swarm.](images/settings/a-settings-pub-swarm.png) Without putting in an address & postage stamp, you'll be using the public gateway, which may not persist your content as surely as if you put in your own info. ![Remix Swarm Settings.](images/settings/a-settings-swarm.png) ### IPFS Settings Just like the Swarm settings above, IPFS settings are for publishing your contracts to IPFS from the Solidity Compiler. - If you do not put in any settings here, you will be using the public Infura node. This will not guarantee your data will persist. Other options are to: - Use your own Infura IPFS node. This requires a subscription. [Learn more](https://www.infura.io/product/ipfs). - Use any external IPFS which doesn’t require any authentication. - Use your own local IPFS node (which usually runs under http://localhost:5001) ![Remix IPFS settings](images/settings/a-settings-ipfs.png) ### [Editor](https://remix-ide.readthedocs.io/en/latest/solidity_editor.html) > Remix IDE uses the Monaco editor with Solidity, JavaScript, and TypeScript syntax highlighting, auto-save, and code formatting. # Editor - Remix uses the Monaco editor. This is the same editor used by VSCode. - Remix saves the current file every 5 seconds. - The Remix Editor will highlight keywords in Solidity, JavaScript, and TypeScript. ## Editor displays information from other plugins The main purpose of the Editor is, of course, to edit code. But it also works with other plugins, notably, the Solidity Compiler and the Debugger. - The Solidity Compiler will display warnings and errors in the Editor's gutter at the problematic line. - Breakpoints for the Debugger are input in the Editor's gutter. - When stepping through code in the Debugger, the relevant code will be highlighted in the Editor. ![Remix editor showing code with gutter annotations from the Solidity Compiler and Debugger](images/solidity-editor/a-editor-general.png) ## General operations Files are open as tabs. When there are too many tabs to display, scrolling with a mouse wheel will horizontally scroll the tabs. ![Remix editor showing multiple open file tabs with toolbar controls](images/solidity-editor/a-editor-tabs.png) - The play button works on the active tab. If a Solidity file is active, clicking Play will compile it. If a TypeScript or JavaScript file is active, Play will run the script. - The magnifying glass icons (+/-) on the top left corner are to increase/decrease the font size. - The small type on the far right of the Editor is clickable to jump to a section. ## TypeScript The Editor and Script Runner support TypeScript, which means that you can write TypeScript, have some auto-completion, and run it straight from Remix. As stated above, there is syntax highlighting in TS. The default Workspace contains example TypeScript files. ## Editor & autoCompile When auto-compile is enabled (in the Solidity Compiler), compilation will occur each time the current file is changed, or another file is selected. ![Remix editor settings showing auto-compile enabled](images/solidity-editor/a-editor-settings.png) ## Autocomplete Autocompleting Solidity code happens when you start typing in the Editor. The Compiler will run in the background, and process any imports you have. You will see these imports appear in the .deps directory in the File Explorer. ![Remix editor showing Solidity autocomplete suggestions while typing](images/solidity-editor/a-editor-autocomplete1.png) ```{tip} If you start with a Solidity file that contains errors, the Compiler might not be able to compile it. In that case, the Editor's autocomplete features will not fully work until after the file is successfully compiled. After that, autocomplete will work even if there are errors, but only for the elements the Compiler already understands. For example, if you add a new function in a file that contains errors, autocomplete will not be able to find that function because it can’t compile the file. ``` ![Remix editor showing autocomplete dropdown with Solidity suggestions](images/solidity-editor/a-editor-autocomplete.png) ## Auto complete on imports The Editor's autocomplete will offer the option to bring in OpenZeppelin contracts, Uniswap contracts, and the paths to all the files in the current Workspace. ![Remix editor showing import autocomplete with OpenZeppelin and Uniswap options](images/solidity-editor/a-editor-auto-import1.png) So, when choosing @openzeppelin, you’ll get this: ![Remix editor showing OpenZeppelin import path autocomplete](images/solidity-editor/a-editor-auto-oz-import2.png) And the same with Uniswap: ![Remix editor showing Uniswap import path autocomplete](images/solidity-editor/a-editor-auto-uni-import3.png) ## Errors and warnings You can tell the file was successfully compiled if no errors or warnings are displayed in the Editor. Errors are displayed using squiggly lines. A red line indicates an error, a yellow line is a warning. ![Remix editor showing red and yellow squiggly lines indicating errors and warnings](images/solidity-editor/a-editor-error-red-squiggles.png) Hovering over the squiggly line shows you the message from the Compiler. ![Remix editor showing compiler error message on hover over squiggly line](images/solidity-editor/a-editor-error-hover.png) Tabs and the File Explorer will also will also display whether a file contains errors or warnings. ![Remix editor tabs and File Explorer showing error and warning indicators](images/solidity-editor/a-editor-errors-tabs-fe.png) #### Errors on Imported Files A file with errors in one of the files that it imports will also trigger an error in the Editor. Your main file might not compile, but you will see there is a problem immediately. ### Hovering over an Error Number in the File Explorer The number of errors in a file is also reported in the File Explorer. Hovering over the number, which indicates the amount of errors/warnings, will display the information from the Compiler. ![File Explorer showing error count with hover tooltip from the compiler](images/solidity-editor/a-editor-error-fe-num.png) ## Quick Fixes for common mistakes The Remix editor offers solutions to the following missing keywords & code: - License - Pragma - Visibility - Mutability - Data Location (storage, memory, etc) - Add virtual or override - Marking a contract abstract A Quick Fix option is available when there is a blue dot in Editor - like in the image below. In this example, the license has been left out. After compilation, a warning is triggered and a Quick Fix blue dot appears. ![Remix editor showing Quick Fix blue dot for a missing license warning](images/solidity-editor/a-editor-qf-license.png) When you click on the blue dot, a popup menu appears. In this case of a missing license, these are the options: ![Remix editor showing Quick Fix popup menu with options for adding a license](images/solidity-editor/a-editor-qf-license-options5.png) If you can’t get the Quick Fix blue dot to appear, try clicking on the number for the line where the error occurs. ## Gas estimates Gas estimates are displayed on the same line where a function is declared. ![Remix editor showing inline gas estimates next to function declarations](images/solidity-editor/a-editor-i-got-gas.png) Constructor gas estimates are also displayed, and consist of two components: creation cost and code deposit cost. ## Go to definition and references ### Definitions By right-clicking, you can go to a definition. You can also use the shortcut displayed. You can also right-click on the filename of an import statement and jump to that file. ![Remix editor showing go to definition context menu option](images/solidity-editor/a-editor-goto-def.png) You can also ‘peek’ at the definition inline in the Editor. You can then jump to a definition by double-clicking on the right hand side of the line. ### References By right-clicking, you can display all the references. You can also use the shortcut displayed. ![Remix editor showing all references panel for a selected symbol](images/solidity-editor/a-editor-refs1.png) You can jump to a reference by double-clicking on the right hand side of the line. ![Remix editor showing a reference with double-click jump option](images/solidity-editor/a-editor-ref2.png) ## Highlighted references References are highlighted in the Editor. ![Remix editor showing highlighted references for a selected symbol](images/solidity-editor/a-editor-ref-highlight.png) ## Hovering When you hover over a term with a definition, the definition will pop up. Hovering over code that has triggered an error (underlined with a red squiggly line) will show the error message. ![Remix editor showing definition popup on hover over a term](images/solidity-editor/a-editor-hover.png) ## Files with errors turn red When a file contains an error, its name will turn red, both in the File Explorer and on its tab at the top of the Editor. More about the Editor updates in this article: Major Updates to Remix Editor ### [Deploy & Run](https://remix-ide.readthedocs.io/en/latest/run.html) > Deploy and interact with smart contracts in Remix IDE using multiple environments including the Remix VM, Browser Extension, WalletConnect, and custom RPC endpoints. # Deploy & Run The Deploy & Run module is for sending transactions to the current **Environment**. The three main actions of the Deploy & Run module are: 1. **Deploying** a contract 2. **Loading** a deployed contract 3. **Interacting** with the functions of a deployed contract This documentation page will cover **Deploying** and **Loading**. Interacting will be covered in {doc}`Deploy & Run part 2 `. ![Deploy & Run plugin](images/deploy-and-run/a-deploy-run1.png) ## Deploying a contract To deploy a contract, it must first be compiled. There are three ways you can compile a contract: 1. You can compile your contract directly from the {doc}`Solidity Compiler plugin `. This allows you to configure the compiler's behavior, including the Solidity version, optimization settings, and EVM target before compiling. 2. You can use the "**Compile**" button that appears in the main panel when you have an active Solidity file. The compilation uses the configuration from the Solidity Compiler plugin, applying whatever settings were last saved there. 3. You can compile directly from the Deploy & Run plugin using the "Deploy" section. It displays a list of the contracts active in the editor, along with a "**Compile**" button that compiles using the settings stored in the Solidity Compiler plugin. ![The Deploy tab showing the contract selector and Compile button.](images/deploy-and-run/deploy-tab.png) Once you have compiled and selected your contract, choose the chain for deployment and/or method for deployment, deployment wallet, and EVM version in the **ENVIRONMENT** section. ![The Environment tab showing environment selector, account, gas limit, and value fields.](images/deploy-and-run/environment-tab.png) ```{note} If you want to connect Remix with a browser wallet (e.g., MetaMask, Phantom), set your environment to **Browser Extension** and choose your preferred wallet/chain. ``` Before clicking **Deploy**, you can configure two additional fields: - **Gas Limit**: Sets the maximum amount of gas allowed for the deployment transaction. Remix pre-fills a sensible default, but you can increase it if your contract is complex or if the deployment reverts due to an out-of-gas error. - **Value**: The amount of ETH (or wei, gwei, etc.) sent along with the deployment transaction. Only relevant if your contract has a payable constructor. Otherwise, leave it at 0. Clicking "**Deploy**" sends a transaction that deploys the selected contract. When the transaction is mined, the newly created instance will be added (this might take several seconds) to the "**Deployed Contracts**" section. ```{note} If the contract's constructor function has parameters, you will need to specify them. ``` ## Verifying on deployment When connected to a public network, there is a switch to enable contract verification. ![The contract verification switch.](images/deploy-and-run/deploy-verify-switch.png) The contract's source-code and metadata will be submitted to Etherscan, Sourcify, Blockscout, and Routescan. For the verification to go through on Etherscan, their API needs to be input either in the Remix Settings panel or in the Contract Verification plugin's Settings tab. Verification can also be done using the Contract Verification plugin. ## Loading deployed contracts If a contract has already been deployed, you can load it into Remix using the "**Add Contract**" button on the **Deployed Contracts** section. Adding an already deployed contract costs no gas, since no redeployment is required. To load a deployed contract: 1. Make sure the contract's source code or ABI is in the active tab of the Editor. If using source code, it must be compiled with the same settings as the originally deployed contract. 2. Enter the deployed contract's address in the contract address field that appears when you click the "**Add Contract**" button. 3. The contract instance will appear in the **Deployed Contracts** list, ready to interact with. ![The Deployed Contracts section showing the contract address field and Add button.](images/deploy-and-run/load-contract.png) ```{warning} Only load contracts from addresses you trust. ``` ### Using the ABI to load contracts If you don't have the source code but have the contract's **ABI**, you can still load and interact with it. The ABI is a JSON array that describes a contract's functions, inputs, and outputs. To use it: 1. Create a new file in Remix with a `.abi` extension and paste the ABI content into it. 2. Make sure this file is the active tab in the Editor. 3. Enter the contract address in the **Contract address** field and click the "**Add**" button. The contract will appear in the **Deployed Contracts** list. ```{note} To get the ABI of a contract you've compiled, open the Solidity Compiler plugin, compile the contract, then click **Compilation Details**. The ABI is listed in the modal that appears. ``` ## Supported environments The Deploy & Run plugin supports several environments that determine where your transactions are sent and how they are signed. You can choose between an in-browser sandbox (including forked chains), a browser wallet, a mobile wallet, or a locally running node. ### Remix VM The Remix VM is a sandbox blockchain in the browser. Transactions do not require an approval to run. Remix VM comes with 10 accounts, each loaded with 100 ETH. The Remix VM supports multiple EVM forks letting you simulate different network conditions without connecting to a live chain. The **state** of the Remix VM chain is saved in the **.states folder** in the File Explorer. If you do not want the Remix VM state to be saved, uncheck **Save environment state** in the Settings panel. Saving the state means you can refresh the browser and not lose your work, the caveat being that browser storage is inherently unstable. Pushing to a remote repository avoids relying on browser storage entirely. In collaborative workflows, you can share the VM state by having teammates load the **state.json** file into their Remix instance. ![The File Explorer showing the .states folder containing the state.json file.](images/deploy-and-run/a-deploy-run-state-file.png) ### Browser Extension Browser extension wallets allow you to connect Remix to a wallet installed in your browser, such as **MetaMask** or **Phantom**. This is the standard way to deploy contracts to a live network or testnet using your own accounts. To use a browser extension: 1. Install a supported wallet extension e.g., MetaMask. (This option will not be visible if you do not have an extension installed). 2. Set the **ENVIRONMENT** to **Browser Extension** in the Deploy & Run panel. Transactions sent through a browser extension require approval in the wallet popup before they are broadcast to the network. ```{note} Make sure your wallet is unlocked and set to the correct network before deploying. ``` ### Mobile Wallets (Wallet Connect) WalletConnect allows you to connect Remix to a wallet on your mobile device by scanning a QR code. This is useful when you want to sign transactions with a hardware-backed or mobile wallet rather than a browser extension. To use WalletConnect: 1. Set the **ENVIRONMENT** to **WalletConnect**. 2. A QR code will appear, scan it with your mobile wallet app (e.g., MetaMask Mobile, Rainbow, Trust Wallet). 3. Approve the connection in your wallet. Remix will then use your mobile wallet's accounts and selected network. Transactions triggered in Remix will appear as signing requests on your mobile device. ### Development Environments Development environments connect Remix to locally running nodes or L2 networks, making them suitable for advanced testing and integration workflows. - **Hardhat Provider**: Connects to a locally running [Hardhat](https://hardhat.org/) node. Transactions execute instantly and do not require wallet approval, making it fast for iterative development. - **Foundry Provider**: Connects to a locally running [Anvil](https://www.getfoundry.sh/anvil) node (part of the Foundry toolchain). Like Hardhat, it runs a local chain with pre-funded accounts and instant transaction finality. - **External HTTP Provider**: Connects Remix to any remote or local Ethereum-compatible node via an RPC URL (e.g., a Geth or Erigon instance). Enter the node's http endpoint when prompted. Read more about [connecting to an External Provider](#more-about-external-http-provider). ```{note} When using a local provider (Hardhat or Foundry), make sure the node is running before selecting the environment in Remix. ``` ### More About External HTTP Provider If you are using Geth and https://app.remix.live, please use the following Geth command to allow requests from Remix: ```shell geth --http --http.corsdomain https://app.remix.live ``` Also see [Geth Docs about the http server](https://geth.ethereum.org/docs/interacting-with-geth/rpc) To run Remix using https://app.remix.live and a local test node, use this Geth command: ```shell geth --http --http.corsdomain="https://app.remix.live" --http.api web3,eth,debug,personal,net --vmdebug --datadir --dev console ``` If you are using Remix-alpha or a local version of Remix, replace the URL of the --http.corsdomain with the URL of Remix that you are using. To run Remix Desktop and a local test node, use this Geth command: ```shell geth --http --http.corsdomain="package://a7df6d3c223593f3550b35e90d7b0b1f.mod" --http.api web3,eth,debug,personal,net --vmdebug --datadir --dev console ``` Also see [Geth Docs on Dev mode](https://geth.ethereum.org/docs/developers/dapp-developer/dev-mode) The Web3 Provider Endpoint for a local node is **http://localhost:8545** ```{warning} Avoid using a wildcard with the Geth flag `--http.corsdomain`. Using `--http.corsdomain *` allows any origin to access your node. Only use this when running a **test chain** with **test accounts**. For real accounts or mainnet, always specify the exact URL, e.g. `--http.corsdomain 'https://app.remix.live'`. ``` ## Forking Chains in Remix Forking a chain will bring that chain to the Remix VM. Once it is forked, you'll have access to the 10 accounts loaded with 100 ETH. ### Remix VM Forks You can also fork the Remix VM in its current state. To fork the Remix VM, click the version control icon to the right of the Environment title to create a fork and then to name it. ![Fork VM state modal.](images/deploy-and-run/fork-vm-state.png) You can switch between existing Remix VM forks by selecting "Forked State" from the Environment dropdown menu. ![Forked state option.](images/deploy-and-run/forked-state.png) ```{note} The "Forked State" option only appears in the dropdown when there is an existing Remix VM fork. ``` ### Live Network Forks The Remix VM can fork a live network, loading its state into the in-browser sandbox. This lets you test contracts against real on-chain data (such as existing token balances, deployed protocols, or mainnet contract state) without spending real ETH. The following fork options are available: - **Mainnet fork**: Forks the Ethereum mainnet at the latest block. - **Sepolia fork**: Forks the Sepolia testnet, useful for testing against testnet deployments. - **Custom fork**: Forks any EVM-compatible chain at a block number of your choice. See [Custom Fork](#forking-a-custom-chain) below. #### Forking a Custom Chain The Custom fork option allows you to specify a chain's RPC server, a block number, and an EVM version. ![The Custom Fork modal showing fields for Node URL, block number, and EVM version.](images/deploy-and-run/custom-fork.png) You can get the **Node URL** from [chainlist.org](https://chainlist.org). If the chain does not load, you may need to choose a different RPC server. You will also need to choose an EVM version appropriate to the block number. If you choose a very low block number, post-Merge EVM versions won't work since they didn't exist at that point in the chain's history. You can reset the state of the VM by clicking the refresh icon to the right of the version control icon. Forking the VM lets you snapshot a working state, try changes, and return to the original if needed. ## Using the recorder The Recorder is a tool used to save a sequence of transactions in a JSON file and re-run them later, either in the same environment or in another. Saving to the JSON file (by default it's called scenario.json) allows one to easily check the transaction list, tweak input parameters, change linked libraries, etc. There are many use cases for the Recorder. For instance: - After having coded and tested contracts in a constrained environment, like the Remix VM, you could then switch the environment and redeploy the contract to a more realistic environment, like a public testnet or to a Geth node. By using the generated **scenario.json** file, you will be using all the same settings that you used in the Remix VM. The Recorder eliminates the need to manually recreate that state step by step. You can also change the settings in the scenario.json file to customize the playback. - Deploying a contract often requires more than creating one transaction, and the Recorder will automate this deployment. - Working in a dev environment often requires setting up the state initially. ![The Recorder panel showing the transactions recorded count and save button.](images/deploy-and-run/recorder.png) When checked, the option `Run transactions using the last compilation result` allows you to develop a contract and easily set the state using **the latest compiled versions of the contracts.** ### scenario.json To create this file in the Recorder, you first need to have run some transactions. The **Transactions Recorded** counter starts at `0` and increments with each transaction. Once you have recorded the transactions you need, click the floppy disk icon to save the scenario.json file. The example below shows a `scenario.json` file containing three transactions, all sent from `account{0}`: 1. **Deploy `testLib`**: deploys a library contract with no constructor parameters. 2. **Deploy `test`**: deploys a contract with constructor parameter `11`. It depends on `testLib`, so the `linkReferences` property maps the library name to the address of the previously created instance using the timestamp ID `created{1512830014773}`. 3. **Call `set` on `test`**: calls the `set` function on the deployed `test` contract (referenced as `created{1512830015080}`) with parameters `1` and `0xca35b7d915458ef540ade6068dfe2f44e8fa733c`. ```json { "accounts": { "account{0}": "0xca35b7d915458ef540ade6068dfe2f44e8fa733c" }, "linkReferences": { "testLib": "created{1512830014773}" }, "transactions": [ { "timestamp": 1512830014773, "record": { "value": "0", "parameters": [], "abi": "0xbc36789e7a1e281436464229828f817d6612f7b477d66591ff96a9e064bcc98a", "contractName": "testLib", "bytecode": "60606040523415600e57600080fd5b60968061001c6000396000f300606060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680636d4ce63c146044575b600080fd5b604a6060565b6040518082815260200191505060405180910390f35b6000610d809050905600a165627a7a7230582022d123b15248b8176151f8d45c2dc132063bcc9bb8d5cd652aea7efae362c8050029", "linkReferences": {}, "type": "constructor", "from": "account{0}" } }, { "timestamp": 1512830015080, "record": { "value": "100", "parameters": [11], "abi": "0xc41589e7559804ea4a2080dad19d876a024ccb05117835447d72ce08c1d020ec", "contractName": "test", "bytecode": "60606040526040516020806102b183398101604052808051906020019091905050806000819055505061027a806100376000396000f300606060405260043610610062576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680632f30c6f61461006757806338cc48311461009e57806362738998146100f357806387cc10e11461011c575b600080fd5b61009c600480803590602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610145565b005b34156100a957600080fd5b6100b1610191565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156100fe57600080fd5b6101066101bb565b6040518082815260200191505060405180910390f35b341561012757600080fd5b61012f6101c4565b6040518082815260200191505060405180910390f35b8160008190555080600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008054905090565b600073__browser/ballot.sol:testLib____________636d4ce63c6000604051602001526040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160206040518083038186803b151561022e57600080fd5b6102c65a03f4151561023f57600080fd5b505050604051805190509050905600a165627a7a72305820e0b2510bb2890a0334bfe5613d96db3e72442e63b514cdeaee8fc2c6bbd19d3a0029", "linkReferences": { "browser/ballot.sol": { "testLib": [ { "length": 20, "start": 511 } ] } }, "name": "", "type": "constructor", "from": "account{0}" } }, { "timestamp": 1512830034180, "record": { "value": "1000000000000000000", "parameters": [1, "0xca35b7d915458ef540ade6068dfe2f44e8fa733c"], "to": "created{1512830015080}", "abi": "0xc41589e7559804ea4a2080dad19d876a024ccb05117835447d72ce08c1d020ec", "name": "set", "type": "function", "from": "account{0}" } } ], "abis": { "0xbc36789e7a1e281436464229828f817d6612f7b477d66591ff96a9e064bcc98a": [ { "constant": true, "inputs": [], "name": "get", "outputs": [ { "name": "", "type": "uint256" } ], "payable": false, "stateMutability": "view", "type": "function" } ], "0xc41589e7559804ea4a2080dad19d876a024ccb05117835447d72ce08c1d020ec": [ { "constant": true, "inputs": [], "name": "getInt", "outputs": [ { "name": "", "type": "uint256" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": true, "inputs": [], "name": "getFromLib", "outputs": [ { "name": "", "type": "uint256" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": true, "inputs": [], "name": "getAddress", "outputs": [ { "name": "", "type": "address" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": false, "inputs": [ { "name": "_t", "type": "uint256" }, { "name": "_add", "type": "address" } ], "name": "set", "outputs": [], "payable": true, "stateMutability": "payable", "type": "function" }, { "inputs": [ { "name": "_r", "type": "uint256" } ], "payable": true, "stateMutability": "payable", "type": "constructor" } ] } } ``` ### [Deploy & Run (part 2)](https://remix-ide.readthedocs.io/en/latest/udapp.html) > Interact with deployed contracts in Remix IDE — call functions, send transactions, and inspect contract state in the Deploy & Run panel. Deploy & Run (part 2) ===================== .. meta:: :description: Interact with deployed contracts in Remix IDE — call functions, send transactions, and inspect contract state in the Deploy & Run panel. :keywords: remix udapp, deployed contracts, interact contracts, remix ide, send transactions This is part 2 of the documentation covering the Deploy & Run plugin. Part 1 covers :doc:`deploying and accessing a contract `. Interacting with deployed contracts ------------------------------------ After you deploy a contract or :ref:`load it into Remix using Add Contract `, the deployed instance will appear in the **Deployed Contracts** section on Deploy & Run. .. image:: images/udapp/a-deploy-run-deployed-instances.png :alt: Deployed Instances The deployed contract's address is visible as are a few other icons - one of which is the **pin** icon. Pinned contracts ---------------- When a contract is pinned, its address and ABI are stored in the ``.deploys`` folder of the current Workspace. Upon reloading Remix, pinned contracts will automatically appear in the **Deployed Contracts** section, provided that both the Workspace and the connected blockchain network remain the same as when the contract was originally pinned. Functions --------- To see a contract's functions, click on the deployed contract. .. video:: images/udapp/viewing-functions.mp4 :nocontrols: :autoplay: :playsinline: :muted: :loop: :width: 100% The functions' buttons can have different colors. - Blue buttons are for ``view`` or ``pure`` functions. Clicking a blue button does not create a new transaction - so there will be **no gas fees**. - Orange buttons are for ``non-payable`` functions. Non-payable functions change the state of the contract BUT **do not accept value** (typically ETH) being sent with the transaction. Clicking an orange button will create a transaction and will cost gas. - Red buttons are for ``payable`` functions. Clicking a red button will create a new transaction and this transaction can accept a **value** (typically ETH). The amount of value is set in the **Value** field which is under the Gas Limit field. .. image:: images/udapp/a-jvm-calling-instance.png :alt: Calling different function types Inputting parameters -------------------- A function has two views - the collapsed and the expanded view. Clicking the function brings you to the expanded view, where you can input the parameters required for the function. - The input box shows the expected type of each parameter. - Numbers and addresses do not need to be wrapped in double quotes. - Strings must be wrapped in double quotes. .. image:: images/udapp/a-udapp-inputs.png :alt: Inputting Parameters in function calls Low level interactions ---------------------- Low level interactions are used to send funds or calldata or funds & calldata to a contract through the ``receive()`` or ``fallback()`` function. Typically, you should only need to implement the fallback function if you are following an upgrade or proxy pattern. To find the low level interactions section, you have to click the contract from the Deployed Contracts section, then click the plus icon with the label "Low level interaction". .. image:: images/udapp/low-level-interaction.png :alt: Low level interactions section .. note:: If you are executing a plain Ether transfer to a contract, you need to have the ``receive()`` function in your contract. If your contract has been deployed and you want to send it funds, you would input the amount of Ether or Wei etc. (see **A** in graphic below), and then input **NOTHING** in the calldata field of **Low level interactions** (see **B** in graphic) and click the Transact button (see **C** in graphic below). .. image:: images/udapp/receive-function.png :alt: Receive function example When using low level interactions, keep the following rules in mind: - If you are sending calldata to your contract with Ether, then you need to use the ``fallback()`` function and have it with the state mutability of **payable**. - If you are not sending ether to the contract but **are** sending call data then you need to use the ``fallback()`` function. - If you break the rules when using the **Low level interactions** you will see a warning. Please see the `Solidity docs `_ for more specifics about using the **fallback** and **receive** functions. Scientific Notation in Function Inputs --------------------------------------- You can use scientific notation to pass numbers as function argument. For example, instead of inputting 12000000000000000000, you can input 12e18. This works for both arrays and single inputs. .. image:: images/udapp/scientific-notation.png :alt: Scientific Notation Inputting a tuple or struct to a function ------------------------------------------ To pass a tuple, you need to put in an array []. Similarly, to pass in a struct as a parameter of a function, it needs to be put in as an array []. .. note:: For Solidity versions before 0.8.0, add ``pragma abicoder v2;`` or ``pragma experimental ABIEncoderV2;`` to your file. This is enabled by default in 0.8.0 and later. Example of passing nested struct to a function ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Consider a nested struct defined like this: .. code-block:: solidity struct Flower { uint flowerNum; string color; } struct Garden { uint slugCount; uint wormCount; Flower[] theFlowers; } If a function has the signature ``fertilizer(Garden memory gardenPlot)`` then the correct syntax is: .. code-block:: text [1,2,[[3,"Petunia"]]] To continue on this example, here's a sample contract: .. code-block:: solidity pragma solidity ^0.8.0; contract Sunshine { struct Flower { uint flowerNum; string color; } struct Garden { uint slugCount; uint wormCount; Flower[] theFlowers; } function fertilizer(Garden memory gardenPlot) public pure returns (uint, string memory) { require(gardenPlot.theFlowers.length > 0, "No flowers"); return (gardenPlot.theFlowers[0].flowerNum, gardenPlot.theFlowers[0].color); } } After compiling, deploying the contract and opening up the deployed instance, we can then add the following input parameters to the function named **fertilizer**: .. code-block:: text [1,2,[[3,"Black-eyed Susan"],[4,"Pansy"]]] The function **fertilizer** accepts a single parameter of the type **Garden**. The type **Garden** is a **struct**. Structs are wrapped in **square brackets**. Inside **Garden** is an array that is an array of structs named **theFlowers**. It gets a set of brackets for the array and another set for the struct. Thus the double square brackets. ### [Deploy & Run Proxy Contracts](https://remix-ide.readthedocs.io/en/latest/run_proxy_contracts.html) > Deploy and manage UUPS proxy contracts in Remix IDE with built-in support for upgradeable smart contract patterns. # Deploy & Run Proxy Contracts Remix IDE has the functionality to assist in the handling of proxy contracts that use the UUPS pattern. A UUPS contract is an implementation contract that contains both the business logic and the upgrade mechanism. It is deployed alongside an [ERC1967Proxy](https://eips.ethereum.org/EIPS/eip-1967), which delegates all calls to it. ## Deploying To try this out, you will need a UUPS contract. Create a new Workspace in Remix and click the Contract Wizard. In the Wizard's **Upgradeability** section check **UUPS** and in the **Access Control section**, choose **Ownable**. Then compile it, and open Deploy & Run. ```{note} UUPS contracts use an `initialize` function instead of a constructor. Call `initialize` via the proxy after deployment to set up initial state. The constructor is intentionally disabled with `_disableInitializers()`. ``` When a UUPS contract is selected in Deploy & Run's Contract dropdown, you'll see some switches below the Deploy button: ![Deploy and Run panel showing proxy deployment checkboxes for a UUPS contract](images/proxy-contracts/proxy-checkboxes.png) Turn on the **Deploy with Proxy** switch. This will create two transactions: one for the implementation (your contract) and the other for the ERC1967 proxy contract. You will get two modals to check through: ![First proxy deployment confirmation modal](images/proxy-contracts/a-proxy-modal1.png) and then ![Second proxy deployment confirmation modal](images/proxy-contracts/a-proxy-modal2.png) If you are deploying to the **Remix VM**, these modals will appear one after the other. If you are connected to the mainnet or a public testnet, then the second modal will appear after the first transaction has gone through. After the ERC1967 proxy contract is deployed, in the Deployed Contracts section, you'll see two deployed instances. ![Deployed Contracts section showing two instances after proxy deployment](images/proxy-contracts/a-deployed-instances.png) To interact with your implementation contract **DO NOT** use the instance of your contract. Instead, you should **use the ERC1967 Proxy**. The proxy will have all the functions of your implementation. ## Upgrading To upgrade, turn on the **Upgrade with Proxy** switch to reveal the address input: ![Deploy and Run panel showing the Upgrade with Proxy options](images/proxy-contracts/a-proxy-upgrade.png) You'll either need to use the last deployed ERC1967 contract, or input the address of the ERC1967 contract that you want to use. Upgrading deploys your new implementation contract as a separate transaction, then calls `upgradeToAndCall` on the proxy to point it at the new address. Like deploying, this produces two modals: one to confirm the new implementation deployment and one to confirm the upgrade call on the proxy. ```{note} Your implementation contract must include an `_authorizeUpgrade` function. Without it, the upgrade transaction will revert. OpenZeppelin's UUPS base contract requires you to override this function with access control (typically `onlyOwner`) to prevent unauthorized upgrades. ``` ## See also - [OpenZeppelin Upgrades documentation](https://docs.openzeppelin.com/upgrades-plugins/proxies) - [ERC-1967 standard](https://eips.ethereum.org/EIPS/eip-1967) ### [QuickDApp: Generating UIs for your Contracts](https://remix-ide.readthedocs.io/en/latest/quickdapp.html) > QuickDApp is a Remix IDE feature that uses AI to generate React front-end interfaces for deployed Solidity contracts, supporting standard web dApps and Base mini apps. # QuickDApp: Generating UIs for your Contracts QuickDApp is a feature in Remix IDE that uses AI to generate front-end interfaces for your deployed Solidity contracts. Instead of manually building a UI, you can describe the dApp you want, optionally providing a reference image or Figma design, and QuickDApp will generate a ready-to-use React application in a new workspace. It supports both standard web dApps and Base mini apps (Farcaster Frames). ## Creating a dApp There are two ways you can create a dApp using QuickDApp: 1. The Deploy and Run plugin. 2. `.sol` files. ### Creating a dApp from Deploy and Run When you compile and deploy a Solidity contract using the Deploy and Run plugin, a sparkle icon appears on the deployed contract's dropdown. ![Sparkle icon on deployed contract dropdown](images/quickdapp/create-dapp-sparkle.png) Click the sparkle icon to open a prompt modal where you can describe what you want the dApp to look like. You can also upload an image for reference to improve the results of the generation. ![QuickDApp prompt modal for describing your dApp](images/quickdapp/prompt-modal.png) Alternatively, you can import a design from Figma to give QuickDApp more context to generate your UI from. By default, QuickDApp generates a standard web dApp built with React, intended for full-featured browser-based interaction with your contract. However, you can generate it as a Base mini app (Farcaster Frame) that runs inside Farcaster by checking the "Create as Base Mini App (Farcaster Frame)" checkbox. ```{warning} The dApps generated by QuickDApp are designed to work with browser extension wallets like Metamask. Thus, if you deploy your contract on Remix VM or any other non-browser wallet environment, your dApp might not work as expected. ``` After providing all the necessary context for your dApp, click the "**Generate**" button. QuickDApp will create a new workspace where the UI logic will live and redirect you to it. The dApp generation process may take up to 2 minutes or more. ![Generated QuickDApp workspace](images/quickdapp/quickdapp-workspace.png) ### Creating a dApp from `.sol` files When you open a `.sol` file in the Remix IDE, a banner with the label "**Create a dApp with your contract**" will appear at the top of the editor. To create a UI for the open contract, click the "**Start now**" button. ![Start now banner at the top of the editor](images/quickdapp/start-now-banner.png) When you click the "**Start now**" button, QuickDApp checks for deployed instances of the open Solidity file. If there are no deployed instances of the contract, you will be prompted to compile and deploy the contract before clicking the "**Start now**" button again. ![Prompt to compile and deploy when no instances are found](images/quickdapp/no-instances.png) If there is a single deployment of the contract, QuickDApp will prompt you to confirm that you want to create a dApp with the contract. After your confirmation, QuickDApp will show you the context modal where you can describe your UI and upload an image or Figma file, similar to the Deploy and Run plugin flow. For cases where more than one deployed instance of the contract exists, you will need to pick the instance you want to create a dApp for before proceeding. ![Selecting from multiple deployed instances](images/quickdapp/multiple-instances.png) ## Generated Workspace structure QuickDApp creates a new workspace named using the pattern `dapp-{contractName}-{id}`. Below is its structure. ```shell dapp-mytoken-a1b2c3/ ├── dapp.config.json ├── src/ ├── contracts/ └── preview.png ``` - `dapp.config.json` - Contains the contract address, ABI, and chain ID needed to connect the UI to your deployed contract. - `src/` - Contains the AI-generated React components, styles, and application logic that make up your dApp's front end. - `contracts/` - A copy of the Solidity source files used to generate the dApp. - `preview.png` - A thumbnail screenshot of the dApp, generated automatically when you first preview it. ### [Deploying a dApp](https://remix-ide.readthedocs.io/en/latest/deploy_dapp.html) > Deploy dApps generated by QuickDApp to IPFS and link them to an ENS subdomain directly from Remix IDE. # Deploying a dApp ```{warning} This feature is only available to beta testers. Join the Remix beta program to get access. ``` You can deploy dApps generated by {doc}`QuickDApp ` on IPFS and link them to an ENS domain directly from Remix. Remix automatically provides a free ENS subdomain under `remixdapp.eth` for your dApp with no gas fees required. ## Deploying to IPFS Before you deploy to IPFS, you must have a smart contract compiled and deployed using the Deploy & Run plugin, and a dApp generated by the QuickDApp plugin. ```{note} When you are configuring rules for the dApp generation, ensure that you leave the "**Create as Base Mini App**" checkbox unchecked. ``` After QuickDApp generates your dApp, expand the "**Publish to IPFS**" tab in QuickDApp's right panel and click the "**Deploy to IPFS**" button. This bundles and uploads your files to IPFS. Once the upload is complete, a `CID` (Content Identifier) is returned. This is a unique address that identifies your dApp on the network and is used as the target when registering the ENS subdomain. ![The Publish to IPFS tab in the QuickDApp right panel, showing the Deploy to IPFS button and a generated CID after a successful upload](images/deploy_dapp/upload-ipfs.png) ## Register ENS subdomain Once your dApp is on IPFS, you can link it to a human-readable ENS subdomain under `remixdapp.eth` (e.g. `myapp.remixdapp.eth`) so users can access it without needing the raw CID. Registration transactions are processed on **Arbitrum One (L2)**, with gas fees covered by the Remix backend, so you pay nothing. To register the subdomain, expand the "**Register ENS (Arbitrum)**" tab in the QuickDApp right panel. ```{note} This tab only becomes visible after the deployment to IPFS is complete. ``` Enter your preferred subdomain name (e.g., `bridge.remixdapp.eth`) and Remix will check its availability. Once you have selected an available subdomain, click the "**Register Subdomain**" button and wait for the server to process the registration. ![The Register ENS (Arbitrum) tab in the QuickDApp right panel, showing the subdomain input field and Register Subdomain button](images/deploy_dapp/link-ens.png) ```{note} The returned URLs have `.limo` appended (e.g. `myapp.remixdapp.eth.limo`). This is because standard web browsers cannot natively resolve `.eth` domains. `.limo` is a gateway service that resolves ENS names and serves the underlying IPFS content over HTTPS. ``` Your dApp is now live at https://[yourname].remixdapp.eth.limo. ### [Deploy a Base Mini App](https://remix-ide.readthedocs.io/en/latest/mini-app.html) > Deploy a QuickDApp-generated dApp as a Base mini app — register an ENS subdomain under remixdapp.eth and verify ownership through the Base Developer Portal. # Deploy a Base Mini App ```{warning} This feature is only available to beta testers. Join the [Remix beta program](https://forms.remix.live/f/3624097e2e21) to get access. ``` The dApps generated by QuickDApp can also be deployed as Base mini apps. Deploying your dApp as a Base mini app allows you to embed it in Base App, making it instantly accessible to users without requiring them to visit an external site. ## Prerequisites Before you can deploy your dApp as a Base mini app, you need the following: - A smart contract compiled and deployed using the Deploy & Run plugin. - A UI for your contract generated by {doc}`QuickDApp `. ```{important} When generating your dApp UI in QuickDApp, you **must** check the "**Create as Base Mini App**" box before clicking "**Generate**". Skipping this step will produce a standard dApp that cannot be registered as a mini app. ``` ## Deploying as a Base mini app On the preview page of the generated UI, you will find the Base mini app setup wizard on the left side of the screen. ![Base mini app setup wizard in the QuickDApp preview page](images/mini-app/setup-wizard.png) The first tab on the setup wizard requires the Base App ID meta tag of an app. To get meta tags of an app, you have to create one on the [Base Developer Portal](https://dashboard.base.org/). ### Creating a Base app To create a Base app, navigate to dashboard.base.org and log in. If you don't have any existing app you will be prompted to create your first app. If you have existing apps, you will be redirected to the dashboard of your latest app. On the dashboard, click the app dropdown, and select "**Register new app**" ![Register new app option in the Base Developer Portal app dropdown](images/mini-app/create-new-app.png) On the next page, name the app, and click "**Continue**". ![App name entry on the Base Developer Portal](images/mini-app/name-screen.png) This will take you to the "Add Domain" page. ![Base App ID meta tag on the Base Developer Portal](images/mini-app/mini-app-tags.png) On this page, copy the meta tags, paste it in the setup wizard, and click "**Save & Next**". ```{note} The App URL should be blank in this step, you will deploy and get the ENS domain in the next step. ``` ### Registering an ENS domain On the next tab, you will register an ENS subdomain for free under `remixdapp.eth`. Choose your preferred name, for example, `flashloan` -> `flashloan.remixdapp.eth` and click "**Deploy and Next**". Before you register, choose your subdomain name carefully. Names are unique and first-come, first-served. Once registered, the name is permanently tied to your browser wallet address (MetaMask, Coinbase Wallet, etc.) and cannot be claimed or overwritten by any other wallet. If you already own the name, re-registering it will permanently replace the previous deployment. For example, if you registered a voting dApp at `myvote.remixdapp.eth` and later register a token swap dApp under the same name, `myvote.remixdapp.eth` will resolve to the token swap dApp and the voting dApp will no longer be accessible at that address. ## Verifying ownership of the mini app On the next tab you will see your dApp's deployed URL ending in `.limo`. ```{note} `.limo` is a gateway service that resolves ENS domains to websites. ``` ![Deployed dApp URL ending in .limo in the setup wizard](images/mini-app/ens-name.png) Copy the URL and paste it in the App URL field on the Base Developer Portal and click "**Register**". This will take you to your app's dashboard. Go back to Remix and click the "**I've Verified on Base.dev**" button. Your dApp is now accessible on the Base app. ![Successfully deployed dApp accessible on the Base app](images/mini-app/success-screen.png) ### [Account Abstraction & Smart Accounts](https://remix-ide.readthedocs.io/en/latest/account-abstraction-7702.html) > Use Remix IDE to work with EIP-4337 and EIP-7702 account abstraction and smart account features on Ethereum. # Account Abstraction & Smart Accounts Remix has functionality for working with EIP 4337 and EIP 7702. In the Ethereum blockchain, there are two different types of accounts: - Externally Owned Accounts (EOA): which require a private key and can initiate transactions. - Smart Contract Accounts (SCA): which represents code deployed on the blockchain. Until the Pectra upgrade, externally owned accounts (EOAs) could not have code associated with them. Pectra went live on 7 May 2025 and introduced EIP-7702, which lets an EOA attach contract code for a transaction. When an EOA is linked to code (a “Connected EOA”), it can behave like a smart account and gain features such as **transaction batching**, **gas sponsorship**, and **delegated actions**. For more information, see this [overview of EIP-7702](https://eip7702.io). ## Using EIP 7702 in Remix ### EIP-7702 Template The EIP-7702 template is located in the Template Explorer. To get to the Template Explorer, click the "hamburger menu" in the File Explorer, and select "Create Using Template". ![workspace template section highlighting the simple EIP 7702 template.](images/account-abstraction-7702/a-aa-ws-template-7702.png) The Simple EIP-7702 template includes a README file that may be helpful to review as an introduction to this EIP's features. The Account Abstraction template has many examples and resources for both EIP-4337 and EIP-7702, including a very informative README file. ### Connecting an EOA account to a Smart Contract The 7702 GUI only appears in Remix when deploying to the Prague flavor of the Remix VM. ![EIP 7702 GUI.](images/account-abstraction-7702/a-aa-7702-vm-prague.png) The **Authorize Delegation** button will open a modal where you’ll input the contract’s address. But before clicking that button, first you need the contract’s address — so deploy the compiled contract and copy its address. Then click the **Authorize** button and a modal will appear: ![Authorization modal for connecting EOA to EIP 7702 contract code.](images/account-abstraction-7702/a-aa-7702-modal.png) And here, you’ll input the contract’s address. Then, when you hit Authorize, you are creating a pointer from the EOA to the Smart Contract Address. Then below the Account at the top of Deploy & Run, you’ll see a badge that contains the contract’s address. ![Delegation badge containing the connected contract address.](images/account-abstraction-7702/a-aa-connection-badge.png) And in the **Deployed contracts** section, you’ll see this: ![Deployed contracts sections showing two deployed contracts.](images/account-abstraction-7702/a-aa-deployed-7702.png) And when you open up the account (which is the new deployment), you can see that it can execute code. ## Account abstraction with EIP 4337 in Remix ### Gnosis Safe Smart Accounts in Remix There is a graphic user interface (GUI) for creating Gnosis Safe Smart Accounts. This allows gasless transactions among other features. This functionality is only available when connected to the **Gnosis chain** or **Sepolia test network**. And when connected to Sepolia, a new button will be displayed: **Create Smart Account**. ![Deploy and run section showing a Create Smart Account button.](images/account-abstraction-7702/a-aa-gsa-create1.png) Click on the Create Smart Account button and you’ll get a modal with information about Safe Smart Accounts, which will also show the address of the EOA that will be the Owner of the Smart Contract Account. After clicking “continue” in the modal, the Smart Contract Account will soon be created. ```{note} **Be Patient** It can take about 15 seconds to be created. ``` When the new account is done “cooking”, a toaster will then pop up at the bottom of Remix with the new Smart Contract Account’s address. After the toaster goes away, there won’t appear to be any visible change in Remix. #### Finding the newly created Safe Smart Account Go to the **Accounts** section of **Deploy & Run** and you will see the Smart Accounts. Select the address that begins with "[SMART]". The Owner of the account will then appear in a “badge” below it: ![Deploy and run section showing a selected smart account.](images/account-abstraction-7702/a-aa-gssa-account-select.png) #### Notice that there is no ETH in the account. Will we need to fund this account before it can be used? No! #### Making a gasless transaction Compile a contract. And deploy using the newly created [SMART] account. Your wallet will issue you a signature request. ![MetaMask signature request.](images/account-abstraction-7702/a-aa-gssa-sig-request.png) In the image above from a wallet, the Safe address and an address for “Interacting with” can be seen. When the transaction goes through, go to Remix’s terminal and click the new transaction. ![Remix terminal showing the smart contract account and its associated bundler.](images/account-abstraction-7702/a-aa-gsa-log.png) You will see both the Smart Contract Account and its associated bundler. ```{note} Following [EIP-155](https://eips.ethereum.org/EIPS/eip-155), Safe Smart Account contracts use a deterministic deployment proxy so for a contract deployed using a smart account, the msg.sender will be: 0x4e59b44847b379578588920cA78FbF26c0B4956C. ``` ### [Terminal](https://remix-ide.readthedocs.io/en/latest/terminal.html) > Use the Remix IDE terminal to run scripts, view transaction logs, and interact with the blockchain via the console. # Terminal ![Remix IDE terminal panel](images/terminal/a-terminal-and-more.png) Features, available in the terminal: - It integrates a JavaScript interpreter and the `web3` object. It enables the execution of the JavaScript script which interacts with the current context. (note that `web3` is only available if the `web provider` or `injected provider` mode is selected). - It displays important actions made while interacting with the Remix IDE (i.e. sending a new transaction). - It displays transactions that are mined in the current context. You can choose to display all transactions or only transactions that refers to the contracts Remix knows (e.g transaction created from the Remix IDE). - It allows searching for the data and clearing the logs from the terminal. - You can run scripts by inputting them at the bottom after the `>`. ### [Remixd: Access your Local Filesystem](https://remix-ide.readthedocs.io/en/latest/remixd.html) > Connect Remix IDE to your local filesystem using Remixd to edit, compile, and deploy contracts from your computer. # Remixd: Access your Local Filesystem ```{warning} **Remixd is deprecated.** For workflows that require access to your local filesystem, use {doc}`Remix Desktop ` instead. Remix Desktop has native filesystem access without the need to run a separate daemon process. Download Remix Desktop from the [releases page](https://github.com/remix-project-org/remix-project/releases). ``` [![npm version](https://badge.fury.io/js/%40remix-project%2Fremixd.svg)](https://www.npmjs.com/package/@remix-project/remixd) To give the Remix IDE (the web app) access to a folder on your computer, you need to use **Remixd** - the plugin along with **Remixd** - the cli/npm module. The **Remixd** plugin can be activated from the plugin manager or in the **File Explorer** - see the image below. The **connect to localhost** - will activate the **Remixd** plugin. ![File Explorer showing the connect to localhost option for Remixd](images/remixd/a-remixd-fe.png) Once you click **connect to localhost** or activate Remixd from the **Plugin Manager**, a modal will come up: ![Remixd connection modal for configuring the local filesystem connection](images/remixd/a-remixd-modal.png) The Remixd plugin is a **Websocket plugin** and it has no UI other than this modal dialog box - so you won't see a Remixd icon in the icon panel. Before you hit **Connect**, you need to install the [Remixd NPM module](https://www.npmjs.com/package/@remix-project/remixd) and run the **Remixd** command. The code of `remixd` is [here](https://github.com/remix-project-org/remix-project/tree/master/libs/remixd) . ## Remixd installation **remixd** is an npm module and can be globally installed using the following command: `npm install -g @remix-project/remixd` Or just install it in the directory of your choice by removing the -g flag: `npm install @remix-project/remixd` **NOTE:** When the Remixd npm module is installed, it also installs [Slither](https://github.com/crytic/slither), [solc-select](https://github.com/crytic/solc-select?tab=readme-ov-file#quickstart) and sets [solc](https://docs.soliditylang.org/en/latest/installing-solidity.html) to latest version i.e. 0.8.15 currently. **ALSO NOTE:** `Python3.6+ (pip3)` needs to already be installed on the System. (This packaging of Slither with the Remixd module is supported since Remixd v0.6.3). In case of any discrepancy, Slither can also be installed along with other dependencies using command `remixd -i slither` ### Find your version of Remixd The command: `remixd -v` or `remixd --version` will return your version number. **If this command does not work, then you have an outdated version!** ### Update to the latest Remixd Because **Remixd** creates a bridge from the browser to your local filesystem, it is important that you have the latest version of script. For users who had installed the version of Remixd from the **VERY** old npm address or for users who do not know which npm address they had installed it from, run these 2 steps: 1. uninstall the old one: **npm uninstall -g remixd** 2. install the new: **npm install -g @remix-project/remixd** **For Most Users** who know that they have a Remixd version installed from @remix-project/remixd then just run: ```shell npm install -g @remix-project/remixd ``` ### Remixd command The `remixd` command without options uses the terminal's current directory as the shared directory and the shared Remix domain will be `https://app.remix.live`, `https://remix-alpha.ethereum.org`, or `https://remix-beta.ethereum.org` The `remixd` command is:
`remixd` If you are using Remix from localhost or you are not running the command from your working directory, you'll need to use the command with flags. ### remixd options ```shell Usage: remixd [options] Establish a two-way websocket connection between the local computer and Remix IDE for a folder Options: -v, --version output the version number -u, --remix-ide URL of remix instance allowed to connect -s, --shared-folder Folder to share with Remix IDE (Default: CWD) -i, --install Module name to install locally (Supported: ["slither"]) -r, --read-only Treat shared folder as read-only (experimental) -h, --help output usage information Example: remixd -s ./shared_project -u http://localhost:8080 ``` **NOTE**: `remixd -i slither` can be used to install Slither along with its dependencies #### HTTP vs HTTPS in the `remixd` command If your browser is on `https://app.remix.live` (**secure http**) then use HTTPS in the command: ```shell remixd -s --remix-ide https://app.remix.live ``` Or if you are using **http** in the browser, then use **http** in the `remixd` command. #### Read/Write permission & Read-only mode The folder is shared using **a Websocket connection** between `Remix IDE` and `remixd`. Be sure the user executing `remixd` has read/write permission on the folder. Alternatively, there is an option to run `remixd` in read-only mode, use `--read-only` flag. ### Ports Usage `remixd` functions by making Websocket connections with Remix IDE on different ports. Ports are defined according to specific purpose. Port usage details are as: - **65520** : For `remixd` Websocket listener, to share local file system with Remix IDE. Shared folder will be loaded in the Remix IDE `File Explorers` workspace named `localhost` - **65522** : For `hardhat` Websocket listener, to enable the Hardhat Compilation using Remix IDE `Solidity Compiler` plugin, if shared folder is a Hardhat project. - **65523** : For `slither` Websocket listener, to enable the Slither Analysis using Remix IDE `Solidity Static Analysis` plugin - **65524** : For `truffle` Websocket listener, to enable the Truffle Compilation using Remix IDE `Solidity Compiler` plugin, if shared folder is a Truffle project. **Note:** Please make sure your system is secured enough and these ports are not opened nor forwarded. ```{warning} - `remixd` **provides full read and write access** to the given folder **for any application** that can access the `TCP port 65520` on your local host. - To minimize the risk, Remixd can **ONLY** bridge between your filesystem and the Remix IDE URLS - including: ``` ```text https://app.remix.live https://remix-alpha.ethereum.org https://remix-beta.ethereum.org package://a7df6d3c223593f3550b35e90d7b0b1f.mod package://6fd22d6fe5549ad4c4d8fd3ca0b7816b.mod https://ipfsgw.komputing.org ``` (the package:// URLs in the list above are for remix desktop) ### Clicking Connect on the modal Clicking on the **Connect** button on the Remixd modal (see the image above), will attempt to start a session where your browser can access the specified folder on your computer's filesystem. If you do not have `remixd` running in the background - another modal will open up and it will say: ```text Cannot connect to the remixd daemon. Please make sure you have the remixd running in the background. ``` Assuming you don't get the 2nd modal, your connection to the `remixd` daemon is successful. The shared folder will be visible in the File Explorer's workspace under **localhost**. ![File Explorer showing the shared folder under the localhost workspace](images/remixd/a-ws-localhost.png) ### Creating & deleting folders & files Clicking on the **new folder** or **new file** icon under **localhost** will create a new file or folder in the shared folder. Similarly, if you **right click** on a file or folder you can **rename** or **delete** the file. ### Closing a `remixd` session In the terminal where `remixd` is running, typing `ctrl-c` will close the session. Remix IDE will then put up a modal saying that `remixd` has stopped running. --- ## Solidity modules ### [Solidity Compiler](https://remix-ide.readthedocs.io/en/latest/compile.html) > Compile Solidity smart contracts in Remix IDE with basic and advanced configuration options including optimization and EVM version settings. # Solidity Compiler Clicking the Solidity icon in the icon panel brings you to the Solidity Compiler. The default view of the Solidity Compiler shows the basic configuration. To open the Advanced Configuration panel, click the **Advanced Configuration** button (**C. in fig. 1**). For details on advanced features - see below. ## Solidity compiler basics ### Selecting a contract to compile To select a contract to compile, choose a file in the File Explorer. Or if there are several files open, make sure the one you want to compile is the active file in the Editor. If there is not an active file in the editor or a file has not already been compiled, then the Solidity Compiler will look like this: ![Solidity Compiler panel with no file loaded](images/compile/a-sol-comp-no-file.png) ### Triggering compilation Compiling is triggered when you: - click the compile button (**D. in fig. 1 below**) - use the shortcut `control + s`. - right click on a file in the File Explorer and select the **Compile** option ![Solidity Compiler basic configuration panel](images/compile/a-sol-comp-basic.png) ### Auto Compile If the auto compile checkbox (**B. in fig. 1 above**) is checked, compilation will occur every few seconds (when the file is auto-saved) as well as when another file is selected. If a contract has a lot of dependencies, it can take a while to compile - so you use autocompilation at your discretion. ### Solidity versions & Remix functionality The compiler version is selected in the **COMPILER** dropdown list (**A. in fig. 1 above**). You can compile (and deploy) contracts with versions of Solidity **older than 0.4.12**. However, the older compilers use a legacy AST — which we no longer support. Consequently, some plugins may not work and some functionality - e.g. source highlighting in the Editor may only be partially working. ### Using the Contract selectbox Because a Solidity file can include multiple contracts and because contracts can import other contracts, multiple contracts are often compiled. **However**, only 1 contract's compilation details can be retrieved at a time. To select the desired contract, use the **Contract** selectbox (**F. in fig. 1**). Forgetting to select the right contract is a common mistake - so remember to verify that the contract you want is selected. ### Compilation Details and Publishing Using the publish button, you can upload your contract to **IPFS** or **Swarm** (only non abstract contracts can be published to Swarm). When publishing a contract that imports other contracts, the main contract and all of its imported contracts will be published - each to their own address. **Published data contains the contract's metadata and the solidity source code.** After either **Publish on IPFS** or **Publish on Swarm** is clicked a modal will pop up. This modal contains the contract's address as well as the addresses of the contracts that it imported and the address of the contract's **metadata**. When the "Compilation Details" button is clicked (**G. in fig. 1**), a modal opens displaying detailed information about the current selected contract. If you just want to get the **ABI** or the **Bytecode** - click the appropriate button see **H. in fig. 1**. ### Passive Contract Verification When you publish your metadata to IPFS and deploy your code to the mainnet or a public testnet, the contract verification service **[Sourcify](https://sourcify.dev/)**, will verify your contracts without you needing to do anything. ### Compile and Run script The Compile and Run script button (**E. in fig. 1**) is for compiling and then immediately running a script. It's a time saver so that you can write some code, automatically run script that sets state of the contract - thus allowing you to quickly understand how the code is working. Learn {ref}`more about Compile and Run `. ### Compilation Errors and Warning Compilation Errors and Warning are displayed below the contract section. At each compilation, the static analysis tab builds a report. It is important to address reported issues even if the compiler doesn't complain. ({doc}`more about static analysis `) ## Advanced compiler configurations Clicking on Advanced Compiler Configurations will open this panel (**M. in fig. 2 below**). ![Solidity Compiler advanced configuration panel](images/compile/a-sol-comp-adv.png) There is a radio button to choose whether to configure the compiler through the interface (**N. in fig 2**) or to use a JSON file for the configuration (**R. in fig 2**). ### Solidity or Yul Since the Solidity version `0.5.7`, it is possible to compile `Yul` files. Please read the ([solidity documentation about Yul](https://docs.soliditylang.org/en/latest/yul.html)) which contain some code examples. You can use the language dropdown (**O. in fig 2**) to switch the language. **This dropdown list is only available for versions greater than or equal to `0.5.7`.** ### Select an EVM version The EVM dropdown list (**P. in fig 2**) allows to compile code against a specific **Ethereum hard fork**. The `compiler default` corresponds to the default hard fork used by a specific version. To see the name of the hard fork used in the current compilation, click the "Compilation Details" button and in the `Metadata` section there will be a sub-section called **settings**. Open up the **settings** to see the EVM version's name. ### Enable optimization According to the Solidity Docs, "the optimizer tries to simplify complicated expressions, which reduces both code size and execution cost, i.e., it can reduce gas needed for contract deployment as well as for external calls made to the contract." For recent versions of Solidity, it is [recommended to enable optimization](https://soliditylang.org/blog/2020/11/04/solidity-ama-1-recap/#:~:text=Why%20do%20you%20think%20people%20are%20generally%20suspicious%20of%20the%20optimizer%2C%20and%20are%20they%20right%20to%20be%3F). To learn more about optimization, (**Q. in the fig 2**) visit the [Solidity docs on the optimizer](https://docs.soliditylang.org/en/latest/internals/optimizer.html). To the right of the **Enable optimization** checkbox is the box to input the number of Optimization runs. The default value is 200. You may ask — "What is the right number of runs for my contract?" And the Solidity docs say: > If you want the initial contract deployment to be cheaper and the later function executions to be more expensive, set it to --optimize-runs=1. If you expect many transactions and do not care for higher deployment cost and output size, set --optimize-runs to a high number. To learn more about the optimization runs, visit the [Solidity docs about Optimizer options](https://docs.soliditylang.org/en/latest/using-the-compiler.html?highlight=optimize-runs#optimizer-options). ### JSON file for Compiler configuration Selecting the radio button next to **Use configuration file** will let you set the configuration using a JSON file (**T. in fig 2**). When you switch to **compile with a config file**, a sample compiler config file is created. This file can be edited with all the available options. Clicking the config file's name will open it up in the Editor. To change the config file click the **Change** button. If you update the text box with a file name of a file that does not exist, a new file will be created containing the default file's contents. There is no error checking when using the .json file for configuration settings, so make sure your config file is correct. ### Use a Custom Solidity Compiler For those writing your own custom Solidity Compiler, you can import that by clicking the **+** button (**X. in fig 1**) to open a modal where you can input the URL of the compiler to be loaded. ### [Debugger](https://remix-ide.readthedocs.io/en/latest/debugger.html) > Step through Ethereum smart contract transactions in Remix IDE's debugger to inspect state, storage, and call stack at each step. Debugger ======== .. meta:: :description: Step through Ethereum smart contract transactions in Remix IDE's debugger to inspect state, storage, and call stack at each step. :keywords: remix debugger, smart contract debugging, transaction debugger, solidity debug The Debugger shows the contract's state while stepping through a transaction. It can be used on transactions created in Remix or by providing a transaction hash. The latter requires either that you have the contract's source code compiled with the same settings as the deployed contract, or that the contract is verified on a block explorer. Starting a Debugging Session ----------------------------- There are two ways to start a debugging session. The first is to click the **Debug** button next to a transaction in the Terminal. The Debugger will be activated and will gain focus in the **Side Panel**. .. image:: images/debugger/debug-button.png :alt: Debug button in the Remix terminal next to a transaction log entry The second is to use the Debugger directly. **Activate** the Debugger in the Plugin Manager and then click the **bug icon** in the Icon Panel. Input a transaction hash (you must also have the contract's source code open in the editor), then click the button with the Play icon to start debugging. .. video:: images/debugger/activate-debugger.mp4 :nocontrols: :autoplay: :playsinline: :muted: :loop: :width: 100% The debugger will highlight the relevant code in the Editor. If you want to go back to editing the code without the Debugger's highlights, then click the button with the Stop icon. To learn more about how to use this tool, go to the :doc:`Debugging Transactions ` page. This page will go over the Debugger's *Use generated sources* option, its navigation, and its panels. .. image:: images/debugger/debugger-overview.png :alt: Overview of the Remix Debugger interface Use generated sources ---------------------- When Solidity compiles a contract, it generates internal Yul routines (such as ABI encoding/decoding and overflow checks) that are embedded in the bytecode but are not part of your source code. By default, the debugger has no source to map these opcodes to and skips over them. When **Use generated sources** is enabled, these routines are surfaced in a separate ``.yul`` file in the editor. The debugger can then step through every opcode in the transaction without gaps, including the compiler-generated ones. This is particularly useful when auditing contracts, as it gives complete visibility into what is actually executing. .. image:: images/debugger/generated-sources.png :alt: Debugger showing a generated Yul file in the editor with Use generated sources enabled This option requires Solidity 0.7.2 or greater. The Debugger's Navigation -------------------------- The navigation buttons appear at the bottom of the editor when a debug session is active. They control how you step through the transaction's execution. .. image:: images/debugger/debugger-navigation.png :alt: Debugger navigation buttons including Step Backward, Step Back, Step Into, Step Forward, and breakpoint controls Step Backward ~~~~~~~~~~~~~ Steps back to the previous opcode without entering function calls. If the previous step is inside a function call, the debugger will skip over it and land on the opcode before the call was made. Use this when you want to move backwards through execution without descending into the internals of every function along the way. Step Back ~~~~~~~~~ Steps back to the previous opcode and will enter function calls. If the previous step was inside a function, the debugger will follow execution back into that function. Use this when you need to trace execution backwards in full detail, opcode by opcode. Step Into ~~~~~~~~~ Advances to the next opcode and will enter function calls. If the next step involves a function call, the debugger will follow execution into that function. Use this when you want full visibility into what a function is doing rather than treating it as a black box. Step Forward ~~~~~~~~~~~~ Advances to the next opcode without entering function calls. If the next step involves a function call, the debugger will skip over it and resume at the opcode after the call returns. Use this when you want to move forward through execution without stepping into every function. Previous Breakpoint ~~~~~~~~~~~~~~~~~~~ Moves the debugger back to the most recently passed breakpoint. Breakpoints are set by clicking a line number in the Editor. Use this to jump between points of interest without stepping through every opcode in between. Next Breakpoint ~~~~~~~~~~~~~~~ Moves the debugger forward to the next breakpoint ahead in the execution. If no further breakpoint exists, the debugger will not advance. Use this alongside **Previous Breakpoint** to navigate quickly through long transactions. The Debugger's Panels ---------------------- Transaction Details ~~~~~~~~~~~~~~~~~~~ The Transaction Details section is collapsible and appears at the top of the debugger panel. It shows metadata about the transaction being debugged, including: - **Status**: whether the transaction succeeded or was reverted - **Block** and **Timestamp** - **From** and **To** addresses - **Function** that was called - **Value**, **Tx Fee**, **Gas Price**, **Gas Used**, **Tx Type**, **Tx Index**, and **Tx Nonce** .. image:: images/debugger/transaction-details.png :alt: Transaction Details panel showing metadata for a debugged transaction Call Trace ~~~~~~~~~~ The Call Trace shows the full call hierarchy of the transaction. The current step is shown in the header as **Step: X / Y**, where X is the current opcode step and Y is the total number of steps in the transaction. Each entry in the trace shows the call type (e.g. **SENDER** or **CALL**), the address, and the function called. Each call entry also has three action icons that let you jump into the call, jump to its start, or jump to its end without stepping through every opcode manually. .. image:: images/debugger/call-trace.png :alt: Call Trace panel showing the sender and internal calls of a transaction State & Locals ~~~~~~~~~~~~~~ The **State & Locals** tab displays a JSON object with two keys: - ``locals``: the local variables in scope at the current execution step - ``state``: the state variables of the contract at the current execution step. Each variable is expanded to show its ``value``, ``type``, ``length`` (for arrays), ``constant``, and ``immutable`` flags. Each entry can be expanded or collapsed using the toggle next to it. .. image:: images/debugger/state-and-locals.png :alt: State and Locals tab showing locals and state variables in JSON format Stack & Memory ~~~~~~~~~~~~~~ The **Stack & Memory** tab displays a single JSON object with four keys, each expandable: - ``opcode``: the current opcode the debugger is on. Updates with each step. - ``callStack``: the call stack at the current step. It has a maximum size of 1024 elements and contains words of 256 bits. - ``stack``: the EVM operand stack at the current step. For more info about the `stack `_. - ``memory``: the EVM memory at the current step. Memory is cleared for each new message call, is linear, and can be addressed at byte level. **Reads** are limited to a width of 256 bits while **writes** can be either 8 bits or 256 bits wide. .. image:: images/debugger/stack-and-memory.png :alt: Stack and Memory tab showing low level EVM execution state Execution Trace ~~~~~~~~~~~~~~~ The Execution Trace appears below the navigation buttons. Select a call from the **Call Trace** to load the step-by-step opcode trace for that call. .. image:: images/debugger/execution-trace.png :alt: Execution trace area prompting the user to select a call from the Call Trace Additional Info --------------- The debugger is not only useful for fixing bugs. Its granular, step-by-step visibility into transaction execution makes it an excellent tool for understanding and auditing smart contracts. To learn about using the debugger, go to :doc:`Debugging Transactions `. ### [Debugging Transactions](https://remix-ide.readthedocs.io/en/latest/tutorial_debug.html) > Learn how to debug Ethereum smart contract transactions in Remix IDE by stepping through execution and inspecting state. # Debugging Transactions ```{tip} Before using this tutorial, we recommend checking out {doc}`the Debugger Tour ` for an overview of the debugger's interface and panels. ``` When developing smart contracts, things don't always behave as expected. A transaction might revert unexpectedly, a function might return the wrong value, or funds might not move the way you intended. These are the situations where Remix's debugger becomes essential. It lets you step through a transaction execution line by line, inspect local variables and state at each step, and pinpoint exactly where your contract's logic breaks down. In this tutorial, we'll walk through using the debugger with a contract that has an intentional bug, so you can see how to identify and trace a problem through the execution flow. ## Debugging a transaction made in Remix We'll use the following `Donation` contract as our example. Don't worry about understanding every detail yet — we'll be using the debugger to explore how it executes. ```Solidity // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract Donation { address owner; event fundMoved(address _to, uint _amount); modifier onlyowner { require(msg.sender == owner); _; } address[] _giver; uint[] _values; constructor() { owner = msg.sender; } function donate() public payable { addGiver(msg.value); } function moveFund(address payable _to, uint _amount) onlyowner public { uint balance = address(this).balance; uint amount = _amount; if (amount <= balance) { (bool success, ) = _to.call{value: balance}(""); if (success) { emit fundMoved(_to, amount); } else { revert(); } } else { revert(); } } function addGiver(uint _amount) internal { _giver.push(msg.sender); _values.push(_amount); } } ``` Make a new file in Remix and copy the code block above into it, compile it and deploy it on the Remix VM. ![Deploy and Run panel showing the Donation contract deployed to Remix VM](images/tutorial-debug/deploy.png) We are going to call the `Donate` function and will send 2 Ether. To do this: in the value input box put in **2** and **select Ether** as the unit. Do not leave the default unit as **gwei** or the change will be hard to detect. ![Deploy and Run panel showing the Donate function call with 2 Ether value](images/tutorial-debug/call-donate.png) Then click the `Donate` button. The 2 ETH is now held by the contract. Because we are using the `Remix VM`, the transaction confirms almost instantly. Now let's try to move 1 ETH out of the contract using `moveFund`. In the deployed instance, find the `moveFund` inputs and provide: - `_to`: a **different address from the Account dropdown that did not call `donate`**. Use an account with a clean 100 ETH balance so the balance change is clearly visible. Copy the address, then switch back to the owner account to make the call. - `_amount`: `1000000000000000000` (1 ETH in wei) ```{important} Before clicking `moveFund`, reset the **Value** field to **0**. Remix keeps the value from the previous `donate` call. Since `moveFund` is not payable, sending ETH with the call will cause it to revert immediately. ``` ![Deploy and Run panel showing the moveFund function inputs with address and amount](images/tutorial-debug/call-move-fund.png) Click **Transact**. The transaction succeeds, but check the recipient's balance by selecting their address in the **Account** dropdown. Instead of receiving 1 ETH, the entire 2 ETH contract balance was transferred. Something is wrong. Notice also that the terminal log shows `_amount: 1000000000000000000` (1 ETH) in the `fundMoved` event, matching what you requested. The event does not reveal the discrepancy because the contract emits `amount` (the requested value) rather than the amount actually sent. Without the debugger, the logs alone would not expose this bug. In the **terminal**, find the `moveFund` transaction and click its **Debug** button. ![Debug button in the terminal transaction log](images/debugger/debug-button.png) The debugger opens and highlights the current execution point in the editor. Use the **Step Forward** button to move forward through `moveFund` line by line. As you step through the function, watch the **State & Locals** panel. You'll see the local variables populate under the **locals** section as they are assigned: - `_amount`: the value you passed in: `1000000000000000000` (1 ETH in wei) - `balance`: the full contract balance: `2000000000000000000` (2 ETH in wei) - `amount`: assigned from `_amount`: `1000000000000000000` (1 ETH in wei) Continue stepping until the debugger reaches the transfer line: ```solidity (bool success, ) = _to.call{value: balance}(""); ``` At this point, look at the **locals** section of the **State & Locals** panel. The `value` being sent by the call is `2000000000000000000` (the full contract balance), not the `1000000000000000000` (1 ETH) you requested. The function is sending `balance` instead of `amount`. The check `if (amount <= balance)` used `amount` correctly, but the transfer itself did not. To fix the bug, change `balance` to `amount` in the transfer line: ```solidity (bool success, ) = _to.call{value: amount}(""); ``` This ensures only the requested amount is sent, not the entire contract balance. ## Starting a debug session from the debugger panel As an alternative to clicking **Debug** in the terminal, you can start a session directly from the Debugger panel using a transaction hash. Click the bug icon in the Icon Panel to open the Debugger. If you don't see the bug icon, activate the Debugger in the Plugin Manager. To find a transaction hash: 1. Go to a transaction in the terminal. 2. Click a line with a transaction to expand the log. 3. Copy the transaction hash. ![Terminal transaction log showing an expanded entry with a copyable transaction hash](images/tutorial-debug/tx-hash.png) Paste the hash into the Debugger and click the button with the Play icon. ![Debugger panel showing a transaction hash pasted in with the Play button](images/tutorial-debug/debug-with-hash.png) ## Using the debugger ![Debugger panel overview showing execution controls and state information](images/tutorial-debug/overview.png) The debugger allows one to see detailed information about the transaction's execution. It uses the editor to display the location in the source code where the current execution is. The navigation part contains a slider and buttons that can be used to step through the transaction execution. ### Explanation of Debugger button capabilities 1. Step Backward Steps back to the previous opcode without entering function calls. Use this to move backwards without descending into function internals. 2. Step Back Steps back to the previous opcode and **will** enter function calls. Use this to trace execution backwards in full detail. 3. Step Into Advances to the next opcode and **will** enter function calls. Use this for full visibility into what a function is doing. 4. Step Forward Advances to the next opcode without entering function calls. Use this to move forward without stepping into every function. 5. Previous Breakpoint Moves the debugger back to the most recently passed breakpoint. Breakpoints are set by clicking a line number in the Editor. 6. Next Breakpoint Moves the debugger forward to the next breakpoint ahead in the execution. ## Debugger panels ### State & Locals The **State & Locals** tab displays a JSON object with two keys: - `locals`: the local variables in scope at the current execution step - `state`: the state variables of the contract at the current execution step ### Stack & Memory The **Stack & Memory** tab displays low-level EVM execution state: - `opcode`: the current opcode, updated with each step - `callStack`: the call stack at the current step - `stack`: the EVM operand stack - `memory`: the EVM memory, cleared for each new message call ### Breakpoints Breakpoints can be added and removed by clicking on the line number in the **Editor**. When debugging, execution will jump to the first encountered breakpoint. ```{important} If you add a breakpoint to a line that declares a variable, it might be triggered twice: once for initializing the variable to zero and a second time for assigning the actual value. ``` Here's an example of this issue. If you are debugging the following contract: ```Solidity pragma solidity >=0.5.1 <0.6.0; contract ctr { function hid() public { uint p = 45; uint m; m = 89; uint l = 34; } } ``` And breakpoints are set for the lines `uint p = 45;` `m = 89;` `uint l = 34;` then clicking the **Next Breakpoint** button will stop at the following lines in the given order: > `uint p = 45;` (declaration of p) > > `uint l = 34;` (declaration of l) > > `uint p = 45;` (45 assigned to p) > > `m = 89;` (89 assigned to m) > > `uint l = 34;` (34 assigned to l) ### [Solidity Analyzers](https://remix-ide.readthedocs.io/en/latest/static_analysis.html) > Run static analysis on Solidity smart contracts in Remix IDE to detect security vulnerabilities and bad practices before deployment. # Solidity Analyzers Static code analysis is a process of debugging code by examining it without executing it. The `Solidity Analyzers` plugin combines three analysis tools to perform static analysis on Solidity smart contracts. Each tool checks for security vulnerabilities and bad development practices, among other issues. The plugin can be activated from the Remix `Plugin Manager`. ![Activating Solidity Analyzers from the Plugin Manager](images/static-analysis/a-ssa-activate.png) `Solidity Analyzers` can also be loaded by clicking on the `Solidity` icon in the featured plugins section of Remix's home tab. This button loads the following plugins: Solidity Compiler, Solidity Unit Testing, and Static Analyzers. `Solidity Analyzers` uses these tools: - [Remix Analysis](#remix-analysis): a basic analysis tool - [Solhint linter](https://github.com/protofire/solhint#rules): a Solidity linter for code and style guide validations - [Slither Static Analysis](https://crytic.github.io/slither/slither.html): a comprehensive static analysis tool ```{note} Slither can only be used on {doc}`Remix Desktop `. ``` ## How to use **A contract must be compiled before analysis can be run.** At the top of the panel, check the tools that you want to use. ![Solidity Analyzers panel with tool selection checkboxes](images/static-analysis/a-ssa-1.png) ### Errors & Warnings By default, `Solidity Analyzers` will show both errors and warnings. The combined number of errors and warnings is shown in the badge on that tool's tab. ![Error and warning badges on the analysis tool tabs](images/static-analysis/a-ssa-err-warn.png) If you check `Hide warnings`, warnings will be hidden and you'll exclusively see the errors. **NOTE:** Remix Analysis does not flag errors — it only shows warnings, so if you check `Hide warnings`, nothing will be shown in the Remix Analysis tab. ![Hide warnings checkbox in Solidity Analyzers](images/static-analysis/a-ssa-show-hide-warnings.png) #### Warnings from external libraries By default, warnings from external libraries are not shown. If you check the box `Show warnings for external libraries`, the tools will also analyze the external libraries for warnings. ## Slither To run [Slither](https://github.com/crytic/slither#slither-the-solidity-source-analyzer) with this plugin, you need to open your workspace on Remix Desktop. ## Solhint The [Solhint](https://github.com/protofire/solhint#rules) linter can be run without connecting Remix to your filesystem. ## Remix analysis Remix Analysis has 4 categories: `Security`, `Gas & Economy`, `ERC` & `Miscellaneous`. Here is the list of modules under each category along with example code which **should be avoided or used very carefully during development**: ### Category: Security - **Transaction origin: 'tx.origin' is used** `tx.origin` is useful only in very exceptional cases. If you use it for authentication, you usually want to replace it by "msg.sender", because otherwise any contract you call can act on your behalf. _Example:_ ```Solidity require(tx.origin == owner); ``` - **Check effects: Potential reentrancy bugs** Potential Violation of Checks-Effects-Interaction pattern can lead to re-entrancy vulnerability. _Example:_ ```Solidity // sending ether first msg.sender.transfer(amount); // updating state afterwards balances[msg.sender] -= amount; ``` - **Inline assembly: Inline assembly used** Use of inline assembly is advised only in rare cases. _Example:_ ```Solidity assembly { // retrieve the size of the code, this needs assembly let size := extcodesize(_addr) } ``` - **Block timestamp: Semantics may be unclear** `now` does not mean current time. `now` is an alias for `block.timestamp`. `block.timestamp` can be influenced by miners to a certain degree, be careful. _Example:_ ```Solidity // using now for date comparison if(startDate > now) isStarted = true; // using block.timestamp uint c = block.timestamp; ``` - **Low level calls: Semantics may be unclear** Use of low level `call`, `callcode` or `delegatecall` should be avoided whenever possible. `send` does not throw an exception when not successful, make sure you deal with the failure case accordingly. Use `transfer` whenever failure of the ether transfer should rollback the whole transaction. _Example:_ ```Solidity x.call('something'); x.send(1 wei); ``` - **Blockhash usage: Semantics may be unclear** `blockhash` is used to access the last 256 block hashes. A miner computes the block hash by "summing up" the information in the current block mined. By summing up the information in a clever way a miner can try to influence the outcome of a transaction in the current block. _Example:_ ```Solidity bytes32 b = blockhash(100); ``` - **Selfdestruct: Beware of caller contracts** `selfdestruct` can block calling contracts unexpectedly. Be especially careful if this contract is planned to be used by other contracts (i.e. library contracts, interactions). Selfdestruction of the callee contract can leave callers in an inoperable state. _Example:_ ```Solidity selfdestruct(address(0x123abc..)); ``` ### Category: Gas & Economy - **Gas costs: Too high gas requirement of functions** If the gas requirement of a function is higher than the block gas limit, it cannot be executed. Please avoid loops in your functions or actions that modify large areas of storage. _Example:_ ```Solidity for (uint8 proposal = 0; proposal < proposals.length; proposal++) { if (proposals[proposal].voteCount > winningVoteCount) { winningVoteCount = proposals[proposal].voteCount; winningProposal = proposal; } } ``` - **This on local calls: Invocation of local functions via 'this'** Never use `this` to call functions in the same contract, it only consumes more gas than normal local calls. _Example:_ ```Solidity contract test { function callb() public { address x; this.b(x); } function b(address a) public returns (bool) {} } ``` - **Delete on dynamic Array: Use require/assert appropriately** The `delete` operation when applied to a dynamically sized array in Solidity generates code to delete each of the elements contained. If the array is large, this operation can surpass the block gas limit and raise an OOG exception. Also nested dynamically sized objects can produce the same results. _Example:_ ```Solidity contract arr { uint[] users; function resetState() public{ delete users; } } ``` - **For loop over dynamic array: Iterations depend on dynamic array's size** Loops that do not have a fixed number of iterations, for example, loops that depend on storage values, have to be used carefully: Due to the block gas limit, transactions can only consume a certain amount of gas. The number of iterations in a loop can grow beyond the block gas limit which can stall the complete contract at a certain point. Additionally, using unbounded loops can incur a lot of avoidable gas costs. Carefully test how many items at maximum you can pass to such functions to make it successful. _Example:_ ```Solidity contract forLoopArr { uint[] array; function shiftArrItem(uint index) public returns(uint[] memory) { for (uint i = index; i < array.length; i++) { array[i] = array[i+1]; } return array; } } ``` - **Ether transfer in loop: Transferring Ether in a for/while/do-while loop** Ether payout should not be done in a loop. Due to the block gas limit, transactions can only consume a certain amount of gas. The number of iterations in a loop can grow beyond the block gas limit which can cause the complete contract to be stalled at a certain point. If required, make sure that the number of iterations is low and you trust each address involved. _Example:_ ```Solidity contract etherTransferInLoop { address payable owner; function transferInForLoop(uint index) public { for (uint i = index; i < 100; i++) { owner.transfer(i); } } function transferInWhileLoop(uint index) public { uint i = index; while (i < 100) { owner.transfer(i); i++; } } } ``` ### Category: ERC - **ERC20: 'decimals' should be 'uint8'** ERC20 contracts' `decimals` function should have `uint8` as the return type. _Example:_ ```Solidity contract EIP20 { uint public decimals = 12; } ``` ### Category: Miscellaneous - **Constant/View/Pure functions: Potentially constant/view/pure functions** It warns for the methods which potentially should be constant/view/pure but are not. _Example:_ ```Solidity function b(address a) public returns (bool) { return true; } ``` - **Similar variable names: Variable names are too similar** It warns on the usage of similar variable names. _Example:_ ```Solidity // Variables have very similar names voter and voters. function giveRightToVote(address voter) public { require(voters[voter].weight == 0); voters[voter].weight = 1; } ``` - **No return: Function with 'returns' not returning** It warns for the methods which define a return type but never explicitly return a value. _Example:_ ```Solidity function noreturn(string memory _dna) public returns (bool) { dna = _dna; } ``` - **Guard conditions: Use 'require' and 'assert' appropriately** Use `assert(x)` if you never ever want x to be false, not in any circumstance (apart from a bug in your code). Use `require(x)` if x can be false, due to e.g. invalid input or a failing external component. _Example:_ ```Solidity assert(a.balance == 0); ``` - **Result not used: The result of an operation not used** A binary operation yields a value that is not used in the following. This is often caused by confusing assignment (=) and comparison (==). _Example:_ ```Solidity c == 5; or a + b; ``` - **String Length: Bytes length != String length** Bytes and string length are not the same since strings are assumed to be UTF-8 encoded (according to the ABI definition) therefore one character is not necessarily encoded in one byte of data. _Example:_ ```Solidity function length(string memory a) public pure returns(uint) { bytes memory x = bytes(a); return x.length; } ``` - **Delete from dynamic array: 'delete' on an array leaves a gap** Using `delete` on an array leaves a gap. The length of the array remains the same. If you want to remove the empty position you need to shift items manually and update the length property. _Example:_ ```Solidity contract arr { uint[] array = [1,2,3]; function removeAtIndex() public returns (uint[] memory) { delete array[1]; return array; } } ``` - **Data Truncated: Division on int/uint values truncates the result** Division of integer values yields an integer value again. That means e.g. 10 / 100 = 0 instead of 0.1 since the result is an integer again. This does not hold for division of (only) literal values since those yield rational constants. _Example:_ ```Solidity function contribute() payable public { uint fee = msg.value * uint256(feePercentage / 100); fee = msg.value * (p2 / 100); } ``` ## Remix-analyzer `remix-analyzer` is the library which works underneath the Remix Analysis tool. `remix-analyzer` is an [NPM package](https://www.npmjs.com/package/@remix-project/remix-analyzer). It can be used as a library in a solution supporting Node.js. Find more information about this type of usage in the [remix-analyzer repository](https://github.com/ethereum/remix-project/tree/master/libs/remix-analyzer#how-to-use). --- ## Other Compilers ### [Noir Compiler](https://remix-ide.readthedocs.io/en/latest/noir.html) > Compile Noir zero-knowledge circuits in Remix IDE, generate ZK proofs, and verify them using Solidity smart contracts. Noir Compiler ============= .. meta:: :description: Compile Noir zero-knowledge circuits in Remix IDE, generate ZK proofs, and verify them using Solidity smart contracts. :keywords: noir compiler, zero knowledge, zk proof, remix ide, noir zkp Noir lets you build zero-knowledge applications without writing cryptographic circuits. This guide covers the entire workflow of using the Noir Compiler plugin in Remix IDE to compile Noir code, generate a zero-knowledge proof, and verify the generated proof using a Solidity smart contract and a js script. Creating a Noir Workspace ------------------------- To create a Noir template, click the **"Create a new workspace"** button in the top center of the screen and scroll to find the **"Noir ZKP"** template and click **"Create"**. This will create a new workspace with the necessary ``Nargo.toml`` and ``src/main.nr`` files. .. video:: ./images/noir/remixxnoir-template.mp4 :nocontrols: :autoplay: :playsinline: :muted: :loop: :width: 100% After generating the workspace, the Noir Compiler Plugin will automatically be activated and the icon will appear on the Icon Panel. Compiling Noir circuits ----------------------- Selecting the ``main.nr`` file will activate the **"Compile"** button. When you click the button the plugin starts the compilation process by zipping the project files and sending them to the compiler's backend. On the backend, the server runs ``nargo compile`` and on successful compilation creates/overwrites two files in your workspace: - ``build/program.json``: The compiled circuit artifact (ACIR/ABI). - ``Prover.toml``: A template file for providing inputs needed for proof generation. Once the compilation process is complete, a **"Compilation Artifacts"** section appears on the Noir Compiler Plugin page showing a **"View Artifact"** button. The **"Generate Proof"** button is activated. If a compilation error occurs during this process, the error message will be displayed in the feedback window below the **"Compile"** button. .. video:: ./images/noir/noir-compile.mp4 :nocontrols: :autoplay: :playsinline: :muted: :loop: :width: 100% Setting circuit inputs ---------------------- If your circuit requires inputs (private or public), you must edit the ``Prover.toml`` file before generating a proof. In the file, fill in the required input values in the ``[inputs]`` section and save the file (e.g., ``a = "1"``, ``b = "2"``). .. video:: ./images/noir/edit-inputs.mp4 :nocontrols: :autoplay: :playsinline: :muted: :loop: :width: 100% Generating zero-knowledge proofs -------------------------------- Once the inputs are set, click the **"Generate Proof"** button. Similar to the compilation process, the plugin zips the entire project, including the ``Prover.toml``, and sends it to the backend. The backend runs ``nargo execute`` to generate a witness, then uses the proving library (bb.js) to generate the proof and related artifacts. The plugin receives a zip file and extracts the following files into your workspace: - ``build/proof``: The formatted hexadecimal proof for use in UI and Solidity. - ``build/public_inputs``: The formatted JSON array of public inputs. - ``contracts/Verifier.sol``: A Solidity smart contract for verifying the proof. - ``scripts/verify.ts``: A JS script for verifying the proof in Remix. On the plugin UI, the **"Proof Artifacts"** section appears along with buttons to view the four main generated files ("View Proof", "View Public Inputs", "View Verifier.sol", "View verify.ts"). .. image:: ./images/noir/generated-proof.png :alt: Noir plugin UI showing the Proof Artifacts section with buttons to view generated proof files Verifying proofs ---------------- Once the proof is generated, you can verify it in two ways. On-Chain verification (with Solidity) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Follow the steps below to verify your proof on-chain using Solidity: 1. In the Noir plugin, click **"View Verifier.sol"** to open the verifier contract. 2. Go to the **"Solidity Compiler"** plugin in Remix, open **"Advanced Configurations"**, and check **"Enable optimization"**. Compile ``Verifier.sol``. 3. Go to the **"Deploy & Run Transactions"** plugin and deploy the ``HonkVerifier`` contract. 4. Find the ``verify`` function on the deployed contract. 5. Go back to the Noir plugin, click **"View Proof"**, and copy the entire ``0x...`` hexadecimal string. Paste it into the ``_proof`` parameter of the ``verify`` function. 6. Click **"View Public Inputs"**, copy the entire ``["0x...", ...]`` JSON array string, and paste it into the ``_publicInputs`` parameter. 7. Execute the ``verify`` transaction (call). If it returns ``true``, the verification is successful. .. video:: ./images/noir/verify-proof.mp4 :nocontrols: :autoplay: :playsinline: :muted: :loop: :width: 100% Off-Chain verification (with JS Script) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Follow the steps below to verify your proof off-chain using JavaScript: 1. In the Noir plugin, click **"View verify.ts"** to open the verification script. 2. Click the **dropdown arrow** next to the **"Run script"** button in the editor's top bar. 3. Select **"Open script configuration"** from the menu. 4. In the configuration panel or modal, set the **"Execution environment"** to **"Noir"**. 5. Close the configuration window and click the main **"Run script"** button to execute the script. .. video:: ./images/noir/verify-proof-js.mp4 :nocontrols: :autoplay: :playsinline: :muted: :loop: :width: 100% ### [Circom Compiler](https://remix-ide.readthedocs.io/en/latest/circom.html) > Write, compile, and test ZK circuits in Remix IDE using the Circom plugin to generate proofs and verify them on-chain or off-chain with no local setup required. # Circom Compiler Circom is a low-level language for writing ZK (zero-knowledge) circuits, programs that express computations as mathematical constraints, making them provable without revealing private inputs. The Remix Circom plugin brings the entire workflow into the browser, with no local setup required. This tutorial walks you through writing a circuit and verifying a proof using the **Hash Checker** template as a worked example. ## How it works Generating a ZK proof in Remix involves three broad stages: 1. **Build the circuit**: You write your computation in Circom, compile it into a format the browser can execute, and generate the constraint file that defines the rules the computation must follow. 2. **Execute the circuit**: You provide your private inputs and compute the witness, the full record of how the circuit ran with those inputs. This is what you will eventually prove, without revealing the inputs themselves. 3. **Set up keys, generate, and verify the proof**: A one-time trusted setup produces the cryptographic keys tied to your circuit. Those keys, combined with the witness, are used to generate the proof. The proof is then verified either off-chain using a verification key, or on-chain using a generated Solidity contract. Each step in this tutorial maps to one of these stages. ## Loading a Circom template To load a Circom template, click the dropdown at the center of the Top Bar, and click the revealed "**Create new Workspace**" button. On the templates modal under "Workspace Templates", scroll till you find "Circom ZKP" and select the **Hash Checker** template. ![Circom ZKP template selection in the Remix workspace templates modal](images/circom/circom-template.png) This template contains `calculate_hash.circom` and the scripts needed to complete the full proof workflow in this tutorial. After generating the workspace, the Circom plugin will automatically be activated and its icon will appear in the Icon Panel. ## Step 1: Compile the circuit The browser and the snarkjs library that powers this plugin cannot work with `.circom` files directly; they need a binary format they can actually execute. Compilation translates your circuit into a `.wasm` (WebAssembly) file that can be run in the browser to compute values later in the workflow. To compile: 1. Open `circuits/calculate_hash.circom` in the Editor so it is the active file 2. Go to the Circom plugin panel 3. Click "Compile `calculate_hash.circom`" This generates `calculate_hash.wasm` in `circuits/.bin/calculate_hash_js`. ![Circom compile button in the Circom plugin panel](images/circom/compile-circom.png) ```{note} The **Compile** button is disabled if the active file in the Editor is not a `.circom` file. ``` ## Step 2: Generate the R1CS file Your compiled circuit needs to be translated into a form the proving system can reason about mathematically. That form is the R1CS file. The proving system uses the R1CS file to check that a witness (your execution trace, generated in the next step) actually satisfies all the rules of the circuit. Without it, there is nothing to verify against. This is also the point where you choose a **proving scheme**. The proving scheme defines the mathematics used to construct and verify your proof. The R1CS file itself is scheme-agnostic, but the cryptographic keys generated from it in a later stage will be tied to whichever scheme you choose here. This tutorial uses **Groth16**. To generate the R1CS file tied to the Groth16 scheme, run the `scripts/groth16/groth16_trusted_setup.ts` script. Similarly, to tie the R1CS file to the Plonk scheme, run the `scripts/plonk/plonk_trusted_setup.ts` script. ![Setup script in the Remix editor](images/circom/setup-script.png) This script generates `calculate_hash.r1cs` in `circuits/.bin/`. Alternatively, you can click the **Run Setup** button on the Circom plugin with Groth16 selected to get the same result. ![Run Setup button on the Circom plugin](images/circom/run-setup.png) ## Step 3: Compute the witness The proof does not directly prove your private inputs. It proves that you have a valid **witness**, a complete record of every value computed during the circuit's execution: your inputs, intermediate calculations, and the final output. Because the witness captures the full execution trace, it is impossible to fake a valid one by only providing the input and output. The prover never reveals their inputs, only this trace. To compute the witness, expand the **Compute Witness** section in the plugin, enter your private input values, and click **Compute**. You can use the values below: ```json { "value1": "1", "value2": "2", "value3": "3", "value4": "4", "hash": "18821383157269793795438455681495246036402687001665670618754263018637548127333" } ``` ![Compute Witness section in the Circom plugin](images/circom/compute-witness.png) This generates `calculate_hash.wtn` in `circuits/.bin/`. ### Files Generated So Far | File | Location | Purpose | | --------------------- | ---------------- | ------------------------------------------------- | | `calculate_hash.wasm` | `circuits/.bin/` | Compiled circuit, used to compute the witness | | `calculate_hash.r1cs` | `circuits/.bin/` | Constraint rulebook, used to validate the witness | | `calculate_hash.wtn` | `circuits/.bin/` | The witness itself, the input to proof generation | These three files together represent the circuit and a single honest execution of it. The next step is generating the cryptographic keys that allow a proof to be constructed and verified. ## Generating a proof using scripts With the setup script complete, the following files are available in `zk/build/` for use in proof generation and verification: | File | Location | Purpose | | ----------------------- | ----------- | ------------------------------------------------------ | | `verification_key.json` | `zk/build/` | Used to verify proofs off-chain | | `zk_verifier.sol` | `zk/build/` | Solidity contract for on-chain verification | | `zk_setup.txt` | `zk/build/` | Stores the `zkey_final` reference for proof generation | ### Generating and Verifying the Proof With the cryptographic keys generated by `groth16_trusted_setup.ts` in Step 2, this script performs the actual proof generation and verification using Groth16. Verification takes the proof, the public signals, and the verification key, and confirms mathematically that the proof was correctly constructed from a valid witness, without running the circuit again or revealing the private inputs. To run the script, open `scripts/groth16/run_verification.ts` in the Editor and click the **Run** button in the top bar. The script picks up the witness and keys produced in the previous steps, generates the proof, and verifies it in one pass. The two core operations the script performs are: ```typescript // Generate the proof and public signals from the witness and ZKEY const { proof, publicSignals } = await snarkjs.groth16.prove(zkey_final, wtns); // Verify the proof against the verification key and public signals const verified = await snarkjs.groth16.verify( vKey, publicSignals, proof, logger, ); ``` The result appears in the Remix terminal. A successful verification prints: ``` > Checking witness correctness WITNESS IS CORRECT WITNESS CHECKING FINISHED SUCCESSFULLY ``` ## Verifying a Circom Circuit with zkVerify The verification covered so far happens in one of two places: off-chain in the browser using `verification_key.json`, or on-chain by deploying `zk_verifier.sol` and calling it from your own contract. On-chain verification is the expensive one. Validating a Groth16 proof requires elliptic curve pairing operations, and running those inside the EVM costs gas every time your contract verifies a proof. zkVerify is a third option. Instead of verifying the proof inside your own contract, you submit it to zkVerify, a network built specifically for proof verification. Because that is the one job the network is designed for, it verifies proofs faster and more cheaply than doing the same work on-chain from your contract. The Circom plugin can submit proofs to zkVerify directly, so this route is available without leaving Remix. Before you can verify this way, you need to add a zkVerify API key. Open the Settings panel, go to **Connected Services**, and find the **zkVerify (Kurier)** section. Enter your key there, choose the network you want to verify against, and click **Save**. You can get a key from the [Kurier portal](https://testnet.kurier.xyz/). ![zkVerify Kurier settings in the Connected Services panel](images/circom/add-zkverify-key.png) ```{important} Proofs submitted to zkVerify must use the **Groth16** proving scheme. If you generated your keys with the Plonk setup script in Step 2, those proofs cannot be verified this way. ``` With the key saved, go to the **Generate Proof** section of the Circom plugin panel and click **Verify on zkVerify**. This replaces the script-based route described above, so you do not need to run `scripts/groth16/run_verification.ts` to verify this way. ![Verify on zkVerify button in the Circom plugin panel](images/circom/verify-with-zkverify.png) The progress and result appear in the Remix terminal. A successful verification looks like this: ![zkVerify verification output in the Remix terminal](images/circom/zkverify-success.png) The status moves from `Submitted`, once the proof reaches the network, through `IncludedInBlock` while it is being processed, to `Finalized` when the result is settled. The **Job ID** identifies this verification on zkVerify. Once it succeeds, the button turns green and reads **Verified on zkVerify**, with the same Job ID shown beneath it. ### [Vyper Compiler](https://remix-ide.readthedocs.io/en/latest/vyper.html) > Compile Vyper smart contracts directly in Remix IDE using the Vyper compiler plugin. # Vyper Compiler Vyper contracts can be compiled in Remix with the **Vyper compiler**. ![Vyper compiler plugin panel](images/vyper/a-vyper-pi-basic.png) The plugin can be activated by going to: 1. the Plugin Manager and clicking on the Vyper compiler's activate button. 2. the File Explorer, then by right-clicking on a .vy file and selecting compile in the pop-up menu. 3. https://app.remix.live/#activate=vyper ## Compiling a Vyper file A Vyper file (with a `.vy` extension) needs to be the active file in the Editor. To get some example files, click on the **Clone Vyper examples repo** button. This will clone a repository and put it in a new Workspace. Go to the File Explorer to see the files. ## Specifying Vyper version, EVM versions, and optimize To specify the Vyper version, the EVM version, and optimize setting, add a comment at the top of your .vy code as in the examples below: ### Specify Vyper version As of 0.3.10, the recommended way to specify the version pragma is as follows: ```python #pragma version ^0.3.10 ``` ### Old way to specify Vyper version ```python # @version ^0.3.0 ``` ### EVM version ```python # @pragma evm-version paris ``` ### Optimize ```python #pragma optimize codesize ``` For optimize, the choices options are `none`, `codesize`, or `optimize`. For more info see the Vyperlang [docs](https://docs.vyperlang.org/en/stable/). ### Initiating compilation There are 4 ways to compile: 1. Click the compile button in the plugin 2. Right-click on a .vy file in the File Explorer and select `Compile for Vyper`. 3. Click on the play button at the top left of the Main Panel when a .vy file is the active tab. 4. CTRL + s when a .vy file is in the active tab of the Main Panel. ## Remote vs local compiler The default is to use the remote compiler. To see the settings open up the Advanced Settings accordion box. ### Remote Compiler The remote compilation is done using our remote containerized service that supports the official Vyper plugin for the Ape framework which ApeWorX maintains. ### Local Compiler Use {doc}`Remix Desktop ` for local compilation. It connects directly to your filesystem and runs the Ape framework in a Docker container. ## Compiler errors When there are compiler errors in the Vyper plugin, a card will appear at the bottom of the compiler. Errors appear one at a time. Fix one error, and the next one, if it exists, will appear. ![Vyper compiler showing an error card at the bottom of the panel](images/vyper/a-vyper-compiler-error.png) --- ## Unit Testing ### [Solidity Unit Testing plugin](https://remix-ide.readthedocs.io/en/latest/unittesting.html) > Write and run automated unit tests for Solidity smart contracts in Remix IDE using the built-in Solidity Unit Testing plugin. # Solidity Unit Testing plugin The Solidity Unit Testing plugin allows you to write and run automated tests for your Solidity smart contracts to verify they work correctly before deployment. It helps you generate test files, write test functions using a built-in assertion library (like `Assert.equal`, `Assert.notEqual`), and execute those tests in a separate environment to see pass/fail results. ## Activating the Solidity unit testing plugin To activate the plugin, go to the Plugin Manager, search "Unit Testing" and enable the "Solidity Unit Testing" plugin. When the plugin loads, you’ll see a screen like this: ![Unit testing page](images/unit-testing/a-unit-testing-feature.png) ## Test directory When you load the plugin, you need to specify a directory where the plugin will load and store test files. By default, it's a **tests** folder at the root of your Workspace. ```{note} The plugin will not automatically create directories. You must click "Create" to generate the specified folder structure. ``` After specifying the test folder, click the "**Create**" button. Alternatively, you can select an existing folder as the **tests** folder by typing "/" followed by the name of the folder. ![Test Directory](images/unit-testing/a-unit-testing-test-directory.png) ## Generating tests The plugin can generate generic test files that contain information about developing tests for a contract. The name of the generic test file is determined by the currently active `.sol` file on the Main Panel. If there is no active file, a generic test file named, **newFile_test.sol** will be created. Below is an example of a generic test file: ```Solidity pragma solidity >=0.4.22 <0.8.0; import "remix_tests.sol"; // this import is automatically injected by Remix. import "remix_accounts.sol"; // Import here the file to test. // File name has to end with '_test.sol', this file can contain more than one testSuite contracts contract testSuite { /// 'beforeAll' runs before all other tests /// More special functions are: 'beforeEach', 'beforeAll', 'afterEach' & 'afterAll' function beforeAll() public { // Here should instantiate tested contract Assert.equal(uint(1), uint(1), "1 should be equal to 1"); } function checkSuccess() public { // Use 'Assert' to test the contract, // See documentation: https://remix-ide.readthedocs.io/en/latest/assert_library.html Assert.equal(uint(2), uint(2), "2 should be equal to 2"); Assert.notEqual(uint(2), uint(3), "2 should not be equal to 3"); } function checkSuccess2() public pure returns (bool) { // Use the return value (true or false) to test the contract return true; } function checkFailure() public { Assert.equal(uint(1), uint(2), "1 is not equal to 2"); } /// Custom Transaction Context /// See more: https://remix-ide.readthedocs.io/en/latest/unittesting.html#customization /// #sender: account-1 /// #value: 100 function checkSenderAndValue() public payable { // account index varies 0-9, value is in wei Assert.equal(msg.sender, TestsAccounts.getAccount(1), "Invalid sender"); Assert.equal(msg.value, 100, "Invalid value"); } } ``` ## Writing tests Write sufficient unit tests to ensure that your contract works as expected under different scenarios. Remix injects a built-in **assert** library for testing. You can visit the library documentation {doc}`here `. Additionally, Remix allows the usage of special functions in the test file to make testing more structural. They are: - `beforeEach()` - Runs before each test - `beforeAll()` - Runs before all tests - `afterEach()` - Runs after each test - `afterAll()` - Runs after all tests To get started, see {ref}`this simple example `. ```{tip} You can use {doc}`RemixAI ` to generate tests for your files. ``` ## Running tests Once you are done with writing tests, select the file(s) and click on `Run` to execute the tests. The execution will run in a separate environment. After completing the execution of one file, a test summary will be shown: ![Unit testing run results showing test pass and fail summary](images/unit-testing/a-unit-testing-run-result.png) For failed tests, there will be more assertion details to analyze the issue. Clicking on failed test will highlight the relevant line of code in the editor. ## Stopping tests If you have selected multiple files to run the tests and want to stop the execution, click on `Stop` button. It will stop execution after running the tests for current file. ## Customizing tests Remix facilitates users with various types of customizations to test a contract properly. ### 1. Custom Compiler Context Solidity Unit Testing refers to the Solidity Compiler plugin for compiler configurations. Configure `Compiler`, `EVM Version`, `Enable Optimization` & `runs` in the Solidity Compiler plugin and this will be used in the Solidity Unit Testing plugin for contract compilation before running unit tests. ![Solidity Compiler plugin showing custom compiler configuration for unit testing](images/unit-testing/a-unit-testing-custom-compiler-config.png) ### 2. Custom Transaction Context For interacting with a contract's method, the main parameters of a transaction are `from` address, `value` & `gas`. Typically, a method's behaviour is tested with different values of these parameters. One can input custom values for `msg.sender` & `msg.value` of transaction using NatSpec comments, like: ```Solidity /// #sender: account-0 /// #value: 10 function checkSenderIs0AndValueis10 () public payable { Assert.equal(msg.sender, TestsAccounts.getAccount(0), "wrong sender in checkSenderIs0AndValueis10"); Assert.equal(msg.value, 10, "wrong value in checkSenderIs0AndValueis10"); } ``` Instructions to use: 1. Parameters must be defined in the method's NatSpec 2. Each parameter key should be prefixed with a hash (**#**) and end with a colon following a space (**: **) like `#sender: ` & `#value: ` 3. For now, customization is only available for parameters `sender` & `value` 4. Sender is the `from` address of a transaction which is accessed using `msg.sender` inside a contract method. It should be defined in a fixed format as '**account-**' 5. `` varies from `0-2` before remix-ide release v0.10.0 and `0-9` afterwards 6. **remix_accounts.sol** must be imported in your test file to use custom `sender` 7. Value is `value` sent along with a transaction in `wei` which is accessed using `msg.value` inside a contract method. It should be a number. Regarding `gas`, Remix estimates the required gas for each transaction internally. Still if a contract deployment fails with `Out-of-Gas` error, it tries to redeploy it by doubling the gas. Deployment failing with double gas will show error: `contract deployment failed after trying twice: The contract code couldn't be stored, please check your gas limit` Various test examples can be seen in [examples](https://remix-ide.readthedocs.io/en/latest/unittesting_examples.html) section. ## Points to remember - A test contract cannot have a method with parameters. Having one such method will show error: `Method 'methodname' can not have parameters inside a test contract` - Number of test accounts are `3` before remix-ide release v0.10.0 and `10` afterwards - While a test file which imports **remix_accounts.sol** might not compile successfully with Solidity Compiler plugin, do not worry, this will have no bearing on its success with Solidity Unit Testing plugin. ### [Command Line Interface](https://remix-ide.readthedocs.io/en/latest/unittestingAsCLI.html) > Run Solidity unit tests from the command line using the remix-tests CLI tool, the same engine powering Remix IDE's testing plugin. # Command Line Interface [![npm badge](https://badge.fury.io/js/%40remix-project%2Fremix-tests.svg)](https://www.npmjs.com/package/@remix-project/remix-tests) `remix-tests` is a tool which can be used as a CLI (Command Line Interface) solution to run the solidity unit tests. This is the same tool which works as a library underneath Remix's `Solidity Unit Testing` plugin. It is available on npm as `@remix-project/remix-tests`. ## Get started You can install it using npm: - As a dev dependency: ```shell npm install --save-dev @remix-project/remix-tests ``` - As a global npm module: ```shell npm install -g @remix-project/remix-tests ``` To confirm installation, run: ```Shell remix-tests version ``` You should get a version as output. For example `0.1.36`. ## How to use You can see all available options using `help` command. ```Shell $ remix-tests help Usage: remix-tests [options] [command] Options: -V, --version output the version number -c, --compiler set compiler version (e.g: 0.6.1, 0.7.1 etc) -e, --evm set EVM version (e.g: petersburg, istanbul etc) -o, --optimize enable/disable optimization -r, --runs set runs (e.g: 150, 250 etc) -v, --verbose set verbosity level (0 to 5) -h, --help output usage information Commands: version output the version number help output usage information ``` General structure of a command is as: ```shell $ remix-tests ``` To run all test files inside `examples` directory ```Shell $ remix-tests examples/ ``` To run single test file named `simple_storage_test.sol` inside `examples` directory ```Shell $ remix-tests examples/simple_storage_test.sol ``` ```{note} `remix-tests` will assume that name of test(s) file ends with `"_test.sol"`. e.g `simple_storage_test.sol` ``` ## Example Consider for a simple storage contract named `simple_storage.sol`: ```javascript pragma solidity >=0.4.22 <=0.8.0; contract SimpleStorage { uint public storedData; constructor() public { storedData = 100; } function set(uint x) public { storedData = x; } function get() public view returns (uint retVal) { return storedData; } } ``` Test file `simple_storage_test.sol` can be as: ```text pragma solidity >=0.4.22 <=0.8.0; import "remix_tests.sol"; // injected by remix-tests import "./simple_storage.sol"; contract MyTest { SimpleStorage foo; function beforeAll() public { foo = new SimpleStorage(); } function initialValueShouldBe100() public returns (bool) { return Assert.equal(foo.get(), 100, "initial value is not correct"); } function initialValueShouldNotBe200() public returns (bool) { return Assert.notEqual(foo.get(), 200, "initial value is not correct"); } function shouldTriggerOneFail() public { Assert.equal(uint(1), uint(2), "uint test 1 fails"); Assert.notEqual(uint(1), uint(2), "uint test 2 passes"); } function shouldTriggerOnePass() public { Assert.equal(uint(1), uint(1), "uint test 3 passes"); } } ``` Running `simple_storage_test.sol` file will output as: ```console $ remix-tests simple_storage_test.sol 👁 :: Running remix-tests - Unit testing for solidity :: 👁 'creation of library remix_tests.sol:Assert pending...' ◼ MyTest ✓ Initial value should be100 ✓ Initial value should not be200 ✘ Should trigger one fail ✓ Should trigger one pass 3 passing (0.282s) 1 failing 1) MyTest: Should trigger one fail error: uint test 1 fails expected value to be equal to: 2 returned: 1 ``` ## Custom compiler context Most of the `remix-tests` options are there to define a custom compiler context. With an extended custom compiler context, execution of above test file will go as: ```console $ remix-tests --compiler 0.7.4 --evm istanbul --optimize true --runs 300 simple_storage_test.sol 👁 :: Running remix-tests - Unit testing for solidity :: 👁 [14:03:18] info: Compiler version set to 0.7.4. Latest version is 0.8.0 [14:03:18] info: EVM set to istanbul [14:03:18] info: Optimization is enabled [14:03:18] info: Runs set to 300 Loading remote solc version v0.7.4+commit.3f05b770 ... 'creation of library remix_tests.sol:Assert pending...' ◼ MyTest ✓ Initial value should be100 ✓ Initial value should not be200 ✘ Should trigger one fail ✓ Should trigger one pass 3 passing (0.316s) 1 failing 1) MyTest: Should trigger one fail error: uint test 1 fails expected value to be equal to: 2 returned: 1 ``` Remember, custom compiler version will require internet connection to load compiler. ## As a CI solution `remix-tests` can also be used for continuous integration (CI) testing. For implementation example, see [Su Squares contract](https://github.com/su-squares/ethereum-contract/tree/e542f37d4f8f6c7b07d90a6554424268384a4186) and [Travis build](https://app.travis-ci.com/su-squares/ethereum-contract/builds/446186067) that uses `remix-tests` for continuous integration. ### [Remix Assert Library](https://remix-ide.readthedocs.io/en/latest/assert_library.html) > Reference for the Remix Assert library — assertion functions for writing Solidity unit tests in Remix IDE. # Remix Assert Library - [Remix Assert Library](#remix-assert-library) - [Assert](#assert) - [Assert.ok(value\[, message\])](#assertokvalue-message) - [Assert.equal(actual, expected\[, message\])](#assertequalactual-expected-message) - [Assert.notEqual(actual, expected\[, message\])](#assertnotequalactual-expected-message) - [Assert.greaterThan(value1, value2\[, message\])](#assertgreaterthanvalue1-value2-message) - [Assert.lesserThan(value1, value2\[, message\])](#assertlesserthanvalue1-value2-message) ## Assert ### Assert.ok(value[, message]) - `value`: \ - `message`: \ Tests if value is truthy. `message` is returned in case of failure. Examples: ```JavaScript Assert.ok(true); // OK Assert.ok(false, "it\'s false"); // error: it's false ``` ### Assert.equal(actual, expected[, message]) - `actual`: \ - `expected`: \ - `message`: \ Tests if `actual` & `expected` values are same. `message` is returned in case of failure. Examples: ```JavaScript Assert.equal(string("a"), "a"); // OK Assert.equal(uint(100), 100); // OK foo.set(200) Assert.equal(foo.get(), 200); // OK Assert.equal(foo.get(), 100, "value should be 100"); // error: value should be 100 ``` ### Assert.notEqual(actual, expected[, message]) - `actual`: \ - `expected`: \ - `message`: \ Tests if `actual` & `expected` values are not same. `message` is returned in case of failure. Examples: ```Javascript Assert.notEqual(string("a"), "b"); // OK foo.set(200) Assert.notEqual(foo.get(), 200, "value should not be 200"); // error: value should not be 200 ``` ### Assert.greaterThan(value1, value2[, message]) - `value1`: \ - `value2`: \ - `message`: \ Tests if `value1` is greater than `value2`. `message` is returned in case of failure. Examples: ```Javascript Assert.greaterThan(uint(2), uint(1)); // OK Assert.greaterThan(uint(-2), uint(1)); // OK Assert.greaterThan(int(2), int(1)); // OK Assert.greaterThan(int(-2), int(-1), "-2 is not greater than -1"); // error: -2 is not greater than -1 ``` ### Assert.lesserThan(value1, value2[, message]) - `value1`: \ - `value2`: \ - `message`: \ Tests if `value1` is lesser than `value2`. `message` is returned in case of failure. Examples: ```Javascript Assert.lesserThan(int(-2), int(-1)); // OK Assert.lesserThan(int(2), int(1), "2 is not lesser than 1"); // error: 2 is not lesser than 1 ``` ### [Testing by Example](https://remix-ide.readthedocs.io/en/latest/unittesting_examples.html) > Solidity unit testing examples for Remix IDE to help you write effective smart contract tests. # Testing by Example Here are some examples which can give you better understanding to plan your tests. **Note:** Examples in this section are intended to give you a push for development. We don't recommend to rely on them without verifying at your end. ## 1. Simple example In this example, we test setting & getting variables. Contract/Program to be tested: `Simple_storage.sol` ```Solidity pragma solidity >=0.4.22 <0.7.0; contract SimpleStorage { uint public storedData; constructor() public { storedData = 100; } function set(uint x) public { storedData = x; } function get() public view returns (uint retVal) { return storedData; } } ``` Test contract/program: `simple_storage_test.sol` ```Solidity pragma solidity >=0.4.22 <0.7.0; import "remix_tests.sol"; import "./Simple_storage.sol"; contract MyTest { SimpleStorage foo; // beforeEach works before running each test function beforeEach() public { foo = new SimpleStorage(); } /// Test if initial value is set correctly function initialValueShouldBe100() public returns (bool) { return Assert.equal(foo.get(), 100, "initial value is not correct"); } /// Test if value is set as expected function valueIsSet200() public returns (bool) { foo.set(200); return Assert.equal(foo.get(), 200, "value is not 200"); } } ``` ## 2. Testing a method involving `msg.sender` In Solidity, `msg.sender` plays a great role in access management of a smart contract methods interaction. Different `msg.sender` can help to test a contract involving multiple accounts with different roles. Here is an example for testing such case: Contract/Program to be tested: `Sender.sol` ```Solidity pragma solidity >=0.4.22 <0.7.0; contract Sender { address private owner; constructor() public { owner = msg.sender; } function updateOwner(address newOwner) public { require(msg.sender == owner, "only current owner can update owner"); owner = newOwner; } function getOwner() public view returns (address) { return owner; } } ``` Test contract/program: `Sender_test.sol` ```Solidity pragma solidity >=0.4.22 <0.7.0; import "remix_tests.sol"; // this import is automatically injected by Remix import "remix_accounts.sol"; import "./Sender.sol"; // Inherit 'Sender' contract contract SenderTest is Sender { /// Define variables referring to different accounts address acc0; address acc1; address acc2; /// Initiate accounts variable function beforeAll() public { acc0 = TestsAccounts.getAccount(0); acc1 = TestsAccounts.getAccount(1); acc2 = TestsAccounts.getAccount(2); } /// Test if initial owner is set correctly function testInitialOwner() public { // account at zero index (account-0) is default account, so current owner should be acc0 Assert.equal(getOwner(), acc0, 'owner should be acc0'); } /// Update owner first time /// This method will be called by default account(account-0) as there is no custom sender defined function updateOwnerOnce() public { // check method caller is as expected Assert.ok(msg.sender == acc0, 'caller should be default account i.e. acc0'); // update owner address to acc1 updateOwner(acc1); // check if owner is set to expected account Assert.equal(getOwner(), acc1, 'owner should be updated to acc1'); } /// Update owner again by defining custom sender /// #sender: account-1 (sender is account at index '1') function updateOwnerOnceAgain() public { // check if caller is custom and is as expected Assert.ok(msg.sender == acc1, 'caller should be custom account i.e. acc1'); // update owner address to acc2. This will be successful because acc1 is current owner & caller both updateOwner(acc2); // check if owner is set to expected account i.e. account2 Assert.equal(getOwner(), acc2, 'owner should be updated to acc2'); } } ``` ## 3. Testing method execution With Solidity, one can directly verify the changes made by a method in storage by retrieving those variables from a contract. But testing for a successful method execution takes some strategy. Well that is not entirely true, when a test is successful - it is usually obvious why it passed. However, when a test fails, it is essential to understand why it failed. To help in such cases, Solidity introduced the `try-catch` statement in version `0.6.0`. Previously, we had to use low-level calls to track down what was going on. Here is an example test file that use both **try-catch** blocks and **low level calls**: Contract/Program to be tested: `AttendanceRegister.sol` ```Solidity pragma solidity >=0.4.22 <0.7.0; contract AttendanceRegister { struct Student{ string name; uint class; } event Added(string name, uint class, uint time); mapping(uint => Student) public register; // roll number => student details function add(uint rollNumber, string memory name, uint class) public returns (uint256){ require(class > 0 && class <= 12, "Invalid class"); require(register[rollNumber].class == 0, "Roll number not available"); Student memory s = Student(name, class); register[rollNumber] = s; emit Added(name, class, now); return rollNumber; } function getStudentName(uint rollNumber) public view returns (string memory) { return register[rollNumber].name; } } ``` Test contract/program: `AttendanceRegister_test.sol` ```Solidity pragma solidity >=0.4.22 <0.7.0; import "remix_tests.sol"; // this import is automatically injected by Remix. import "./AttendanceRegister.sol"; contract AttendanceRegisterTest { AttendanceRegister ar; /// 'beforeAll' runs before all other tests function beforeAll () public { // Create an instance of contract to be tested ar = new AttendanceRegister(); } /// For solidity version greater or equal to 0.6.0, /// See: https://solidity.readthedocs.io/en/v0.6.0/control-structures.html#try-catch /// Test 'add' using try-catch function testAddSuccessUsingTryCatch() public { // This will pass try ar.add(101, 'secondStudent', 11) returns (uint256 r) { Assert.equal(r, 101, 'wrong rollNumber'); } catch Error(string memory /*reason*/) { // This is executed in case // revert was called inside getData // and a reason string was provided. Assert.ok(false, 'failed with reason'); } catch (bytes memory /*lowLevelData*/) { // This is executed in case revert() was used // or there was a failing assertion, division // by zero, etc. inside getData. Assert.ok(false, 'failed unexpected'); } } /// Test failure case of 'add' using try-catch function testAddFailureUsingTryCatch1() public { // This will revert on 'require(class > 0 && class <= 12, "Invalid class");' for class '13' try ar.add(101, 'secondStudent', 13) returns (uint256 r) { Assert.ok(false, 'method execution should fail'); } catch Error(string memory reason) { // Compare failure reason, check if it is as expected Assert.equal(reason, 'Invalid class', 'failed with unexpected reason'); } catch (bytes memory /*lowLevelData*/) { Assert.ok(false, 'failed unexpected'); } } /// Test another failure case of 'add' using try-catch function testAddFailureUsingTryCatch2() public { // This will revert on 'require(register[rollNumber].class == 0, "Roll number not available");' for rollNumber '101' try ar.add(101, 'secondStudent', 11) returns (uint256 r) { Assert.ok(false, 'method execution should fail'); } catch Error(string memory reason) { // Compare failure reason, check if it is as expected Assert.equal(reason, 'Roll number not available', 'failed with unexpected reason'); } catch (bytes memory /*lowLevelData*/) { Assert.ok(false, 'failed unexpected'); } } /// For solidity version less than 0.6.0, low level call can be used /// See: https://solidity.readthedocs.io/en/v0.6.0/units-and-global-variables.html#members-of-address-types /// Test success case of 'add' using low level call function testAddSuccessUsingCall() public { bytes memory methodSign = abi.encodeWithSignature('add(uint256,string,uint256)', 102, 'firstStudent', 10); (bool success, bytes memory data) = address(ar).call(methodSign); // 'success' stores the result in bool, this can be used to check whether method call was successful Assert.equal(success, true, 'execution should be successful'); // 'data' stores the returned data which can be decoded to get the actual result uint rollNumber = abi.decode(data, (uint256)); // check if result is as expected Assert.equal(rollNumber, 102, 'wrong rollNumber'); } /// Test failure case of 'add' using low level call function testAddFailureUsingCall() public { bytes memory methodSign = abi.encodeWithSignature('add(uint256,string,uint256)', 102, 'duplicate', 10); (bool success, bytes memory data) = address(ar).call(methodSign); // 'success' will be false if method execution is not successful Assert.equal(success, false, 'execution should be successful'); } } ``` ## 4. Testing a method involving `msg.value` In Solidity, ether can be passed along with a method call which is accessed inside contract as `msg.value`. Sometimes, multiple calculations in a method are performed based on `msg.value` which can be tested with various values using Remix's Custom transaction context. See the example: Contract/Program to be tested: `Value.sol` ```Solidity pragma solidity >=0.4.22 <0.7.0; contract Value { uint256 public tokenBalance; constructor() public { tokenBalance = 0; } function addValue() payable public { tokenBalance = tokenBalance + (msg.value/10); } function getTokenBalance() view public returns (uint256) { return tokenBalance; } } ``` Test contract/program: `Value_test.sol` ```Solidity pragma solidity >=0.4.22 <0.7.0; import "remix_tests.sol"; import "./Value.sol"; contract ValueTest{ Value v; function beforeAll() public { // create a new instance of Value contract v = new Value(); } /// Test initial balance function testInitialBalance() public { // initially token balance should be 0 Assert.equal(v.getTokenBalance(), 0, 'token balance should be 0 initially'); } /// For Solidity version greater than 0.6.1 /// Test 'addValue' execution by passing custom ether amount /// #value: 200 function addValueOnce() public payable { // check if value is same as provided through devdoc Assert.equal(msg.value, 200, 'value should be 200'); // execute 'addValue' v.addValue{gas: 40000, value: 200}(); // introduced in Solidity version 0.6.2 // As per the calculation, check the total balance Assert.equal(v.getTokenBalance(), 20, 'token balance should be 20'); } /// For Solidity version less than 0.6.2 /// Test 'addValue' execution by passing custom ether amount again using low level call /// #value: 100 function addValueAgain() public payable { Assert.equal(msg.value, 100, 'value should be 100'); bytes memory methodSign = abi.encodeWithSignature('addValue()'); (bool success, bytes memory data) = address(v).call.gas(40000).value(100)(methodSign); Assert.equal(success, true, 'execution should be successful'); Assert.equal(v.getTokenBalance(), 30, 'token balance should be 30'); } } ``` ## 5. Testing a method involving `msg.sender` and `msg.value` In the following test, we will be emulating multiple accounts making deposits in a smart contract to the same recipient and finally having the recipient withdraw the lump sum of all donations. We are also verifying that the donations match the expected amounts. This example really drives home how could you switch between different accounts, while using a set of different msg.value amounts. Contract/Program to be tested: `Donations.sol` ```Solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.4; contract donations{ struct Donation { uint id; uint amount; string donor; string message; uint timestamp; //seconds since unix start } uint amount = 0; uint id = 0; mapping(address => uint) public balances; mapping(address => Donation[]) public donationsMap; function donate(address _recipient, string memory _donor, string memory _msg) public payable { require(msg.value > 0, "The donation needs to be >0 in order for it to go through"); amount = msg.value; balances[_recipient] += amount; donationsMap[_recipient].push(Donation(id++,amount,_donor,_msg,block.timestamp)); } function withdraw() public { //whole thing by default. amount = balances[msg.sender]; balances[msg.sender] -= amount; require(amount > 0, "Your current balance is 0"); (bool success,) = msg.sender.call{value:amount}(""); if(!success){ revert(); } } function balances_getter(address _recipient) public view returns (uint){ return balances[_recipient]; } function getBalance() public view returns(uint) { return msg.sender.balance; } } ``` Test contract/program: `Donations_test.sol` ```Solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.22 <0.9.0; import "remix_tests.sol"; import "remix_accounts.sol"; import "../donations.sol"; contract testSuite is donations { address acc0 = TestsAccounts.getAccount(0); //owner by default address acc1 = TestsAccounts.getAccount(1); address acc2 = TestsAccounts.getAccount(2); address acc3 = TestsAccounts.getAccount(3); address recipient = TestsAccounts.getAccount(4); //recipient /// #value: 1000000000000000000 /// #sender: account-1 function donateAcc1AndCheckBalance() public payable{ Assert.equal(msg.value, 1000000000000000000, 'value should be 1 Eth'); donate(recipient, "Mario", "Are you a bird?"); Assert.equal(balances_getter(recipient), 1000000000000000000, 'balances should be 1 Eth'); } /// #value: 1000000000000000000 /// #sender: account-2 function donateAcc2AndCheckBalance() public payable{ Assert.equal(msg.value, 1000000000000000000, 'value should be 1 Eth'); donate(recipient, "Tom", "Are you a plane?"); Assert.equal(balances_getter(recipient), 2000000000000000000, 'balances should be 2 Eth'); } /// #value: 2000000000000000000 /// #sender: account-3 function donateAcc3AndCheckBalance() public payable{ Assert.equal(msg.value, 2000000000000000000, 'value should be 1 Eth'); donate(recipient, "Maria", "Are you a car?"); Assert.equal(balances_getter(recipient), 4000000000000000000, 'balances should be 4 Eth'); } /// #sender: account-4 function withdrawDonations() public payable{ uint initialBal = getBalance(); withdraw(); uint finalBal = getBalance(); Assert.equal(finalBal-initialBal, 4000000000000000000, 'balances should be 4 Eth'); } } ``` ### [Testing using Chai & Mocha](https://remix-ide.readthedocs.io/en/latest/testing_using_Chai_&_Mocha.html) > Test JavaScript and TypeScript scripts in Remix IDE using the Chai assertion library and Mocha test framework. # Testing using Chai & Mocha _(Supported since Remix IDE v0.22.0)_ Remix supports testing of your files in JavaScript using assertion library [Chai](https://www.chaijs.com/) & test framework [Mocha](https://mochajs.org/) _Chai is a BDD / TDD assertion library for node and the browser that can be delightfully paired with any JavaScript testing framework._ _Mocha is a feature-rich JavaScript test framework running on Node.js and in the browser, making asynchronous testing simple and fun._ ## Write tests Create a js file in your project workspace. Better to create it inside `scripts` folder. Let's name it `sample.test.js`. Write your tests in the file. Here is a sample: ```JavaScript const { expect } = require("chai"); describe("Sample", function () { it("Sample tests with mocha and chai", async function () { var foo = 'bar' var beverages = { tea: [ 'chai', 'matcha', 'oolong' ] }; expect(foo).to.be.a('string'); expect(foo).to.equal('bar'); expect(foo).to.have.lengthOf(3); expect(beverages).to.have.property('tea').with.lengthOf(3); }); }); ``` ## Run tests Once done with writing the tests, right click on file name in `File Explorers` plugin. It will show some options along with option to `Run`. This `Run` option is used to run the JavaScript scripts. ![File Explorer context menu showing the Run option for a test file](images/chai-mocha/run_with_mocha_option.png) Click on `Run`, tests will be executed and result will be shown on Terminal. ![Terminal showing Mocha test execution results](images/chai-mocha/run_with_mocha_result.png) ## Test a contract Similarly unit tests can be written to test the functionality of a smart contract. An example to test default `1_Storage.sol` contract can be as: ```JavaScript const { expect } = require("chai"); describe("Storage", function () { it("test initial value", async function () { // Make sure contract is compiled and artifacts are generated const metadata = JSON.parse(await remix.call('fileManager', 'getFile', 'contracts/artifacts/Storage.json')) const signer = (new ethers.providers.Web3Provider(web3Provider)).getSigner() let Storage = new ethers.ContractFactory(metadata.abi, metadata.data.bytecode.object, signer); let storage = await Storage.deploy(); console.log('storage contract Address: ' + storage.address); await storage.deployed() expect((await storage.retrieve()).toNumber()).to.equal(0); }); it("test updating and retrieving updated value", async function () { const metadata = JSON.parse(await remix.call('fileManager', 'getFile', 'contracts/artifacts/Storage.json')) const signer = (new ethers.providers.Web3Provider(web3Provider)).getSigner() let Storage = new ethers.ContractFactory(metadata.abi, metadata.data.bytecode.object, signer); let storage = await Storage.deploy(); await storage.deployed() const setValue = await storage.store(56); await setValue.wait(); expect((await storage.retrieve()).toNumber()).to.equal(56); }); it("fail test updating and retrieving updated value", async function () { const metadata = JSON.parse(await remix.call('fileManager', 'getFile', 'contracts/artifacts/Storage.json')) const signer = (new ethers.providers.Web3Provider(web3Provider)).getSigner() let Storage = new ethers.ContractFactory(metadata.abi, metadata.data.bytecode.object, signer); let storage = await Storage.deploy(); await storage.deployed() const setValue = await storage.store(56); await setValue.wait(); expect((await storage.retrieve()).toNumber()).to.equal(55); }); }); ``` Result will be as: ![Terminal showing Mocha test results for the Storage contract](images/chai-mocha/run_with_mocha_storage_test.png) ## Debugging a test transaction To debug a transaction in one of the tests, print the transaction hash and input that in the [Remix Debugger plugin](https://remix-ide.readthedocs.io/en/latest/tutorial_debug.html). ![Terminal showing a printed transaction hash from a Mocha test](images/chai-mocha/run_with_mocha_print_hash.png) ## Hardhat-ethers support Remix also supports methods of [hardhat-ethers](https://v2.hardhat.org/hardhat-runner/plugins/nomicfoundation-hardhat-ethers) plugin of Hardhat framework. Available methods under this plugin are: ```TypeScript interface Libraries { [libraryName: string]: string; } interface FactoryOptions { signer?: ethers.Signer; libraries?: Libraries; } function getContractFactory(name: string, signer?: ethers.Signer): Promise; function getContractFactory(name: string, factoryOptions: FactoryOptions): Promise; function getContractFactory(abi: any[], bytecode: ethers.utils.BytesLike, signer?: ethers.Signer): Promise; function getContractAt(name: string, address: string, signer?: ethers.Signer): Promise; function getContractAt(abi: any[], address: string, signer?: ethers.Signer): Promise; function getSigners() => Promise; function getSigner(address: string) => Promise; function getContractFactoryFromArtifact(artifact: Artifact, signer?: ethers.Signer): Promise; function getContractFactoryFromArtifact(artifact: Artifact, factoryOptions: FactoryOptions): Promise; function getContractAtFromArtifact(artifact: Artifact, address: string, signer?: ethers.Signer): Promise; ``` With this, one can run the tests for a hardhat project easily using Remix. Example to test `Storage` contract with this plugin methods can be as: ```JavaScript const { expect } = require("chai"); const { ethers } = require("hardhat"); describe("Storage", function () { it("test initial value", async function () { const Storage = await ethers.getContractFactory("Storage"); const storage = await Storage.deploy(); await storage.deployed(); console.log('storage deployed at:'+ storage.address) expect((await storage.retrieve()).toNumber()).to.equal(0); }); it("test updating and retrieving updated value", async function () { const Storage = await ethers.getContractFactory("Storage"); const storage = await Storage.deploy(); await storage.deployed(); const storage2 = await ethers.getContractAt("Storage", storage.address); const setValue = await storage2.store(56); await setValue.wait(); expect((await storage2.retrieve()).toNumber()).to.equal(56); }); }); ``` Result will be as: ![Terminal showing Mocha test results using hardhat-ethers](images/chai-mocha/run_with_mocha_hhethers.png) --- ## External Tool Integrations ### [Hardhat](https://remix-ide.readthedocs.io/en/latest/hardhat.html) > Integrate Remix IDE with a Hardhat project using Remix Desktop to compile and debug contracts with the Hardhat provider. # Hardhat Remix IDE has built-in support for [Hardhat](https://hardhat.org/), an Ethereum development environment for compiling, deploying, testing, and debugging Solidity smart contracts. With Remix Desktop, you can connect to a local Hardhat project, giving you access to Hardhat compilation and the Hardhat Provider for deploying to a local node. ## Enable Hardhat compilation ### Prerequisites To use Hardhat compilation with Remix Desktop efficiently: 1. **Hardhat** should be installed locally on the system [https://hardhat.org/docs/getting-started](https://hardhat.org/docs/getting-started). 2. The folder should be a Hardhat project containing `hardhat.config.js` or `hardhat.config.ts`. ### How to Use When you open a Hardhat project on Remix Desktop, there will be an extra checkbox in the `Solidity Compiler` plugin with the label `Enable Hardhat Compilation`. ![Enable Hardhat Compilation checkbox in the Solidity Compiler plugin](images/hardhat/a-hardhat-compilation.png) Check the `Enable Hardhat Compilation` box to run the compilation for Hardhat along with Remix using the compiler configuration in the `Solidity Compiler` plugin. On clicking the `Compile` button, a `remix-compiler.config.js` file will be created in the project root which stores the compiler configuration set in Remix's `Solidity Compiler` plugin. It is passed to Hardhat for compilation. The result of the compilation will be shown in the Remix IDE terminal. ![Successful Hardhat compilation output in Remix IDE terminal](images/hardhat/a-hardhat-compilation-success.png) ## Hardhat provider ```{note} In Hardhat, contracts are deployed by starting a local node. Read more about it in the [Hardhat documentation](https://hardhat.org/docs/getting-started). ``` **Hardhat Provider** enables deployment to the Hardhat localhost network. This can be chosen in the **ENVIRONMENT** dropdown of the **Deploy and Run** plugin. ![Hardhat Provider option in the Environment dropdown](images/hardhat/a-hardhat-provider-dropdown.png) As soon as you select `Hardhat Provider`, a modal is opened asking for the `Hardhat JSON-RPC Endpoint`. ![Modal prompting for the Hardhat JSON-RPC Endpoint](images/hardhat/a-hardhat-provider-modal.png) If the Hardhat node is running with default options, the default endpoint value in the modal will not need any change. If the Hardhat node host and port are different, the JSON-RPC endpoint should be updated in the modal text box. Once the correct endpoint is filled in the modal, click `OK` and the accounts from the Hardhat node will be loaded in the `ACCOUNT` section. The network id will also be shown. ![Remix IDE connected to Hardhat Provider showing loaded accounts](images/hardhat/a-hardhat-provider-connected.png) Now, you can start deploying the contract from Remix IDE to the Hardhat local node as usual. ## Using `console.log` in Remix IDE Remix IDE supports the Hardhat console library while using `Remix VM`. It can be used while making a transaction or running unit tests. ### Using `console.log` To try it out, you need to put an import statement and use `console.log` to print the value as shown in the image. ![Solidity file with console.log import and usage](images/hardhat/hardhat-console-file.png) Further, once you execute the `changeOwner` method, the value from the console statement will be shown in the Remix terminal after the transaction details: ![Remix terminal showing console.log output after transaction](images/hardhat/hardhat-tx-terminal.png) ### Solidity Unit Testing Similarly, `console.log` can be used while running unit tests using the Remix Solidity Unit Testing plugin. ![Solidity unit test file using console.log](images/hardhat/hardhat-utesting-file.png) For tests that include a logging message, the output will display in the Remix Terminal corresponding to the test name. ![Remix terminal showing console.log output from unit tests](images/hardhat/hardhat-utesting-terminal.png) ### [Slither](https://remix-ide.readthedocs.io/en/latest/slither.html) > Run Slither static analysis on Solidity contracts in Remix IDE to detect security vulnerabilities and get detailed contract information. # Slither [Slither](https://github.com/crytic/slither) is a static analysis framework for Solidity. It runs a suite of vulnerability detectors and provides information about contract details. ## Prerequisites To use Slither analysis with Remix IDE efficiently, the following tools should be installed locally on your system: 1. **Slither:** [Installing Slither](https://crytic.github.io/slither/slither.html#how-to-install) 2. **Solc:** [Installing Solidity](https://docs.soliditylang.org/en/latest/installing-solidity.html) 3. **Solc-select:** [Solc Quickstart](https://github.com/crytic/solc-select#quickstart) ## How to use Slither analysis is available in Remix Desktop through the `Solidity Static Analysis` plugin and on Remix Web through RemixAI. ### Remix Web On Remix Web, Slither analysis is available through RemixAI. Open the RemixAI Assistant, describe your contract, and ask it to run a Slither analysis. Here's an example prompt: ``` Run a Slither analysis on MyToken.sol and list any security vulnerabilities or warnings. ``` The `Slither` checkbox in the Solidity Static Analysis plugin will be greyed out on Remix Web. ### Remix Desktop If you load a local project in Remix Desktop, there will be an extra checkbox shown in `Solidity Static Analysis` plugin with the label `Slither` (On Remix Web, this option will be greyed out). ![Slither checkbox in the Solidity Static Analysis plugin](images/slither/a-slither-analysis.png) The Slither Analysis report will be displayed on the Slither tab of the Solidity Static Analysis plugin, next to the Remix analysis report for better readability. ![Slither analysis report in the Solidity Static Analysis plugin](images/slither/a-slither-analysis-success.png) The result of the analysis will be shown in the Remix IDE terminal. ![Slither analysis result in the Remix IDE terminal](images/slither/a-slither-analysis-success-terminal.png) To only run Slither Analysis, deselect the `Remix` and `Solhint` checkboxes and click on "Analyze". Now it will show only the Slither Analysis report. By default, it doesn't show the warnings for external libraries like remix-tests.sol, hardhat/console.sol etc. To have a look at them, check the box with label `Show warnings for external libraries`. ![Slither analysis report showing warnings for external libraries](images/slither/a-slither-analysis-ext-libs.png) ### More Details Analysis for Slither is run using the version set in the `Solidity Compiler` plugin. Slither is a CLI tool and requires `solc` to run. Before running the analysis, the Slither Websocket plugin checks if the current local `solc` version matches the version set in Remix IDE. If the versions differ, the Slither Websocket plugin will use `solc-select` to switch the local `solc` version to match. For example, if the local `solc` version is 0.8.4 and Remix IDE is set to 0.8.6, the logs will show the version switch. ![Slither Websocket plugin log showing solc version selection](images/slither/a-slither-analysis-select.png) After a successful analysis run: ![Slither analysis success after solc version switch](images/slither/a-slither-analysis-select-success.png) ### [Foundry](https://remix-ide.readthedocs.io/en/latest/foundry.html) > Connect Remix IDE to Foundry Anvil, use Foundry remappings, and deploy contracts to a local Anvil node. # Foundry [Foundry](https://www.getfoundry.sh/) is an Ethereum development toolkit for compiling, testing, and deploying Solidity smart contracts. With **Remix Desktop**, you can connect to a local Foundry project folder and deploy to a local Anvil chain. These features are not available on the online IDE, you must use {doc}`Remix Desktop ` to access them. ## Deploying to Anvil To deploy to Anvil, Foundry's local test chain, Anvil needs to be installed and running on your computer. ```{note} You can install Anvil by following the instructions in [this guide](https://www.getfoundry.sh/introduction/installation). ``` Then, start `Anvil` by running the command below in the Remix Desktop terminal: ```shell anvil ``` ![Running the anvil command in the Remix Desktop terminal](images/foundry/anvil-command.png) Then select **Foundry Provider** in the **Environments** section of the **Deploy & Run** module. ![Foundry Provider option in the Environment dropdown](images/foundry/a-foundry-provider.png) As soon as you select **Foundry Provider**, a modal is opened asking for the **Anvil JSON-RPC Endpoint**. ![Modal prompting for the Anvil JSON-RPC Endpoint](images/foundry/a-foundry-provider-modal.png) If the Anvil node is running with default options, the default endpoint value in the modal doesn't need to be changed. If the Anvil node host and port are different, the JSON-RPC endpoint should be updated in the modal's text box. Once the correct endpoint is filled in the modal, click **OK** and the accounts from the Anvil node will be loaded in the **ACCOUNT** section. The network id will also be shown. ![Remix IDE connected to Foundry Provider showing loaded accounts](images/foundry/a-foundry-provider-connected.png) Now, you can start deploying the contract from Remix IDE to the local Anvil node as usual. ## Foundry remappings Foundry manages dependencies using git submodules and can remap dependencies to make them easier to import. So imports defined by remappings can have compilation errors on Remix IDE. To support such compilation, Remix suggests running [compilation using a compiler config file](https://remix-ide.readthedocs.io/en/latest/compile.html#json-file-for-compiler-configuration). Remix adds some default Forge remappings in the compiler config file when a Foundry project is loaded on Remix Desktop. ![Compiler config file with default Forge remappings](images/foundry/a-foundry-cc.png) Further, more remappings can be added manually if required. --- ## Guides ### [Creating and Deploying a Contract](https://remix-ide.readthedocs.io/en/latest/create_deploy.html) > Step-by-step guide to creating a new Solidity file and deploying your first smart contract in Remix IDE. # Creating and Deploying a Contract Let's go through a basic workflow: - create a new file - code a contract in the file - compile the contract - deploy it to the local simulated blockchain (Remix VM) - interact with the deployed contract's functions ## Creating a new file ![File Explorer showing the new file icon](images/file-explorer/a-file-explorer-new-file2.png) In the File Explorer, create a new file by clicking on the new file icon, and name it. The `.sol` is default extension in Remix, if a file is named without an extension, `.sol` will appended. **NOTE:** For information about templates or workspaces, see the {doc}`File Explorer docs `. In the editor, paste in the following contract into the empty file: ```Solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.18; contract testContract { uint256 value; constructor (uint256 _p) { value = _p; } function setP(uint256 _n) payable public { value = _n; } function setNP(uint256 _n) public { value = _n; } function get () view public returns (uint256) { return value; } } ``` When pasting in code, make sure you understand it before deploying or interacting with it. Don't get scammed! ## Compile the contract With the contract above as the active tab in the Editor, compile the contract. A quick way to compile is to hit **ctrl + s**. You can also compile by going to the Solidity Compiler and clicking the compile button, or by right clicking a file in the File Explorer, or by clicking the play button at the top of the Editor. **For More Info** see the docs on the {doc}`Solidity Compiler `. ## Deploy the contract Go to the **Deploy & Run Transactions** plugin. At the top of this plugin is the Environment selectbox. Here you can choose where you want to deploy your contract. There are many choices. For more info about these options see {ref}`this section ` of the docs. For a brief synopsis: - **Injected Provider** is used to connect Remix with a Browser Wallet (e.g. MetaMask) which is generally for deploying to a public network. - **Remix VM** is a test blockchain in the browser. There are quite a few "flavors" of the Remix VM. Each "flavor" is associated with a different hard fork with the name in parentheses - e.g. Remix VM (Shanghai) or for the choice of a chain to fork into the Remix VM. - The **Remix VM** is convenient because it is a blockchain that runs in the browser and nothing else needs to be installed in order to run it. - **Dev** is for connecting Remix to a local chain running on your computer. - **L2** is for connecting Remix to Optimism or Arbitrum via a browser wallet. Its essentially the same as Injected Provider, but it sets the wallet with the configuration of the specified L2. (For details see [Running transactions](https://remix-ide.readthedocs.io/en/latest/run.html)) ## Select the top Remix VM environment Choose the top first Remix VM in the dropdown list. The Remix VM comes with 10 accounts funded with 100 ether. **NOTE:** When you are in the **Remix VM** and you reload the browser - the **Remix VM** will also restart to its fresh & default state. For a more realistic testing environment, use a public testnet. ![Deploy and Run panel showing Remix VM environment with funded accounts](images/create_deploy/a-run-remix-vm-accounts.png) ## Deploying a contract ![Deploy and Run panel showing testContract deployment with constructor parameter input](images/create_deploy/a-run-testContract.png) The constructor of `testContract` needs a parameter of the type `uint256`. Input a uint256 and click on `Deploy`. The transaction is created which deploys the instance of `testContract` . In a more realistic blockchain, you would have to approve the transaction and then wait for the transaction to be mined. However, because we are using the `Remix VM`, the execution is immediate. The terminal will give information about the transaction. The newly created instance is displayed in the **Deployed Contracts** section. ![Deployed Contracts section showing a testContract instance](images/create_deploy/a-remix-vm-inst ance.png) ## Interacting with the deployed instance Clicking on the caret to the left of the instance of `TESTCONTRACT` will expand it so its functions are visible. This new instance contains the 3 functions (`setP`, `setPN`, `get`). Clicking on `setP` or `setPN` will create a new transaction. `setP` is a `payable` function (payable functions have red buttons). With a payable function, value (ETH) can be sent to the contract. The amount of ETH is chosen in the VALUE input field and the unit of ETH is selected in the box to the right. ![Deployed contract instance showing the payable setP function with value input field](images/create_deploy/a-remix-vm-value.png) `setPN` is not payable (an orange button - depending on the theme). It is not possible to send value (Ether) to this function. `get` is a **view function** (a blue button - depending on the theme). It doesn't execute a transaction because a `get` does not modify the state (it is only returning the value of the variable `value`). The value that gets returned appears just below the `get` button. ![Deployed contract instance showing the get view function with its returned value](images/create_deploy/a-remix-vm-view.png) ### [Subgraphs in Remix](https://remix-ide.readthedocs.io/en/latest/subgraph.html) > Query subgraphs from The Graph directly in Remix IDE, and scaffold a dApp from your query results. # Subgraphs in Remix Remix has functionality for querying [The Graph](https://thegraph.com)'s Subgraphs directly from the Editor, and for scaffolding a dApp from the results of a query. RemixAI can also help you find an existing Subgraph and form your queries. ## Configuring your Graph API key Before you can run a query, you need to add your Graph API key to Remix. Go to the **Connected Services** section of the **Settings** plugin and paste in your API key. ![Graph API key field in Connected Services settings](images/subgraph/thegraph-api-key.png) ## Querying a Subgraph When a file in the Editor has a `.subgraph` extension, the **Compile** button becomes the **Run Query** button. Running the query displays the results on the right side of the Editor. ![Run Query button on a Subgraph file](images/subgraph/subgraph-query.png) ### Try querying a Subgraph from Remix Go to the [Subgraph Explorer](https://thegraph.com/explorer) and search for a Subgraph, then paste its query into a file in Remix with a `.subgraph` extension. Grab the query's endpoint URL and add it to the top of the file as a comment, like this: ```text # @endpoint: https://gateway.thegraph.com/api/[]/subgraphs/id/5XqPmWe6gjyrJtFn9cLy237i4cWw2j9HcUJEXsP5qGtH ``` Leave the square brackets after `/api/` empty, as shown above, then run the query. ![Subgraph query results panel](images/subgraph/query.png) ## RemixAI and the Graph You can ask RemixAI to create a Subgraph query for you. For the best results, name the specific contract or protocol you're targeting, the network it's deployed on, and the data you want back (event type, time range, sort order, and so on). The more specific the request, the less editing you'll need to do to the generated `.subgraph` file. Here's an example prompt: ```text Create a Subgraph query that returns the 10 most recent Transfer events for the USDC contract on Ethereum mainnet, sorted by timestamp. ``` You can also ask RemixAI whether a Subgraph already exists for a given contract or protocol, and ask it to help you form your queries against that Subgraph. As above, naming the protocol, network, and the metric or data you're after will get you a more usable query on the first try. Here's an example prompt: ```text Does a Subgraph exist for Uniswap v3 on Ethereum mainnet? If so, help me write a query for the top 5 pools by trading volume over the last 24 hours. ``` ## Subgraph queries for local Subgraphs For local Subgraph development, use [Remix Desktop](https://remix.live/desktop). Because it's a native app, you have access to your machine's terminal, so you can install the Graph CLI and index a Subgraph locally. This lets you run queries against data on a local chain, usually Hardhat or Anvil, before your Subgraph is deployed anywhere. Once your local Subgraph is indexing, every other flow described on this page (writing `.subgraph` files, setting the endpoint, running queries, and asking RemixAI for help) works exactly the same as it does on Remix Web. ## Making a dApp that queries a Subgraph In the File Explorer, right-click a `.subgraph` file and select **Create dApp from Subgraph Query**. Answer RemixAI's questions, and {doc}`QuickDApp ` will launch. From there you can deploy your dApp to IPFS and set up a URL for it. ![Create dApp from Subgraph Query context menu option](images/subgraph/create-dapp.png) ### [Importing & Loading Source Files in Solidity](https://remix-ide.readthedocs.io/en/latest/import.html) > Import external libraries and dependencies into your Solidity contracts in Remix IDE from npm, GitHub, IPFS, or local files. # Importing & Loading Source Files in Solidity There are two main reasons for loading external files into Remix: - **to import a library or dependency** (for files you will NOT be editing) - **to load some files for manipulation and editing** (for files you might want to edit) ## Importing a library or dependency When importing from npm, or a URL (like GitHub, an IPFS gateway, or a Swarm gateway) you do not need to do anything more than use the `import` statement in your contract. The dependencies do not need to be "preloaded" into the File Explorer's current Workspace before the contract is compiled. Files loaded from the import statement are placed in the **File Explorer's** current Workspace's `.deps` folder. Under the hood, Remix checks to see if the files are already loaded in the **.deps** directory. If not, it gets them via unpkg if it is an npm lib. Here are some example import statements: ### Import from npm Use an npm package name directly in the import path. Remix resolves the package automatically via unpkg. ```Solidity import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; ``` ```Solidity import "@openzeppelin/contracts@4.2.0/token/ERC20/ERC20.sol"; ``` ```{note} In the scoped-package example above, **@openzeppelin** is the name of the npm library. In the following example the library's name does not begin with an @ - but Remix will go and check npm for a library of that name. ``` ```Solidity import "solidity-linked-list/contracts/StructuredLinkedList.sol"; ``` ### Import from a GitHub URL Paste a full GitHub URL to import a file directly from a public repository. ```Solidity import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v2.5.0/contracts/math/SafeMath.sol"; ``` You should specify the release tag (where available), otherwise you will get the latest code in the main branch. For OpenZeppelin Contracts you should only use code published in an official release, the example above imports from OpenZeppelin Contracts v2.5.0. ### Import from Swarm Use a `bzz-raw://` URI to import a file stored on the Swarm decentralized storage network. ```Solidity import 'bzz-raw://5766400e5d6d822f2029b827331b354c41e0b61f73440851dd0d06f603dd91e5'; ``` ### Import from IPFS Use an `ipfs://` URI to import a file stored on the IPFS network. ```Solidity import 'ipfs://Qmdyq9ZmWcaryd1mgGZ4PttRNctLGUSAMpPqufsk6uRMKh'; ``` ### Importing a local file not in .deps To import a file NOT in the **.deps** folder, use a relative path (**./**). For example: ```Solidity import "./myLovelyLovelyLib.sol"; ``` ```{warning} Imports cannot reference files in a different Workspace. Both the contract and its dependencies must be in the same Workspace. ``` ### Importing a file from your computer's filesystem This method uses **Remix Desktop**, which has direct access to your computer's filesystem. Open the folder you want to work with from within the Remix Desktop app and its files will appear in the File Explorer. ### More about the import keyword For a detailed explanation of the `import` keyword see the [Solidity documentation](https://docs.soliditylang.org/en/latest/layout-of-source-files.html?highlight=import#importing-other-source-files) ## Importing files for manipulation When importing from the home tab widgets or with a remix command in the console, the files are placed in the **root of the current Workspace** inside a folder that shows their source - eg GitHub or gists. ### Import buttons on the Remix home tab The Gist, GitHub, Swarm, IPFS, & HTTPS buttons are to assist in getting files into Remix so you can explore. ![Remix home tab showing import buttons for Gist, GitHub, Swarm, IPFS, and HTTPS](images/import/a-import-from.png) Clicking on any of the Import buttons will bring up a modal like this one: ![Import modal for entering a URL or ID](images/import/a-gist-modal.png) No need to wrap the URL or ID in quotes. ### Loading with a remix command in the console The 2 remix commands for loading are: - remix.loadurl(url) - remix.loadgist(id) ```js remix.loadurl('https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v2.5.0/contracts/math/SafeMath.sol') ``` ```js remix.loadgist('5362adf2000afa4cbdd2c6d239e06bf5') ``` ### Accessing files loaded from the Home tab or from a remix command When you load from GitHub, a folder named `github` is created in the root of your current workspace. To import a file from the `github` folder, you would use a command like this: ```Solidity import "github/OpenZeppelin/openzeppelin-contracts/contracts/math/SafeMath.sol"; ``` Notice that this import statement doesn't include the version information that was in the remix.load(url) command. So it is recommended that you use the methods described at the top of this page for importing dependencies that you are not intending to edit. Assume the .sol file that contained the import statement above is in the contracts folder. Notice that this import statement didn't need to traverse back to the `github` folder with a relative path like: `../github`. ### [Contract Verification](https://remix-ide.readthedocs.io/en/latest/contract_verification.html) > Verify deployed smart contracts on Sourcify, Etherscan, Blockscout, and Routescan directly from Remix IDE. # Contract Verification Remix IDE includes a plugin for contract verification called "**Contract Verification**", available in the Plugin Manager. This plugin supports contract verification on Sourcify, Etherscan, Blockscout, and Routescan. The plugin has 4 tabs: the **Verify** tab, the **Receipts** tab, the **Lookup** tab, and the **Settings** tab. You can also verify contracts directly from the [Deploy and Run](#verifying-with-deploy-and-run) plugin. ## Verify tab This is the home view of the plugin where you can verify your contracts. ![Contract verification home page](images/contract-verification/verify-tab.png) To verify a contract, you need to have: 1. The address of a deployed contract on a public network. 2. The same contract source code compiled in Remix, using the same compiler version, optimization settings, and EVM version that were used during deployment. 3. Constructor arguments matching those used during deployment (if applicable). With the above, you can select which verification services you want to use for your verification by checking their boxes. By default, all of them have valid configurations that allow you to verify without any setup. The only exception to this is verification using Etherscan on Ethereum mainnet; this requires a valid [Etherscan API key](https://docs.etherscan.io/introduction) which you can provide on the settings tab. ### Verifying with constructor arguments When a contract has arguments in the constructor, a text field will appear where you can enter the constructor arguments used during deployment. ![Constructor verify page with constructor arguments.](images/contract-verification/verify-with-args.png) ### Verifying a proxy contract If your contract is behind a proxy, you can also verify the proxy with the implementation contract. You just need to check the "The deployed contract is behind a proxy" checkbox, and provide the address of the proxy contract. ![Constructor verify page showing proxy address field.](images/contract-verification/verify-by-proxy.png) The plugin will first verify the implementation contract, and then verify the proxy contract. Proxies can only be verified on Etherscan and Blockscout. ### Supported networks The plugin supports hundreds of EVM-compatible networks. Notable examples include: - Ethereum mainnet and testnets (Sepolia, Holesky) - Arbitrum One, Arbitrum Nova, Arbitrum Sepolia - Base and Base Sepolia - BNB Smart Chain mainnet and testnet - Avalanche C-Chain and Fuji testnet - Optimism and OP Sepolia - Polygon and Polygon Amoy - Berachain, Blast, Celo, and many more The full list of supported networks is available in the network dropdown inside the plugin. ## Receipts tab Verification receipts are found on the receipts tab. ![Contract verification receipts page with the Receipts bar highlighted.](images/contract-verification/receipts-page.png) You can hover over the status symbols to get more information about failed verifications. ## Lookup tab The Lookup tab is used to check if a contract is verified on the verification services, and to download its source code into the Remix File Explorer. ![Contract verification lookup page with the Lookup bar highlighted.](images/contract-verification/lookup-tab.png) ## Settings tab In the settings tab, you can configure custom API URLs for the verification services, and add your own API keys. For Etherscan, adding an API key is mandatory. ![Contract verification settings page with the Settings bar highlighted.](images/contract-verification/settings-tab.png) The settings are always stored per chain, meaning that if you change the settings for a chain, it will not affect other chains. However, the Contract Verification plugin uses the Etherscan v2 API, meaning the same API key will work for over 50 different chains. ```{important} For the time being, you’ll still need to input your Etherscan v2 API key on each different chain, but at least it will be the same key for all of them. ``` ## Verifying with Deploy & run You can also verify your contracts during deployment on the Deploy and Run plugin by checking the "Verify Contract on Explorers" checkbox before clicking **Deploy**. ![Deploy and Run plugin with the Verify Contract on Explorers checkbox highlighted.](images/contract-verification/verify-on-deploy-and-run.png) When the checkbox is enabled, verification is automatically submitted to the configured verification services immediately after the contract is deployed. The verification uses the same service configuration set up in the Contract Verification plugin's [Settings tab](#settings-tab). Verification results can be found in the [Receipts tab](#receipts-tab) of the Contract Verification plugin. ### [Naming Contracts](https://remix-ide.readthedocs.io/en/latest/naming-contracts.html) > Give your deployed smart contract a human readable ENS name from inside Remix IDE. # Naming Contracts A contract address like `0xF2F31B340900cDC4561bb3cC999dabDF85c81939` is hard to read and easy to confuse with another. With Remix, you can give a deployed contract an [ENS](https://ens.domains) name such as `ownable.project.remixcontract.eth`, so people can recognize it by name instead. Remix registers the name on Ethereum L1 for you and pays the gas. You can then set a **reverse name**, which lets block explorers and wallets show the name wherever the contract's address appears. For background on the ENS side of this, see [Naming contracts](https://docs.ens.domains/web/naming-contracts) in the ENS documentation. ## Before you start The contract must be **Ownable**, meaning it has an owner account that can sign transactions on its behalf. The simplest way to do this is to inherit OpenZeppelin's `Ownable` contract. Deploy it to Ethereum L1 or an Ethereum L2. Most of these networks are supported, but testnets such as Sepolia are not. ## Registering the name In the **Deployed Contracts** section, click the three dots menu on your contract and select **Name Contract (ENS)**. ![Name Contract option in the contract menu](images/naming-contracts/name-contract-menu.png) Enter a **Label** and a **Project**. The preview shows the full name, in the form `label.project.remixcontract.eth`, along with the address it will point to. Remix also checks whether the name is available. If it's taken, choose a different label or project. Once the name is available, click **Register ENS Name**. ![Label and project fields](images/naming-contracts/label-and-project.png) When registration finishes, the name resolves to your contract's address. This is called the forward record. ## Setting the reverse name The forward record points the name to the address. The reverse name points the address back to the name, which is what block explorers and wallets use to display it. Setting the reverse name takes one transaction on the network your contract is deployed to, signed by the contract owner. Make sure the owner account is selected in Remix, then click **Set Reverse** and confirm the transaction. If you only need the forward record for now, click **Skip** instead. You can set the reverse name later. ![Set Reverse Name step](images/naming-contracts/set-reverse-name.png) ## Reviewing the result Whether you set the reverse name or skip it, you end on a summary screen. It shows the name and the address it resolves to, the total gas used and its cost (which Remix pays), and links to the registration transactions. From there, you can open the contract in the block explorer or the name in the ENS App. ![Summary of the named contract](images/naming-contracts/ens-app-link.png) ### [Running Scripts](https://remix-ide.readthedocs.io/en/latest/running_js_scripts.html) > Execute JavaScript and TypeScript scripts in Remix IDE to automate deployment, testing, and interaction with smart contracts. # Running Scripts Remix IDE supports execution of JavaScript & TypeScript files. For some script examples using ethers.js, go to the scripts folder in the Default Workspace or the Basic Workspace. ## Why run scripts in Remix? - To mimic how the front-end of your dApp will use ethers.js - To quickly deploy and interact with a bunch of instances of a contract without going through the Remix GUI. - To run tests on a previous deployed contract. ## Writing and running scripts Create a file with `.js` or `.ts` extension and put your logic inside it. To run a script: - Click the play button at the upper left of the Main Panel when the script is the active file in the Editor. - Right click on the script name in the `File Explorers` and click on the **Run** option. - `Ctrl+Shift+S` when the script is displayed in the editor. - Make the script the active file in the editor and run `remix.exeCurrent()` from Remix terminal Here is a sample .js script: ```JavaScript function test() { var num=12; if(num<10) console.log(num + " is less than 10"); else console.log(num + " is not less than 10"); } test(); ``` Running it using one of options mentioned above will show result in Remix terminal ## Script to deploy a contract Remix accepts async/await scripts to run [ethers.js](https://docs.ethers.org/v6/) commands. The script needs to be wrapped in a self executing function. ## Setup 1. Scripts will need to access the contract's ABI. The ABI is located in the contract's metadata file. Make sure that this metadata file will be created by going to the **Settings** module and checking that the **Generate contract metadata** option is indeed **checked**. (It is enabled by default) 2. Compile a Solidity file - to generate the contract metadata. 3. In the Deploy & Run plugin, choose the Environment for your script. - Async/await scripts work on in all of the Environments: the Remix VM, Injected Provider (usually MetaMask), and External HTTP Provider. ## Compile and run script In the Solidity Compiler, there is a button called "Compile and Run script". When drafting a contract, it can be helpful to run a script just after the compilation succeeds that will deploy and set the state. The script can contains Mocha tests to be run. In order to connect a contract with a script, add the **NatSpec** tag `@custom:dev-run-script` to the contract followed by the absolute file path, like: ```JavaScript /** * @title ContractName * @dev ContractDescription * @custom:dev-run-script file_path */ contract ContractName {} ``` When you are ready to deploy the code for real, remove the NatSpec comment `@custom:dev-run-script`. **ShortCut**: `Ctrl+Shift+S` , when editing a solidity file, will compile that file and then will run the script. In contrast, `ctrl+S` will only start the compiling. ## Adding external dependencies Remix has organized JS/TS dependencies into sets called "Configurations". These dependencies are available for use in your scripts. The following list contains the **Default** dependencies: - `ethers (v5)`: [Ethers v5 docs](https://docs.ethers.org/v5/) - `zokrates-js`: [Zokrates docs](https://zokrates.github.io/toolbox/zokrates_js.html) - `web3`: [Web3js docs](https://web3js.readthedocs.io/en/v1.10.0/) - `zksync-ethers`: [Zksync Ethers docs](https://www.npmjs.com/package/zksync-ethers) - `starknet`: [JavaScript library for Starknet docs](https://www.npmjs.com/package/starknet) - `snarkjs`: [Snarkjs docs](https://github.com/iden3/snarkjs) - `circomlibjs`: [Circomlibjs docs](https://github.com/iden3/circomlibjs) - `ffjavascript`: [Finite Field Library in Javascript docs](https://github.com/iden3/ffjavascript) - `big-integer`: [Big integer docs](https://www.npmjs.com/package/big-integer) - `@zk-kit/incremental-merkle-tree`: [Incremental Merkle tree implementation in TypeScript docs](https://www.npmjs.com/package/@zk-kit/incremental-merkle-tree.sol) - `sindri`: [Sindri CLI TypeScript SDK](https://www.npmjs.com/package/sindri) - `@semaphore-protocol/data`: [Semaphore data docs](https://www.npmjs.com/package/@semaphore-protocol/data) - `@semaphore-protocol/group`: [Semaphore group docs](https://www.npmjs.com/package/@semaphore-protocol/group) - `@semaphore-protocol/identity`: [Semaphore identity docs](https://www.npmjs.com/package/@semaphore-protocol/identity) - `@semaphore-protocol/proof`: [Semaphore proof docs](https://www.npmjs.com/package/@semaphore-protocol/proof) - `crypto-js`: [Cryptojs docs](https://www.npmjs.com/package/crypto-js) - `aes-js`: [AES-JS docs](https://www.npmjs.com/package/aes-js) - `multihashes`: [Multihashes docs](https://www.npmjs.com/package/multihashes) - `openai`: [TypeScript library for Openai docs](https://www.npmjs.com/package/openai) ### Loading other script dependencies If you don't see what you need in the Default configuration of scripts, you can load other configurations of scripts using the Script Configuration panel. This panel is accessed from the dropdown on the "Run Script" button. ```{note} If the active file in the Editor is not a script, then the "Run Script" button turns into the "Compile" button and the Open script configuration option is not present. ``` ![Script config](./images/running-scripts/script-config.png) It is not necessary to install the scripts to use; just use the `import` or `require` keyword. For example: ```js //using require const { expect } = require("chai"); //using import import { UltraHonkBackend } from "@aztec/bb.js"; ``` If you try to import an unsupported module, you will get the error below: ```bash module require is not supported by Remix IDE ``` --- ## x402 ### [The Remix x402 MCP Server](https://remix-ide.readthedocs.io/en/latest/x402/x402-Guide.html) > Overview of the Remix x402 MCP Server, which exposes Remix's Solidity compiler, Slither analysis, contract deployment, and AI security auditing as pay-per-call services priced in USDC. # The Remix x402 MCP Server The Remix x402 MCP Server exposes Remix's Solidity compiler, Slither analysis, contract deployment, and AI security auditing as services that are paid for per call in USDC. It is aimed at AI agents, and at anything else that can pay per call over MCP or plain HTTP. The server is indexed on the [x402 Bazaar](https://agentic.market/services/api-remix-live) with full metadata, so agents can discover the tools rather than being configured with them. There are two ways to use Remix x402. The first is through any MCP client that can make payments: you describe what you want in plain language, and the client makes the call and pays for it from a wallet. {doc}`Setting up Claude ` walks through Claude Desktop and Claude Code, though nothing here is specific to them. The second is to call the {doc}`HTTP endpoints ` from your own code. ## Available tools | Tool | What it does | Price | | ---------------------------------- | ----------------------------------------------------------------- | ------------------------------------------------ | | `compile_solidity` | Compiles Solidity sources and returns ABI, bytecode, and metadata | 0.01 USDC | | `analyze_with_slither` | Runs Slither static security analysis | 0.02 USDC | | `compile_and_deploy` | Compiles and deploys to one network | (Gas cost × 1.3) + 0.05 USDC | | `compile_and_deploy_multi_network` | Compiles once, deploys to several networks | (Total gas × 1.3) + 0.05 USDC, plus a 10% buffer | Two further services, `get_audit_checklist` and `do_audit`, run an AI security audit. They are available over HTTP only, and are covered on the {doc}`AI audit ` page. Each tool has its own page in this section, with full parameter and response reference. ## HTTP endpoints Compilation, analysis, and the AI audit services are also reachable as REST endpoints, under `https://api.remix.live/mcp/x402-http/`: | Method | Endpoint | Price | | ------ | ----------------------- | --------- | | POST | `/compile` | 0.01 USDC | | POST | `/analyze` | 0.02 USDC | | POST | `/get_audit_checklist` | 0.05 USDC | | POST | `/do_audit` | 0.10 USDC | | GET | `/info` | Free | | GET | `/health` | Free | The split runs both ways: the deployment tools are MCP-only, and the two audit endpoints are HTTP-only. `/info` reports the server's name, version, endpoints and prices, and the network it settles on, which makes it a quick way to confirm what you are talking to: ```bash curl https://api.remix.live/mcp/x402-http/info ``` ```{only} html Or call it from here:
``` ## Network The hosted service settles on **Base mainnet**, chain ID 8453. Every call therefore spends real USDC, starting at 0.01 for a compile, so treat the prices on this page as money rather than credits. To work against a testnet instead, you have to run the server yourself on Base Sepolia, chain ID 84532. The {doc}`HTTP endpoints ` page covers that. Either way, `/info` reports the network a given server is on. ## Paying for calls Compilation and analysis are fixed price. The deployment tools are priced dynamically, because the server pays the deployment gas for you: the quote is that gas cost with a multiplier applied, plus a flat fee. The x402 payment itself is gasless. You sign an authorization rather than sending a transaction, and a facilitator service settles it on chain and pays that transaction's gas. This covers the payment only. The gas to actually deploy a contract is real, and is what the deployment tools price in. If your balance does not cover a call, it is rejected before any work is done: ```json { "error": "Insufficient USDC balance. Required: 0.01 USDC, Available: 0.005 USDC" } ``` ## Best practices 1. Test compilation before you deploy. 2. Run a Slither analysis before deploying, to catch security issues early, and an AI audit when you want a written review alongside it. 3. Start with small contracts, to get a feel for the costs. 4. Use the optimizer for production deployments, to reduce gas costs. 5. Check constructor arguments carefully before deploying. 6. Check the network carefully, since testnet tokens have no real value. 7. Save your deployment addresses. You need them to interact with the contracts afterwards. 8. Test post-deployment calls on a single network before deploying to several. ## Support - [The x402 server repository](https://github.com/remix-project-org/x402) for issues, questions, and feature requests - [HTTP x402 endpoints](https://github.com/remix-project-org/x402/blob/main/HTTP_X402_ENDPOINTS.md) for direct API usage - [MCP usage guide](https://github.com/remix-project-org/x402/blob/main/MCP_USAGE.md) for using the server programmatically - [x402 protocol documentation](https://docs.x402.org/introduction) for the protocol itself - [agentic.market](https://agentic.market) to discover and validate x402 services ### [Using x402 Services with Claude](https://remix-ide.readthedocs.io/en/latest/x402/claude-setup.html) > Set up the Coinbase agentic wallet in Claude Desktop or Claude Code, then compile and analyze Solidity contracts with Remix's x402 services, paying per call in USDC. # Using x402 Services with Claude Claude Desktop and Claude Code can call Remix's x402 services directly, once they have a wallet to pay with. You describe the contract you want in the chat, and Claude finds the service, pays for the call, and returns the result. This page uses Claude as the worked example, but the services are not tied to it. Any MCP client that can make x402 payments reaches them the same way, and the wallet installer below supports other MCP clients too. ## The wallet Payment goes through the **Coinbase agentic wallet**, provided by the `@coinbase/payments-mcp` server. It is a Model Context Protocol server that lets an AI agent pay for x402 services in USDC on Base, manage a wallet in natural language, and browse the x402 Bazaar. Because Coinbase custodies the keys, there is no private key for you to manage. You sign in with a one-time passcode sent to your email, and the x402 payments themselves are gasless: a facilitator settles each one on chain and covers that transaction's gas. Spending limits, KYT screening, and OFAC compliance are built in. ### Before you start - Claude Desktop, or the Claude Code CLI - Node.js 18 or later - An email address, for authentication - USDC on Base, to pay for calls ## Setting up Claude Desktop ### Automatic installation Run the interactive installer and choose **Claude Desktop** from the list of MCP clients. It configures your Claude Desktop settings for you. ```bash npx @coinbase/payments-mcp ``` Then quit Claude Desktop completely and restart it. ### Manual configuration If the installer fails, open your Claude Desktop configuration file and add the server: ```json { "mcpServers": { "payments": { "command": "npx", "args": [ "-y", "@coinbase/payments-mcp" ], "env": { "NETWORK": "base" } } } } ``` `NETWORK` takes either `base` for Base mainnet, or `base-sepolia` for the Base Sepolia testnet. It has to match the network the service you are calling settles on: the hosted Remix service is on Base mainnet, so leave this as `base` unless you are pointing at a server of your own running on testnet. Quit Claude Desktop completely and restart it, and the server initializes on its own. ### Verifying the installation ```bash npx @coinbase/payments-mcp status ``` To reinstall, run `npx @coinbase/payments-mcp install --force`. To remove it, run `npx @coinbase/payments-mcp uninstall`. ## Setting up Claude Code The quickest route installs the server and writes the configuration in one step: ```bash npx @coinbase/payments-mcp --client claude-code --auto-config ``` To keep control of the configuration, install without it and register the server yourself: ```bash npx @coinbase/payments-mcp --client claude-code --no-auto-config claude mcp add --transport stdio payments-mcp -- node /Users/YOUR_USERNAME/.payments-mcp/bundle.js ``` Replace `YOUR_USERNAME` with your own home directory. The same registration can be done as JSON: ```bash claude mcp add-json payments-mcp '{"type":"stdio","command":"node","args":["/Users/YOUR_USERNAME/.payments-mcp/bundle.js"]}' ``` Quit Claude Code completely, restart it, then confirm the server is registered and healthy: ```bash claude mcp list ``` `payments-mcp` should appear in the list with its health status. ## Signing in The first time you use the wallet, ask for it in the chat: ```text show me my wallet ``` If you are not authenticated, the wallet interface opens automatically. Enter your email address, then the six-digit code that arrives in your inbox. Your wallet is created on first sign-in. To confirm it worked: ```text show me my wallet balance ``` Sessions stay active across Claude sessions. When one expires you are prompted to sign in again, and you can sign out at any time through the wallet interface. ## Using the services Claude discovers the Remix services through the Bazaar, so you can ask for what you want in plain language rather than naming an endpoint. ```{note} Compilation, Slither analysis, and the deployment tools are MCP tools, so Claude can call them directly. The {doc}`AI audit services ` are not MCP tools. They are published to the Bazaar with their input schemas, so Claude can still find them and describe them, but running one means a paid HTTP request rather than a tool call. ``` ### Compiling a contract Compilation costs 0.01 USDC per call. ```text compile a simple storage contract using remix.live bazaar services ``` Claude finds the compile endpoint, writes the contract, pays the 0.01 USDC, and returns the bytecode and ABI. You can describe the contract you want in as much detail as you like: ```text compile an ERC20 token contract with the following features: - Name: MyToken - Symbol: MTK - Initial supply: 1,000,000 - Mintable by owner - Burnable ``` Or paste your own: ````text compile this contract using remix.live: ```solidity // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract Voting { mapping(address => bool) public hasVoted; mapping(uint256 => uint256) public votes; function vote(uint256 proposalId) public { require(!hasVoted[msg.sender], "Already voted"); hasVoted[msg.sender] = true; votes[proposalId]++; } } ``` ```` The response carries `success`, the compiled `contracts` (each with an `abi` and `evm.bytecode.object`), the compiler `version`, and any `errors`. See the compiling page in this section for the full response reference. ### Analyzing a contract Analysis costs 0.02 USDC per call. Slither is a static analysis tool that finds vulnerabilities and code quality problems without running the contract. ````text analyze this contract for security vulnerabilities using remix.live bazaar service: ```solidity // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract VulnerableBank { mapping(address => uint256) public balances; function deposit() public payable { balances[msg.sender] += msg.value; } function withdraw() public { uint256 amount = balances[msg.sender]; (bool success, ) = msg.sender.call{value: amount}(""); require(success, "Transfer failed"); balances[msg.sender] = 0; // Reentrancy vulnerability! } } ``` ```` Claude sends the contract to the analyze endpoint, pays the 0.02 USDC, and explains what Slither found. In this case that is the reentrancy, since the balance is zeroed only after the external call returns. ### Example workflows Chaining the services in one request works well: ```text 1. compile a simple ERC20 token using remix.live 2. analyze it for security issues 3. if it's safe, show me the deployment bytecode ``` ```text I have this contract [paste contract code]. Please: 1. compile it using remix.live 2. run security analysis 3. summarize the vulnerabilities found 4. suggest fixes ``` ## Managing your wallet Ask for your balance: ```text what's my USDC balance? ``` ```text Your wallet balance on Base: - USDC: 10.00 USDC - ETH: 0.005 ETH ``` Ask for your address: ```text what's my wallet address? ``` ```text Your wallet addresses: - Base (EVM): 0x1234567890abcdef1234567890abcdef12345678 - Solana: AbC123...xyz ``` To add funds, send USDC on Base to that address, then ask Claude to check your balance again to confirm it arrived. The wallet also enforces spending limits, configured on the Coinbase side, which guard against unauthorized large transactions. ## Getting help - [Coinbase agentic wallet documentation](https://docs.cdp.coinbase.com/agentic-wallet/welcome) for wallet-specific issues - [x402 protocol documentation](https://docs.x402.org/introduction) for the protocol itself - [The x402 server repository](https://github.com/remix-project-org/x402) for the Remix services themselves ### [Compiling Solidity](https://remix-ide.readthedocs.io/en/latest/x402/compile.html) > Compile Solidity contracts with the Remix x402 MCP Server's compile_solidity tool, including compiler version, optimizer, and EVM version settings. # Compiling Solidity The `compile_solidity` tool compiles one or more Solidity source files with the Remix compiler. It returns the ABI, bytecode, method identifiers, gas estimates, and metadata for every contract it finds. **Price:** 0.01 USDC per call. ## Input parameters ```typescript { sources: { [filename: string]: { content: string } }, version?: string, settings?: { optimizer?: { enabled: boolean, runs: number }, evmVersion?: string } } ``` | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `sources` | Object | Yes | Map of filename to source code content | | `sources[filename].content` | string | Yes | Solidity source code | | `version` | string | No | Solidity compiler version, for example `v0.8.20+commit.a1b79de6`. Defaults to `v0.8.35+commit.47b9dedd` | | `settings` | Object | No | Compiler settings | | `settings.optimizer` | Object | No | Optimizer configuration | | `settings.optimizer.enabled` | boolean | No | Enable the optimizer. Defaults to `false` | | `settings.optimizer.runs` | number | No | Optimizer runs. Defaults to `200` | | `settings.evmVersion` | string | No | EVM version. Defaults to `osaka` | ### Compiler settings The `settings.evmVersion` field accepts any of the following: - `homestead` - `tangerineWhistle` - `spuriousDragon` - `byzantium` - `constantinople` - `petersburg` - `istanbul` - `berlin` - `london` - `paris` - `shanghai` - `osaka` (default) Turning the optimizer on reduces the gas cost of the deployed contract, so it is worth enabling for anything you intend to put on a live network. ## Output ```typescript { success: boolean, contracts?: { [filename: string]: { [contractName: string]: { abi: Array, evm: { bytecode: { object: string, opcodes: string, sourceMap: string, linkReferences: Object }, deployedBytecode: { object: string, opcodes: string, sourceMap: string, linkReferences: Object }, methodIdentifiers: Object, gasEstimates: Object }, metadata: string } } }, sources?: { [filename: string]: { id: number, ast: Object } }, errors?: Array<{ severity: "error" | "warning", message: string, formattedMessage: string, sourceLocation?: { file: string, start: number, end: number } }>, settings?: { optimizer: { enabled: boolean, runs: number }, evmVersion: string }, version?: string } ``` ### Output fields | Field | Type | Description | |-------|------|-------------| | `success` | boolean | Whether compilation succeeded | | `contracts` | Object | Compiled contracts by file and contract name. Only present on success | | `contracts[file][name].abi` | Array | Contract ABI | | `contracts[file][name].evm.bytecode` | Object | Contract creation bytecode | | `contracts[file][name].evm.deployedBytecode` | Object | Runtime bytecode | | `contracts[file][name].evm.methodIdentifiers` | Object | Function signature hashes | | `contracts[file][name].evm.gasEstimates` | Object | Gas cost estimates | | `contracts[file][name].metadata` | string | Contract metadata JSON | | `sources` | Object | Source file information with AST. Only present on success | | `errors` | Array | Compilation errors and warnings, if there are any | | `settings` | Object | Compiler settings used. Only present on success | | `version` | string | Solidity compiler version used | ## Example ```javascript const result = await client.callTool({ name: "compile_solidity", arguments: { sources: { "MyToken.sol": { content: ` // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract MyToken { string public name = "MyToken"; mapping(address => uint256) public balances; function mint(address to, uint256 amount) public { balances[to] += amount; } } ` } }, version: "v0.8.20+commit.a1b79de6", // Optional: specify compiler version settings: { optimizer: { enabled: true, runs: 200 }, evmVersion: "paris" } } }); const output = JSON.parse(result.content[0].text); console.log('Compiler version:', output.version); console.log('ABI:', output.contracts['MyToken.sol'].MyToken.abi); console.log('Bytecode:', output.contracts['MyToken.sol'].MyToken.evm.bytecode.object); ``` ## Errors When the source does not compile, `success` is `false` and the `errors` array describes what went wrong. Each entry carries a `severity` of either `error` or `warning`, so warnings can appear alongside a successful compilation. ```json { "errors": [ { "severity": "error", "message": "ParserError: Expected ';' but got 'identifier'", "formattedMessage": "ParserError: Expected ';' but got 'identifier'\n --> MyContract.sol:5:9:\n |\n5 | uint x\n | ^", "sourceLocation": { "file": "MyContract.sol", "start": 78, "end": 79 } } ] } ``` ### [Compiling and Deploying](https://remix-ide.readthedocs.io/en/latest/x402/compile-and-deploy.html) > Compile and deploy a contract to one or many networks with the Remix x402 MCP Server, including constructor arguments and post-deployment method calls. # Compiling and Deploying Two tools compile a contract and put it on chain in a single call, using the server's delegated deployment service. You do not supply a private key: the server deploys from its own address and reports that address back to you as `deployerAddress`. - `compile_and_deploy` deploys to one network. - `compile_and_deploy_multi_network` compiles once and deploys the result to several networks. ## Pricing Both tools are priced dynamically, because the server pays the gas on your behalf: | Tool | Price | |------|-------| | `compile_and_deploy` | (Gas cost × 1.3) + 0.05 USDC | | `compile_and_deploy_multi_network` | (Total gas across networks × 1.3) + 0.05 USDC, plus a 10% multi-network buffer | ## Supported networks Currently on testnet: - `base-sepolia`: Base Sepolia testnet (primary) - `sepolia`: Ethereum Sepolia testnet Both tools accept any network from `viem/chains`. On mainnet launch, networks such as `base`, `mainnet`, `polygon`, `arbitrum`, and `optimism` will be available. ## Deploying to one network ### Input parameters ```typescript { sources: { [filename: string]: { content: string } }, contractName: string, contractFile: string, network: string, constructorArgs?: Array, version?: string, settings?: { optimizer?: { enabled: boolean, runs: number }, evmVersion?: string }, value?: string, postDeploymentCall?: { methodName: string, methodArgs?: Array, value?: string } } ``` | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `sources` | Object | Yes | Map of filename to source code content | | `contractName` | string | Yes | Name of the contract to deploy | | `contractFile` | string | Yes | Filename containing the contract | | `network` | string | Yes | Network to deploy to | | `constructorArgs` | Array | No | Constructor arguments for the contract | | `version` | string | No | Solidity compiler version. Defaults to `v0.8.35+commit.47b9dedd` | | `settings` | Object | No | Compiler settings, the same as `compile_solidity` | | `value` | string | No | Value in wei to send with the deployment, for payable constructors | | `postDeploymentCall` | Object | No | A method to call once the contract is deployed | | `postDeploymentCall.methodName` | string | Yes | Name of the method to call | | `postDeploymentCall.methodArgs` | Array | No | Arguments for the method call | | `postDeploymentCall.value` | string | No | Value in wei to send with the method call, for payable methods | `postDeploymentCall.methodName` is required only when you include a `postDeploymentCall` object at all. ### Output ```typescript { success: boolean, compilation?: { version: string, warnings: Array, settings: { optimizer: { enabled: boolean, runs: number }, evmVersion: string } }, deployment?: { success: boolean, contractAddress: string, transactionHash: string, blockNumber: string, gasUsed: string, status: string, network: string, deployedBy: string, deployerAddress: string }, abi?: Array, postDeploymentCall?: { success: boolean, methodName: string, methodArgs: Array, transactionHash?: string, blockNumber?: string, gasUsed?: string, status?: string, error?: string, details?: string }, message?: string, error?: string, details?: string } ``` | Field | Type | Description | |-------|------|-------------| | `success` | boolean | Whether the overall operation succeeded | | `compilation` | Object | Compilation warnings and settings used | | `compilation.version` | string | Solidity compiler version used | | `deployment` | Object | Deployment details and transaction info | | `deployment.contractAddress` | string | Deployed contract address | | `deployment.transactionHash` | string | Deployment transaction hash | | `deployment.blockNumber` | string | Block number of the deployment | | `deployment.gasUsed` | string | Actual gas used for the deployment | | `deployment.status` | string | Transaction status | | `deployment.network` | string | Network deployed to | | `deployment.deployerAddress` | string | Server Deployer address | | `abi` | Array | Contract ABI, for interacting with the contract afterwards | | `postDeploymentCall` | Object | Result of the post-deployment call, if there was one | | `postDeploymentCall.success` | boolean | Whether the method call succeeded | | `postDeploymentCall.transactionHash` | string | Method call transaction hash | | `postDeploymentCall.error` | string | Error if the method call failed | | `message` | string | Additional message, for example on partial success | | `error` | string | Error message if the operation failed | | `details` | string | Stack trace or additional error details | A deployment can succeed while its post-deployment call fails. When that happens, `message` explains the partial success, so check `postDeploymentCall.success` separately rather than relying on the top-level `success` alone. ### Example ```javascript const result = await client.callTool({ name: "compile_and_deploy", arguments: { sources: { "Counter.sol": { content: ` // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract Counter { uint256 public count; address public owner; constructor(uint256 _initialCount) { count = _initialCount; owner = msg.sender; } function increment() public { count += 1; } } ` } }, contractName: "Counter", contractFile: "Counter.sol", network: "base-sepolia", constructorArgs: [42], postDeploymentCall: { methodName: "increment", methodArgs: [] } } }); const output = JSON.parse(result.content[0].text); console.log('Contract deployed at:', output.deployment.contractAddress); console.log('Transaction:', output.deployment.transactionHash); console.log('View on explorer: https://sepolia.basescan.org/address/' + output.deployment.contractAddress); ``` ## Deploying to several networks `compile_and_deploy_multi_network` takes a `networks` array in place of `network`, compiles the contract once, and deploys that same output to each network in turn. The constructor arguments and compiler settings are shared across all of them. ### Multi-network parameters ```typescript { sources: { [filename: string]: { content: string } }, contractName: string, contractFile: string, networks: Array, constructorArgs?: Array, version?: string, settings?: { optimizer?: { enabled: boolean, runs: number }, evmVersion?: string }, postDeploymentCall?: { methodName: string, methodArgs?: Array } } ``` | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `sources` | Object | Yes | Map of filename to source code content | | `contractName` | string | Yes | Name of the contract to deploy | | `contractFile` | string | Yes | Filename containing the contract | | `networks` | Array<string> | Yes | Networks to deploy to | | `constructorArgs` | Array | No | Constructor arguments, the same for every network | | `version` | string | No | Solidity compiler version. Defaults to `v0.8.35+commit.47b9dedd` | | `settings` | Object | No | Compiler settings, the same as `compile_solidity` | | `postDeploymentCall` | Object | No | Method to call after each deployment | ### Multi-network output ```typescript { success: boolean, compilation?: { version: string, warnings: Array }, deployments: Array<{ network: string, success: boolean, contractAddress?: string, transactionHash?: string, blockNumber?: string, gasUsed?: string, status?: string, deployedBy?: string, deployerAddress?: string, postDeploymentCall?: { success: boolean, methodName: string, transactionHash?: string, blockNumber?: string, gasUsed?: string, status?: string, error?: string }, error?: string }>, abi?: Array, summary?: { total: number, successful: number, failed: number }, error?: string, details?: string } ``` | Field | Type | Description | |-------|------|-------------| | `success` | boolean | Whether every deployment succeeded | | `compilation` | Object | Compilation warnings, from the single compilation | | `compilation.version` | string | Solidity compiler version used | | `deployments` | Array | One result per network | | `deployments[].network` | string | Network name | | `deployments[].success` | boolean | Whether this network's deployment succeeded | | `deployments[].contractAddress` | string | Deployed contract address on this network | | `deployments[].transactionHash` | string | Deployment transaction hash | | `deployments[].blockNumber` | string | Block number | | `deployments[].gasUsed` | string | Gas used for this deployment | | `deployments[].postDeploymentCall` | Object | Post-deployment call result | | `deployments[].error` | string | Error if this deployment failed | | `abi` | Array | Contract ABI, the same for every network | | `summary` | Object | Summary statistics | | `summary.total` | number | Total networks attempted | | `summary.successful` | number | Number of successful deployments | | `summary.failed` | number | Number of failed deployments | | `error` | string | Overall error if the entire operation failed | Deployments are reported per network, so a failure on one network does not undo the others. Read `summary` for the counts, then walk `deployments` for the detail. ### Multi-network example ```javascript const result = await client.callTool({ name: "compile_and_deploy_multi_network", arguments: { sources: { "NFT.sol": { content: ` // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract SimpleNFT { string public name; string public symbol; uint256 public totalSupply; constructor(string memory _name, string memory _symbol) { name = _name; symbol = _symbol; } function mint(address to, uint256 tokenId) public { totalSupply += 1; } } ` } }, contractName: "SimpleNFT", contractFile: "NFT.sol", networks: ["base-sepolia", "sepolia"], constructorArgs: ["MyNFT", "MNFT"], postDeploymentCall: { methodName: "mint", methodArgs: ["0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb1", 1] } } }); const output = JSON.parse(result.content[0].text); console.log('Summary:', output.summary); // Check results for each network output.deployments.forEach(deployment => { if (deployment.success) { console.log(`${deployment.network}: ${deployment.contractAddress}`); console.log(` Transaction: ${deployment.transactionHash}`); } else { console.log(`${deployment.network}: Failed - ${deployment.error}`); } }); ``` ## Errors A deployment that reverts on chain returns the transaction hash alongside the error, so you can look the transaction up on a block explorer: ```json { "success": false, "error": "Contract deployment failed: execution reverted", "transactionHash": "0x..." } ``` An unrecognized network name is rejected before anything is deployed: ```json { "error": "Network not supported: ethereum-mainnet. Supported networks: base-sepolia, sepolia" } ``` Test a post-deployment call on a single network before running the same deployment across several, since a mistake there is paid for once per network. ### [Analyzing Contracts with Slither](https://remix-ide.readthedocs.io/en/latest/x402/analyze.html) > Run Slither static security analysis on Solidity contracts through the Remix x402 MCP Server, with detector selection and severity filtering. # Analyzing Contracts with Slither The `analyze_with_slither` tool runs Slither's static security analysis over your Solidity sources and returns the findings grouped by severity. Run it before deploying anything, to catch problems while they are still cheap to fix. **Price:** 0.02 USDC per call. ## Input parameters ```typescript { sources: { [filename: string]: { content: string } }, version?: string, detectors?: Array, excludeLow?: boolean, excludeInformational?: boolean } ``` | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `sources` | Object | Yes | Map of filename to source code content | | `sources[filename].content` | string | Yes | Solidity source code | | `version` | string | No | Solidity compiler version, for example `0.8.35` | | `detectors` | Array<string> | No | Specific detectors to run | | `excludeLow` | boolean | No | Exclude low severity findings. Defaults to `false` | | `excludeInformational` | boolean | No | Exclude informational findings. Defaults to `false` | ### Common detectors If you leave `detectors` empty, the full detector set runs. Some of the more commonly used ones are: - `reentrancy-eth`: reentrancy vulnerabilities - `arbitrary-send-eth`: unprotected ETH send - `suicidal`: unprotected self-destruct - `uninitialized-state`: uninitialized state variables - `unchecked-transfer`: unchecked return values - `tx-origin`: dangerous use of `tx.origin` - `timestamp`: timestamp dependency ## Output ```typescript { success: boolean, summary?: { totalFindings: number, high: number, medium: number, low: number, informational: number, optimization: number }, findings?: Array<{ check: string, impact: "High" | "Medium" | "Low" | "Informational" | "Optimization", confidence: "High" | "Medium" | "Low", description: string, elements?: Array<{ type: string, name: string, source_mapping?: { start: number, length: number, filename_relative: string, lines: Array } }>, reference?: string, id?: string }>, rawAnalysis?: string, rawOutput?: Object, compilerVersion?: string, error?: string } ``` ### Output fields | Field | Type | Description | |-------|------|-------------| | `success` | boolean | Whether the analysis completed | | `summary` | Object | Counts by severity level | | `findings` | Array | The security findings | | `findings[].check` | string | Detector that found the issue | | `findings[].impact` | string | Severity level of the finding | | `findings[].confidence` | string | Confidence level of the finding | | `findings[].description` | string | Human-readable description | | `findings[].elements` | Array | Code elements involved, where available | | `findings[].reference` | string | URL with more information | | `rawAnalysis` | string | Raw Slither output text | | `rawOutput` | Object | Complete Remix API response | | `compilerVersion` | string | Solidity version used for the analysis | | `error` | string | Error message if the analysis failed | ### Impact levels - **High**: critical vulnerabilities that should be fixed immediately - **Medium**: important issues that could lead to problems - **Low**: minor issues or code quality improvements - **Informational**: best practice suggestions A finding also carries a `confidence` level. Treat a high impact, high confidence finding as a blocker; lower confidence findings are worth reading, but may not apply to your contract. ## Example This contract changes state after an external call, which is the classic reentrancy pattern: ```javascript const result = await client.callTool({ name: "analyze_with_slither", arguments: { sources: { "Vulnerable.sol": { content: ` // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract Vulnerable { mapping(address => uint256) public balances; function withdraw() public { uint256 amount = balances[msg.sender]; (bool success, ) = msg.sender.call{value: amount}(""); require(success); balances[msg.sender] = 0; // State change after external call! } } ` } }, excludeInformational: true } }); const output = JSON.parse(result.content[0].text); console.log('Summary:', output.summary); output.findings.forEach(finding => { console.log(`[${finding.impact}] ${finding.check}: ${finding.description}`); }); ``` ### [Auditing Contracts with AI](https://remix-ide.readthedocs.io/en/latest/x402/audit.html) > Generate an AI security audit checklist for a Solidity contract and run a full audit against it, using the Remix x402 HTTP endpoints. # Auditing Contracts with AI Two endpoints run an AI security audit over your Solidity sources. `/get_audit_checklist` works out which security categories apply to your contract, and `/do_audit` audits the code against that checklist and writes up the findings. Both return markdown, so the output is meant to be read rather than parsed. They are designed to run in sequence: generate the checklist first, then pass it to the audit. ```{note} These two services are HTTP only. Unlike compilation and Slither analysis, they are not registered as MCP tools, so an MCP client such as Claude cannot invoke them as a tool. They are indexed on the Bazaar with their input schemas, so an agent can still discover them and call them as a paid HTTP request. See {doc}`Using the HTTP Endpoints ` for how payment works. ``` This is static AI analysis, not a substitute for a human audit. Treat the output as a starting point for review, and pair it with {doc}`Slither analysis `, which catches different classes of problem. ## Step 1: Generate a checklist **Endpoint:** `POST /get_audit_checklist` **Price:** 0.05 USDC per call. The server matches your contract against a library of security audit categories and returns the ones that apply, each with a severity and a short note on why it is relevant. ### Input parameters ```typescript { sources: { [filename: string]: { content: string } }, maxCategories?: number } ``` | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `sources` | Object | Yes | Map of filename to source code content, the same shape `/compile` takes | | `sources[filename].content` | string | Yes | Solidity source code | | `maxCategories` | number | No | Maximum number of categories to match. Defaults to `12`, maximum `20` | ### Output ```typescript { success: boolean, markdown: string, matchedCategories: number, model: string, tokensUsed: number } ``` | Field | Type | Description | |-------|------|-------------| | `success` | boolean | Whether the request completed | | `markdown` | string | The checklist report, in markdown | | `matchedCategories` | number | How many categories were matched to the contract | | `model` | string | AI model used for the analysis | | `tokensUsed` | number | Tokens consumed by the model | The `markdown` field is what you pass to `/do_audit` in step 2. ## Step 2: Run the audit **Endpoint:** `POST /do_audit` **Price:** 0.10 USDC per call. This takes your sources and a checklist, works through the code against every checklist item, and returns a full audit report with findings classified by severity. ### Input parameters ```typescript { sources: { [filename: string]: { content: string } }, checklist: string } ``` | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `sources` | Object | Yes | Map of filename to source code content | | `checklist` | string | Yes | Audit checklist in markdown, normally the `markdown` field from `/get_audit_checklist` | The `checklist` parameter is required, but it does not have to come from step 1. If you have your own checklist in markdown, you can send that instead. ### Output ```typescript { success: boolean, markdown: string, findingsCount: number, severity: { critical: number, high: number, medium: number, low: number, informational: number }, model: string, tokensUsed: number } ``` | Field | Type | Description | |-------|------|-------------| | `success` | boolean | Whether the audit completed | | `markdown` | string | The audit report, in markdown | | `findingsCount` | number | Total number of findings | | `severity` | Object | Counts by severity level | | `model` | string | AI model used for the audit | | `tokensUsed` | number | Tokens consumed by the model | Each finding in the report carries a severity, a category, a description of the problem, and a recommendation for fixing it. ## Example Running both steps costs 0.15 USDC. This uses `@x402/fetch` to handle payment, as described in {doc}`Using the HTTP Endpoints `: ```javascript const BASE_URL = "https://api.remix.live/mcp/x402-http"; const sources = { "MyToken.sol": { content: ` // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract MyToken { mapping(address => uint256) public balances; function mint(address to, uint256 amount) public { balances[to] += amount; } } ` } }; // Step 1: work out which security categories apply (0.05 USDC) const checklistResponse = await x402Fetch(`${BASE_URL}/get_audit_checklist`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ sources, maxCategories: 12 }) }); const checklist = await checklistResponse.json(); console.log(`Matched ${checklist.matchedCategories} categories`); // Step 2: audit the contract against that checklist (0.10 USDC) const auditResponse = await x402Fetch(`${BASE_URL}/do_audit`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ sources, checklist: checklist.markdown }) }); const audit = await auditResponse.json(); console.log(`${audit.findingsCount} findings:`, audit.severity); console.log(audit.markdown); ``` The contract above has an unrestricted `mint` function, so expect access control to come back as a high severity finding. ## Costs | Call | Price | |------|-------| | `/get_audit_checklist` | 0.05 USDC | | `/do_audit` | 0.10 USDC | | Both, for one contract | 0.15 USDC | These are the most expensive fixed-price calls the server offers, so check your contract compiles before auditing it. A contract that does not compile still costs you the audit fee. ### [Using the HTTP Endpoints](https://remix-ide.readthedocs.io/en/latest/x402/http.html) > Call the Remix x402 HTTP endpoints directly with the x402 payment protocol, using @x402/fetch for automatic payment or handling the 402 flow yourself. # Using the HTTP Endpoints Alongside the MCP tools, Remix's compilation, analysis, and AI audit services are available as plain REST endpoints that implement the x402 payment protocol. Use these when you are integrating from your own code rather than through an AI agent. The two audit endpoints are available here only, and have no MCP equivalent. Payment settlement runs through a facilitator service, which means you pay no gas for the payment: you sign an authorization rather than sending a transaction, and the facilitator pays the fee to settle it on chain. You pay the quoted service fee and nothing more. ## Available endpoints | Method | Endpoint | Price | |--------|----------|-------| | POST | `/compile` | 0.01 USDC | | POST | `/analyze` | 0.02 USDC | | POST | `/get_audit_checklist` | 0.05 USDC | | POST | `/do_audit` | 0.10 USDC | | GET | `/info` | Free | | GET | `/health` | Free | The two audit endpoints run an AI security review of your sources and are covered on the {doc}`AI audit ` page. The hosted service is at `https://api.remix.live/mcp/x402-http/`, so the compile endpoint is `https://api.remix.live/mcp/x402-http/compile`. The two free endpoints can be called from here: ```{only} html
``` ## Before you start - 1-5 USDC on the network the server settles on, to pay for calls - An HTTP client, such as `curl`, Postman, or any HTTP library - An x402 client library, if you want payment handled for you ```bash npm install @x402/fetch @x402/evm viem dotenv ``` Put the key for the wallet you are paying from in a `.env` file: ```bash PRIVATE_KEY=0xYourPrivateKeyHere ``` ## How payment works An x402 request is made twice. The first attempt carries no payment, so the server answers `402 Payment Required` and describes what it wants. The client then signs an EIP-3009 authorization and repeats the request with that signature attached. That authorization is an EIP-712 signature rather than a transaction, so signing it costs no gas. The server verifies the signature with the facilitator, has the facilitator settle it on chain, and only then runs the tool. ![Sequence diagram of the x402 HTTP payment flow](../images/x402/remix-x402.png) The practical consequence is the cost. Paying for a service on chain yourself means the service fee plus gas. Here you pay the service fee only, and the facilitator covers the gas. ## Paying automatically The `@x402/fetch` library wraps `fetch` and runs the whole exchange for you. It catches the 402, reads the requirements, signs, and retries: ```javascript import { wrapFetchWithPayment, x402Client } from "@x402/fetch"; import { ExactEvmScheme } from "@x402/evm/exact/client"; import { privateKeyToAccount } from "viem/accounts"; import dotenv from "dotenv"; dotenv.config(); // Setup wallet const privateKey = process.env.PRIVATE_KEY; const evmSigner = privateKeyToAccount(privateKey); // Create x402 client const client = new x402Client(); const exactScheme = new ExactEvmScheme(evmSigner); client.register("eip155:8453", exactScheme); // Base mainnet // Wrap fetch with payment handling const x402Fetch = wrapFetchWithPayment(fetch, client); // Make request - payment happens automatically! const response = await x402Fetch("https://api.remix.live/mcp/x402-http/compile", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ sources: { "SimpleStorage.sol": { content: ` // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract SimpleStorage { uint256 public value; function set(uint256 _value) public { value = _value; } function get() public view returns (uint256) { return value; } } ` } } }) }); const result = await response.json(); console.log("Compilation result:", result); ``` The request body is the same as the `compile_solidity` tool takes, and the response is the same shape it returns. See the compiling page in this section for the full reference. ## Paying manually If you would rather drive the exchange yourself, start with an unpaid request: ```bash curl -X POST https://api.remix.live/mcp/x402-http/compile \ -H "Content-Type: application/json" \ -d '{"sources":{"Test.sol":{"content":"pragma solidity ^0.8.0; contract Test {}"}}}' ``` The server replies `402 Payment Required` with what it accepts. Read the values out of that response rather than hardcoding them, since the asset, amount, network, and recipient all come from the server. Sending that unpaid request costs nothing, so you can see the real answer here: ```{only} html
``` Trimmed, it looks like this: ```json { "x402Version": 2, "resource": { "url": "https://..." }, "accepts": [{ "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", "amount": "10000", "network": "eip155:8453", "payTo": "0x4CF33cCB14B43D76b4f672C3feDe297d1d763ace", "scheme": "exact", "maxTimeoutSeconds": 300, "extra": { "name": "USD Coin", "version": "2" } }] } ``` Sign an EIP-712 message with your wallet authorizing that USDC transfer, then send the request again with the signature in a `Payment-Signature` header: ```bash curl -X POST https://api.remix.live/mcp/x402-http/compile \ -H "Content-Type: application/json" \ -H "Payment-Signature: " \ -d '{"sources":{"Test.sol":{"content":"pragma solidity ^0.8.0; contract Test {}"}}}' ``` This time the call goes through: ```text { "success": true, "contracts": { "Test.sol": { "Test": { "abi": [...], "evm": {...} } } }, "version": "v0.8.35+commit.47b9dedd" } ``` ## The facilitator A facilitator is a payment settlement service. It verifies EIP-3009 payment signatures, executes the USDC transfer on chain, pays the gas for that transfer, and confirms the transaction back to the server. From a client's point of view the facilitator is invisible. You send a payment signature, and the server handles everything else. There is nothing to configure on your side. ### Running your own server If you are running the server rather than calling the hosted one, it settles through the CDP Facilitator at `https://api.cdp.coinbase.com/platform/v2/x402`, which supports both testnet and mainnet and authenticates with JWT and Ed25519 signing. It also catalogs your service automatically on agentic.market. Sign up at the [Coinbase Developer Platform](https://portal.cdp.coinbase.com/), create an API key, and set the credentials before starting the server: ```bash CDP_API_KEY_ID=your_api_key_id CDP_API_KEY_SECRET=your_api_key_secret ``` The startup log confirms which facilitator is in use: ```text 🔐 Facilitator: CDP - https://api.cdp.coinbase.com/platform/v2/x402 ``` ## Network details The hosted service settles on **Base mainnet**, chain ID 8453, in real USDC. Confirm this before you fund a wallet, since it is the value `/info` reports and it is what your client has to register: ```bash curl https://api.remix.live/mcp/x402-http/info ``` A server you run yourself can settle on Base Sepolia instead, chain ID 84532, which is Base's testnet: - **USDC contract**: `0x036CbD53842c5426634e7929541eC2318f3dCF7e` - **RPC**: `https://sepolia.base.org` Get Base Sepolia ETH from the [Alchemy faucet](https://www.alchemy.com/faucets/base-sepolia), then bridge or use a faucet for Base Sepolia USDC. To look up a settled payment, search the transaction hash on a Base block explorer: `basescan.org` for mainnet, or `sepolia.basescan.org` for testnet. ## Errors An unfunded wallet is rejected before any work happens: ```json { "error": "Insufficient USDC balance" } ``` A signature the facilitator cannot verify is rejected the same way: ```json { "error": "Payment verification failed" } ``` Either way, fix the cause and retry. A payment that settles but hits a broken contract still returns a result. Compilation failures come back with `success: false` and the usual `errors` array: ```json { "success": false, "errors": [ { "severity": "error", "message": "ParserError: Expected ';' but got 'identifier'" } ] } ``` ## Security notes - Your private keys never leave your machine. - Signatures are gasless. An EIP-712 signature is not a transaction. - The facilitator pays the gas, not you. - Payments are verified on chain before the service runs. - Pricing is the quoted service fee, with nothing added. The gasless part is the payment. Compilation and analysis involve no other on-chain activity, but the MCP deployment tools do put a contract on chain, and their price includes that deployment gas. ## Further reading - [HTTP x402 endpoint specifications](https://github.com/remix-project-org/x402/blob/main/HTTP_X402_ENDPOINTS.md) - [MCP usage guide](https://github.com/remix-project-org/x402/blob/main/MCP_USAGE.md), for using the server with AI agents - [API reference](https://github.com/remix-project-org/x402/blob/main/API_REFERENCE.md) - Working examples live in `src/examples/` in the server repository, including `compile-http.js` --- ## Advanced ### [Compilation Artifacts](https://remix-ide.readthedocs.io/en/latest/contract_metadata.html) > Understand the JSON compilation artifacts generated by Remix IDE including ABI, bytecode, and metadata for deployed contracts. # Compilation Artifacts When a compilation for a Solidity file succeeds, Remix creates three JSON files for each compiled contract. Files can be seen in the `File Explorers plugin` as: 1. `artifacts/.json`: contains the link to the libraries, the bytecode, the deployed bytecode, the gas estimation, the method identifiers, and the ABI. It is used for linking a library address to the file. 1. `artifacts/.json`: contains the metadata from the output of Solidity compilation. 1. `artifacts/build-info/.json`: contains info about `solc` compiler version, compiler input and output. This file is generated similar to the files generated through Hardhat compilation. You can also try [Hardhat compilation](https://remix-ide.readthedocs.io/en/latest/hardhat.html#enable-hardhat-compilation) from Remix. Please note that in order to generate these artifact files, the **Generate contract metadata** box in the **General settings** section of the **Settings** module needs to be checked. By default, it is checked. You can write scripts that can access either of these files. ## Library deployment with filename.json By default Remix automatically deploys needed libraries. When you open the metadata file for the libraries - **artifact/filename.json** you will see the following sections: `linkReferences` contains a map representing libraries which depend on the current contract. Values are addresses of libraries used for linking the contract. `autoDeployLib` defines if the libraries should be auto deployed by Remix or if the contract should be linked with libraries described in `linkReferences` Note that Remix will resolve addresses corresponding to the current network. By default, a configuration key follows the form: `:`, but it is also possible to define `` or `` as keys. Here is a sample metadata file for linking a library: ```json { "VM:-": { "linkReferences": { "browser/Untitled.sol": { "lib": "
", "lib2": "
" } }, "autoDeployLib": true }, "main:1": { "linkReferences": { "browser/Untitled.sol": { "lib": "
", "lib2": "
" } }, "autoDeployLib": true }, "ropsten:3": { "linkReferences": { "browser/Untitled.sol": { "lib": "
", "lib2": "
" } }, "autoDeployLib": true }, "rinkeby:4": { "linkReferences": { "browser/Untitled.sol": { "lib": "
", "lib2": "
" } }, "autoDeployLib": true }, "kovan:42": { "linkReferences": { "browser/Untitled.sol": { "lib": "
", "lib2": "
" } }, "autoDeployLib": true }, "data": { "bytecode": { "linkReferences": {}, "object": "608060405234801561001057600080fd5b506040516108723803806108728339818101604052602081101561003357600080fd5b8101908080519060200190929190505050336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060018060008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001819055508060ff166002816100fd9190610104565b5050610157565b81548183558181111561012b5781836000526020600020918201910161012a9190610130565b5b505050565b61015491905b808211156101505760008082016000905550600101610136565b5090565b90565b61070c806101666000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80635c19a95c14610051578063609ff1bd146100955780639e7b8d61146100b9578063b3f98adc146100fd575b600080fd5b6100936004803603602081101561006757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061012e565b005b61009d610481565b604051808260ff1660ff16815260200191505060405180910390f35b6100fb600480360360208110156100cf57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506104f9565b005b61012c6004803603602081101561011357600080fd5b81019080803560ff1690602001909291905050506105f6565b005b6000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060010160009054906101000a900460ff161561018e575061047e565b5b600073ffffffffffffffffffffffffffffffffffffffff16600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141580156102bc57503373ffffffffffffffffffffffffffffffffffffffff16600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b1561032b57600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160029054906101000a900473ffffffffffffffffffffffffffffffffffffffff16915061018f565b3373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610365575061047e565b60018160010160006101000a81548160ff021916908315150217905550818160010160026101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060010160009054906101000a900460ff161561046457816000015460028260010160019054906101000a900460ff1660ff168154811061044557fe5b906000526020600020016000016000828254019250508190555061047b565b816000015481600001600082825401925050819055505b50505b50565b6000806000905060008090505b6002805490508160ff1610156104f4578160028260ff16815481106104af57fe5b906000526020600020016000015411156104e75760028160ff16815481106104d357fe5b906000526020600020016000015491508092505b808060010191505061048e565b505090565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415806105a15750600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160009054906101000a900460ff165b156105ab576105f3565b60018060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001819055505b50565b6000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060010160009054906101000a900460ff168061065e57506002805490508260ff1610155b1561066957506106d4565b60018160010160006101000a81548160ff021916908315150217905550818160010160016101000a81548160ff021916908360ff160217905550806000015460028360ff16815481106106b857fe5b9060005260206000200160000160008282540192505081905550505b5056fea265627a7a72315820457d09494a1d1d64ebd9b931a6c692e671dc1f14d4a0c6600f7aa00fed36011064736f6c634300050b0032", "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x40 MLOAD PUSH2 0x872 CODESIZE SUB DUP1 PUSH2 0x872 DUP4 CODECOPY DUP2 DUP2 ADD PUSH1 0x40 MSTORE PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x33 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP CALLER PUSH1 0x0 DUP1 PUSH2 0x100 EXP DUP2 SLOAD DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF MUL NOT AND SWAP1 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND MUL OR SWAP1 SSTORE POP PUSH1 0x1 DUP1 PUSH1 0x0 DUP1 PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 ADD DUP2 SWAP1 SSTORE POP DUP1 PUSH1 0xFF AND PUSH1 0x2 DUP2 PUSH2 0xFD SWAP2 SWAP1 PUSH2 0x104 JUMP JUMPDEST POP POP PUSH2 0x157 JUMP JUMPDEST DUP2 SLOAD DUP2 DUP4 SSTORE DUP2 DUP2 GT ISZERO PUSH2 0x12B JUMPI DUP2 DUP4 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 SWAP2 DUP3 ADD SWAP2 ADD PUSH2 0x12A SWAP2 SWAP1 PUSH2 0x130 JUMP JUMPDEST JUMPDEST POP POP POP JUMP JUMPDEST PUSH2 0x154 SWAP2 SWAP1 JUMPDEST DUP1 DUP3 GT ISZERO PUSH2 0x150 JUMPI PUSH1 0x0 DUP1 DUP3 ADD PUSH1 0x0 SWAP1 SSTORE POP PUSH1 0x1 ADD PUSH2 0x136 JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST SWAP1 JUMP JUMPDEST PUSH2 0x70C DUP1 PUSH2 0x166 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0x4C JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x5C19A95C EQ PUSH2 0x51 JUMPI DUP1 PUSH4 0x609FF1BD EQ PUSH2 0x95 JUMPI DUP1 PUSH4 0x9E7B8D61 EQ PUSH2 0xB9 JUMPI DUP1 PUSH4 0xB3F98ADC EQ PUSH2 0xFD JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x93 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x67 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x12E JUMP JUMPDEST STOP JUMPDEST PUSH2 0x9D PUSH2 0x481 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 PUSH1 0xFF AND PUSH1 0xFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0xFB PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0xCF JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x4F9 JUMP JUMPDEST STOP JUMPDEST PUSH2 0x12C PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x113 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH1 0xFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x5F6 JUMP JUMPDEST STOP JUMPDEST PUSH1 0x0 PUSH1 0x1 PUSH1 0x0 CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SWAP1 POP DUP1 PUSH1 0x1 ADD PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH1 0xFF AND ISZERO PUSH2 0x18E JUMPI POP PUSH2 0x47E JUMP JUMPDEST JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH1 0x1 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x1 ADD PUSH1 0x2 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO DUP1 ISZERO PUSH2 0x2BC JUMPI POP CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH1 0x1 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x1 ADD PUSH1 0x2 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO JUMPDEST ISZERO PUSH2 0x32B JUMPI PUSH1 0x1 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x1 ADD PUSH1 0x2 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP2 POP PUSH2 0x18F JUMP JUMPDEST CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0x365 JUMPI POP PUSH2 0x47E JUMP JUMPDEST PUSH1 0x1 DUP2 PUSH1 0x1 ADD PUSH1 0x0 PUSH2 0x100 EXP DUP2 SLOAD DUP2 PUSH1 0xFF MUL NOT AND SWAP1 DUP4 ISZERO ISZERO MUL OR SWAP1 SSTORE POP DUP2 DUP2 PUSH1 0x1 ADD PUSH1 0x2 PUSH2 0x100 EXP DUP2 SLOAD DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF MUL NOT AND SWAP1 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND MUL OR SWAP1 SSTORE POP PUSH1 0x0 PUSH1 0x1 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SWAP1 POP DUP1 PUSH1 0x1 ADD PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH1 0xFF AND ISZERO PUSH2 0x464 JUMPI DUP2 PUSH1 0x0 ADD SLOAD PUSH1 0x2 DUP3 PUSH1 0x1 ADD PUSH1 0x1 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH1 0xFF AND PUSH1 0xFF AND DUP2 SLOAD DUP2 LT PUSH2 0x445 JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 ADD PUSH1 0x0 ADD PUSH1 0x0 DUP3 DUP3 SLOAD ADD SWAP3 POP POP DUP2 SWAP1 SSTORE POP PUSH2 0x47B JUMP JUMPDEST DUP2 PUSH1 0x0 ADD SLOAD DUP2 PUSH1 0x0 ADD PUSH1 0x0 DUP3 DUP3 SLOAD ADD SWAP3 POP POP DUP2 SWAP1 SSTORE POP JUMPDEST POP POP JUMPDEST POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 SWAP1 POP PUSH1 0x0 DUP1 SWAP1 POP JUMPDEST PUSH1 0x2 DUP1 SLOAD SWAP1 POP DUP2 PUSH1 0xFF AND LT ISZERO PUSH2 0x4F4 JUMPI DUP2 PUSH1 0x2 DUP3 PUSH1 0xFF AND DUP2 SLOAD DUP2 LT PUSH2 0x4AF JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 ADD PUSH1 0x0 ADD SLOAD GT ISZERO PUSH2 0x4E7 JUMPI PUSH1 0x2 DUP2 PUSH1 0xFF AND DUP2 SLOAD DUP2 LT PUSH2 0x4D3 JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 ADD PUSH1 0x0 ADD SLOAD SWAP2 POP DUP1 SWAP3 POP JUMPDEST DUP1 DUP1 PUSH1 0x1 ADD SWAP2 POP POP PUSH2 0x48E JUMP JUMPDEST POP POP SWAP1 JUMP JUMPDEST PUSH1 0x0 DUP1 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO DUP1 PUSH2 0x5A1 JUMPI POP PUSH1 0x1 PUSH1 0x0 DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x1 ADD PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH1 0xFF AND JUMPDEST ISZERO PUSH2 0x5AB JUMPI PUSH2 0x5F3 JUMP JUMPDEST PUSH1 0x1 DUP1 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 ADD DUP2 SWAP1 SSTORE POP JUMPDEST POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 PUSH1 0x0 CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SWAP1 POP DUP1 PUSH1 0x1 ADD PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH1 0xFF AND DUP1 PUSH2 0x65E JUMPI POP PUSH1 0x2 DUP1 SLOAD SWAP1 POP DUP3 PUSH1 0xFF AND LT ISZERO JUMPDEST ISZERO PUSH2 0x669 JUMPI POP PUSH2 0x6D4 JUMP JUMPDEST PUSH1 0x1 DUP2 PUSH1 0x1 ADD PUSH1 0x0 PUSH2 0x100 EXP DUP2 SLOAD DUP2 PUSH1 0xFF MUL NOT AND SWAP1 DUP4 ISZERO ISZERO MUL OR SWAP1 SSTORE POP DUP2 DUP2 PUSH1 0x1 ADD PUSH1 0x1 PUSH2 0x100 EXP DUP2 SLOAD DUP2 PUSH1 0xFF MUL NOT AND SWAP1 DUP4 PUSH1 0xFF AND MUL OR SWAP1 SSTORE POP DUP1 PUSH1 0x0 ADD SLOAD PUSH1 0x2 DUP4 PUSH1 0xFF AND DUP2 SLOAD DUP2 LT PUSH2 0x6B8 JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 ADD PUSH1 0x0 ADD PUSH1 0x0 DUP3 DUP3 SLOAD ADD SWAP3 POP POP DUP2 SWAP1 SSTORE POP POP JUMPDEST POP JUMP INVALID LOG2 PUSH6 0x627A7A723158 KECCAK256 GASLIMIT PUSH30 0x9494A1D1D64EBD9B931A6C692E671DC1F14D4A0C6600F7AA00FED360110 PUSH5 0x736F6C6343 STOP SDIV SIGNEXTEND STOP ORIGIN ", "sourceMap": "33:2130:0:-;;;382:163;8:9:-1;5:2;;;30:1;27;20:12;5:2;382:163:0;;;;;;;;;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;382:163:0;;;;;;;;;;;;;;;;446:10;432:11;;:24;;;;;;;;;;;;;;;;;;495:1;466:6;:19;473:11;;;;;;;;;;;466:19;;;;;;;;;;;;;;;:26;;:30;;;;525:13;506:32;;:9;:32;;;;;:::i;:::-;;382:163;33:2130;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;" }, "deployedBytecode": { "linkReferences": {}, "object": "608060405234801561001057600080fd5b506004361061004c5760003560e01c80635c19a95c14610051578063609ff1bd146100955780639e7b8d61146100b9578063b3f98adc146100fd575b600080fd5b6100936004803603602081101561006757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061012e565b005b61009d610481565b604051808260ff1660ff16815260200191505060405180910390f35b6100fb600480360360208110156100cf57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506104f9565b005b61012c6004803603602081101561011357600080fd5b81019080803560ff1690602001909291905050506105f6565b005b6000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060010160009054906101000a900460ff161561018e575061047e565b5b600073ffffffffffffffffffffffffffffffffffffffff16600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141580156102bc57503373ffffffffffffffffffffffffffffffffffffffff16600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160029054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b1561032b57600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160029054906101000a900473ffffffffffffffffffffffffffffffffffffffff16915061018f565b3373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610365575061047e565b60018160010160006101000a81548160ff021916908315150217905550818160010160026101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060010160009054906101000a900460ff161561046457816000015460028260010160019054906101000a900460ff1660ff168154811061044557fe5b906000526020600020016000016000828254019250508190555061047b565b816000015481600001600082825401925050819055505b50505b50565b6000806000905060008090505b6002805490508160ff1610156104f4578160028260ff16815481106104af57fe5b906000526020600020016000015411156104e75760028160ff16815481106104d357fe5b906000526020600020016000015491508092505b808060010191505061048e565b505090565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415806105a15750600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160009054906101000a900460ff165b156105ab576105f3565b60018060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001819055505b50565b6000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060010160009054906101000a900460ff168061065e57506002805490508260ff1610155b1561066957506106d4565b60018160010160006101000a81548160ff021916908315150217905550818160010160016101000a81548160ff021916908360ff160217905550806000015460028360ff16815481106106b857fe5b9060005260206000200160000160008282540192505081905550505b5056fea265627a7a72315820457d09494a1d1d64ebd9b931a6c692e671dc1f14d4a0c6600f7aa00fed36011064736f6c634300050b0032", "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0x4C JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x5C19A95C EQ PUSH2 0x51 JUMPI DUP1 PUSH4 0x609FF1BD EQ PUSH2 0x95 JUMPI DUP1 PUSH4 0x9E7B8D61 EQ PUSH2 0xB9 JUMPI DUP1 PUSH4 0xB3F98ADC EQ PUSH2 0xFD JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x93 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x67 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x12E JUMP JUMPDEST STOP JUMPDEST PUSH2 0x9D PUSH2 0x481 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 PUSH1 0xFF AND PUSH1 0xFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0xFB PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0xCF JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x4F9 JUMP JUMPDEST STOP JUMPDEST PUSH2 0x12C PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x113 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD PUSH1 0xFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x5F6 JUMP JUMPDEST STOP JUMPDEST PUSH1 0x0 PUSH1 0x1 PUSH1 0x0 CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SWAP1 POP DUP1 PUSH1 0x1 ADD PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH1 0xFF AND ISZERO PUSH2 0x18E JUMPI POP PUSH2 0x47E JUMP JUMPDEST JUMPDEST PUSH1 0x0 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH1 0x1 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x1 ADD PUSH1 0x2 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO DUP1 ISZERO PUSH2 0x2BC JUMPI POP CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH1 0x1 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x1 ADD PUSH1 0x2 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO JUMPDEST ISZERO PUSH2 0x32B JUMPI PUSH1 0x1 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x1 ADD PUSH1 0x2 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP2 POP PUSH2 0x18F JUMP JUMPDEST CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0x365 JUMPI POP PUSH2 0x47E JUMP JUMPDEST PUSH1 0x1 DUP2 PUSH1 0x1 ADD PUSH1 0x0 PUSH2 0x100 EXP DUP2 SLOAD DUP2 PUSH1 0xFF MUL NOT AND SWAP1 DUP4 ISZERO ISZERO MUL OR SWAP1 SSTORE POP DUP2 DUP2 PUSH1 0x1 ADD PUSH1 0x2 PUSH2 0x100 EXP DUP2 SLOAD DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF MUL NOT AND SWAP1 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND MUL OR SWAP1 SSTORE POP PUSH1 0x0 PUSH1 0x1 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SWAP1 POP DUP1 PUSH1 0x1 ADD PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH1 0xFF AND ISZERO PUSH2 0x464 JUMPI DUP2 PUSH1 0x0 ADD SLOAD PUSH1 0x2 DUP3 PUSH1 0x1 ADD PUSH1 0x1 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH1 0xFF AND PUSH1 0xFF AND DUP2 SLOAD DUP2 LT PUSH2 0x445 JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 ADD PUSH1 0x0 ADD PUSH1 0x0 DUP3 DUP3 SLOAD ADD SWAP3 POP POP DUP2 SWAP1 SSTORE POP PUSH2 0x47B JUMP JUMPDEST DUP2 PUSH1 0x0 ADD SLOAD DUP2 PUSH1 0x0 ADD PUSH1 0x0 DUP3 DUP3 SLOAD ADD SWAP3 POP POP DUP2 SWAP1 SSTORE POP JUMPDEST POP POP JUMPDEST POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 SWAP1 POP PUSH1 0x0 DUP1 SWAP1 POP JUMPDEST PUSH1 0x2 DUP1 SLOAD SWAP1 POP DUP2 PUSH1 0xFF AND LT ISZERO PUSH2 0x4F4 JUMPI DUP2 PUSH1 0x2 DUP3 PUSH1 0xFF AND DUP2 SLOAD DUP2 LT PUSH2 0x4AF JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 ADD PUSH1 0x0 ADD SLOAD GT ISZERO PUSH2 0x4E7 JUMPI PUSH1 0x2 DUP2 PUSH1 0xFF AND DUP2 SLOAD DUP2 LT PUSH2 0x4D3 JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 ADD PUSH1 0x0 ADD SLOAD SWAP2 POP DUP1 SWAP3 POP JUMPDEST DUP1 DUP1 PUSH1 0x1 ADD SWAP2 POP POP PUSH2 0x48E JUMP JUMPDEST POP POP SWAP1 JUMP JUMPDEST PUSH1 0x0 DUP1 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO DUP1 PUSH2 0x5A1 JUMPI POP PUSH1 0x1 PUSH1 0x0 DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x1 ADD PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH1 0xFF AND JUMPDEST ISZERO PUSH2 0x5AB JUMPI PUSH2 0x5F3 JUMP JUMPDEST PUSH1 0x1 DUP1 PUSH1 0x0 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 ADD DUP2 SWAP1 SSTORE POP JUMPDEST POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 PUSH1 0x0 CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SWAP1 POP DUP1 PUSH1 0x1 ADD PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH1 0xFF AND DUP1 PUSH2 0x65E JUMPI POP PUSH1 0x2 DUP1 SLOAD SWAP1 POP DUP3 PUSH1 0xFF AND LT ISZERO JUMPDEST ISZERO PUSH2 0x669 JUMPI POP PUSH2 0x6D4 JUMP JUMPDEST PUSH1 0x1 DUP2 PUSH1 0x1 ADD PUSH1 0x0 PUSH2 0x100 EXP DUP2 SLOAD DUP2 PUSH1 0xFF MUL NOT AND SWAP1 DUP4 ISZERO ISZERO MUL OR SWAP1 SSTORE POP DUP2 DUP2 PUSH1 0x1 ADD PUSH1 0x1 PUSH2 0x100 EXP DUP2 SLOAD DUP2 PUSH1 0xFF MUL NOT AND SWAP1 DUP4 PUSH1 0xFF AND MUL OR SWAP1 SSTORE POP DUP1 PUSH1 0x0 ADD SLOAD PUSH1 0x2 DUP4 PUSH1 0xFF AND DUP2 SLOAD DUP2 LT PUSH2 0x6B8 JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 KECCAK256 ADD PUSH1 0x0 ADD PUSH1 0x0 DUP3 DUP3 SLOAD ADD SWAP3 POP POP DUP2 SWAP1 SSTORE POP POP JUMPDEST POP JUMP INVALID LOG2 PUSH6 0x627A7A723158 KECCAK256 GASLIMIT PUSH30 0x9494A1D1D64EBD9B931A6C692E671DC1F14D4A0C6600F7AA00FED360110 PUSH5 0x736F6C6343 STOP SDIV SIGNEXTEND STOP ORIGIN ", "sourceMap": "33:2130:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;33:2130:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;872:577;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;872:577:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;1801:360;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;655:164;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;655:164:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;1509:286;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;1509:286:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;872:577;919:20;942:6;:18;949:10;942:18;;;;;;;;;;;;;;;919:41;;995:6;:12;;;;;;;;;;;;991:25;;;1009:7;;;991:25;1025:115;1063:1;1032:33;;:6;:10;1039:2;1032:10;;;;;;;;;;;;;;;:19;;;;;;;;;;;;:33;;;;:70;;;;;1092:10;1069:33;;:6;:10;1076:2;1069:10;;;;;;;;;;;;;;;:19;;;;;;;;;;;;:33;;;;1032:70;1025:115;;;1121:6;:10;1128:2;1121:10;;;;;;;;;;;;;;;:19;;;;;;;;;;;;1116:24;;1025:115;;;1160:10;1154:16;;:2;:16;;;1150:29;;;1172:7;;;1150:29;1203:4;1188:6;:12;;;:19;;;;;;;;;;;;;;;;;;1235:2;1217:6;:15;;;:20;;;;;;;;;;;;;;;;;;1247:24;1274:6;:10;1281:2;1274:10;;;;;;;;;;;;;;;1247:37;;1298:10;:16;;;;;;;;;;;;1294:148;;;1368:6;:13;;;1328:9;1338:10;:15;;;;;;;;;;;;1328:26;;;;;;;;;;;;;;;;;:36;;;:53;;;;;;;;;;;1294:148;;;1429:6;:13;;;1408:10;:17;;;:34;;;;;;;;;;;1294:148;872:577;;;;:::o;1801:360::-;1849:22;1883:24;1910:1;1883:28;;1926:10;1939:1;1926:14;;1921:234;1949:9;:16;;;;1942:4;:23;;;1921:234;;;2019:16;1991:9;2001:4;1991:15;;;;;;;;;;;;;;;;;:25;;;:44;1987:168;;;2074:9;2084:4;2074:15;;;;;;;;;;;;;;;;;:25;;;2055:44;;2136:4;2117:23;;1987:168;1967:6;;;;;;;1921:234;;;;1801:360;;:::o;655:164::-;732:11;;;;;;;;;;;718:25;;:10;:25;;;;:50;;;;747:6;:15;754:7;747:15;;;;;;;;;;;;;;;:21;;;;;;;;;;;;718:50;714:63;;;770:7;;714:63;811:1;786:6;:15;793:7;786:15;;;;;;;;;;;;;;;:22;;:26;;;;655:164;;:::o;1509:286::-;1558:20;1581:6;:18;1588:10;1581:18;;;;;;;;;;;;;;;1558:41;;1613:6;:12;;;;;;;;;;;;:46;;;;1643:9;:16;;;;1629:10;:30;;;;1613:46;1609:59;;;1661:7;;;1609:59;1692:4;1677:6;:12;;;:19;;;;;;;;;;;;;;;;;;1720:10;1706:6;:11;;;:24;;;;;;;;;;;;;;;;;;1775:6;:13;;;1740:9;1750:10;1740:21;;;;;;;;;;;;;;;;;:31;;;:48;;;;;;;;;;;1509:286;;;:::o" }, "gasEstimates": { "creation": { "codeDepositCost": "360800", "executionCost": "infinite", "totalCost": "infinite" }, "external": { "delegate(address)": "infinite", "giveRightToVote(address)": "20997", "vote(uint8)": "62215", "winningProposal()": "infinite" } }, "methodIdentifiers": { "delegate(address)": "5c19a95c", "giveRightToVote(address)": "9e7b8d61", "vote(uint8)": "b3f98adc", "winningProposal()": "609ff1bd" } }, "abi": [ { "constant": false, "inputs": [ { "internalType": "address", "name": "to", "type": "address" } ], "name": "delegate", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { "constant": true, "inputs": [], "name": "winningProposal", "outputs": [ { "internalType": "uint8", "name": "_winningProposal", "type": "uint8" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": false, "inputs": [ { "internalType": "address", "name": "toVoter", "type": "address" } ], "name": "giveRightToVote", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { "constant": false, "inputs": [ { "internalType": "uint8", "name": "toProposal", "type": "uint8" } ], "name": "vote", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "uint8", "name": "_numProposals", "type": "uint8" } ], "payable": false, "stateMutability": "nonpayable", "type": "constructor" } ] } ``` ### [Remix Commands](https://remix-ide.readthedocs.io/en/latest/remix_commands.html) > Console commands available in Remix IDE for loading files, running scripts, and interacting with web3 and ethers libraries. # Remix Commands In the console, you can run the commands listed below. Once you start to type a command, there is _auto complete_. These commands are using the following libraries: `remix`: Remix has a number of CLI commands for loading & executing file in a workspace. See the list below. `ethers`: Remix IDE enables the use of ethersjs commands. See the [Ethers docs](https://docs.ethers.org/v6/) for the full list. `web3`: Remix IDE enables the use of web3js commands. See the [Web3js docs](https://web3js.readthedocs.io/) for the full list. `swarmgw`: This library can be used to upload/download files to Swarm via https://swarm-gateways.net/. ## Commands `remix.execute(filepath)`: Run the script specified by file path. If filepath is empty, script currently displayed in the editor is executed. `remix.exeCurrent()`: Run the script currently displayed in the editor. `remix.getFile(path)`: Returns the content of the file located at the given path `remix.help()`: Display this help message. `remix.loadgist(id)`: Load a gist in the File Explorer. `remix.loadurl(url)`: Load the given URL in the File Explorer. The URL can be of type `github`, `swarm` or `ipfs`. ### A few ethers JS examples `ethers.providers`: A Provider abstracts a connection to the Ethereum blockchain, for issuing queries and sending state changing transactions. `ethers.utils`: The utility functions exposed in both the ethers umbrella package and the ethers-utils. eg ethers.utils.formatBytes32String( text ) ### A few Web3 JS examples `web3.eth.abi`: The web3.eth.abi functions let you de- and encode parameters to ABI (Application Binary Interface) for function calls to the EVM (Ethereum Virtual Machine). `web3.providers`: Contains the current available providers. `web3.utils`: This package provides utility functions for Ethereum dApps and other \*\*web3.js packages. ### A few Swarm examples (these will be updated soon) `swarmgw.get(url, cb)`: Download files from Swarm via https\*\*://swarm-gateways.net/ `swarmgw.put(content, cb)`: Upload files to Swarm via https\*\*://swarm-gateways.net/ --- ## Miscellaneous ### [Plugin List](https://remix-ide.readthedocs.io/en/latest/plugin_list.html) > Complete list of plugins available in Remix IDE's Plugin Manager for extending the IDE with additional tools and functionality. # Plugin List Here is the list of Remix plugins that you will see in the Plugin Manager. ```{tip} Click a card to open the Remix IDE with the plugin enabled. ``` ## Internal plugins These are plugins that are managed by the Remix team. ::::{grid} 3 :gutter: 4 :::{grid-item-card} Contract Verification :columns: 12 6 4 4 :class-card: plugin-card sd-border-1 sd-rounded-2 :link-type: url :link: https://app.remix.live/?#activate=contract-verification :img-top: images/plugin-list/contractVerification.webp Verify contract code on Sourcify, Etherscan and Blockscout at the same time. - [Documentation](https://remix-ide.readthedocs.io/en/latest/contract_verification.html) - Profile name: **contract-verification** ::: :::{grid-item-card} Debugger :columns: 12 6 4 4 :class-card: plugin-card sd-border-1 sd-rounded-2 :link-type: url :link: https://app.remix.live/?#activate=debugger :img-top: images/plugin-list/debuggerLogo.webp Insert breakpoints, step through a contract, and debug transactions. - [Documentation](https://remix-ide.readthedocs.io/en/latest/debugger.html) - Profile name: **debugger** ::: :::{grid-item-card} Deploy & Run :columns: 12 6 4 4 :class-card: plugin-card sd-border-1 sd-rounded-2 :link-type: url :link: https://app.remix.live/?#activate=udapp :img-top: images/plugin-list/deployAndRun.webp Deploy & interact with smart contracts on the in-browser chain (JSVM), local nodes, and public networks. - [Documentation](https://remix-ide.readthedocs.io/en/latest/run.html) - Profile name: **udapp** ::: :::{grid-item-card} File Explorer :columns: 12 6 4 4 :class-card: plugin-card sd-border-1 sd-rounded-2 :link-type: url :link: https://app.remix.live/?#activate=fileManager :img-top: images/plugin-list/fileManager.webp The File Explorer is where you can see the files. - [Documentation](https://remix-ide.readthedocs.io/en/latest/file_explorer.html) - Profile name: **fileManager** ::: :::{grid-item-card} Git plugin :columns: 12 6 4 4 :class-card: plugin-card sd-border-1 sd-rounded-2 :link-type: url :link: https://app.remix.live/?#activate=dgit :img-top: images/plugin-list/Git-logo-black.png Enables version control using Git. - [Documentation](https://remix-ide.readthedocs.io/en/latest/git.html) - Profile name: **dgit** ::: :::{grid-item-card} Solidity Compiler :columns: 12 6 4 4 :class-card: plugin-card sd-border-1 sd-rounded-2 :link-type: url :link: https://app.remix.live/?#activate=solidity :img-top: images/plugin-list/solidity.webp Compiles Solidity & Yul. - [Documentation](https://remix-ide.readthedocs.io/en/latest/compile.html) - Profile name: **solidity** ::: :::{grid-item-card} Solidity Static Analysis :columns: 12 6 4 4 :class-card: plugin-card sd-border-1 sd-rounded-2 :link-type: url :link: https://app.remix.live/?#activate=solidityStaticAnalysis :img-top: images/plugin-list/staticAnalysis.webp Static code analysis with integrations for **Slither** and **Solhint**. - [Documentation](https://remix-ide.readthedocs.io/en/latest/static_analysis.html) - Profile name: **solidityStaticAnalysis** ::: :::{grid-item-card} Solidity Unit Testing :columns: 12 6 4 4 :class-card: plugin-card sd-border-1 sd-rounded-2 :link-type: url :link: https://app.remix.live/?#activate=solidityUnitTesting :img-top: images/plugin-list/pi-sut.png Run unit tests written in Solidity. - [Documentation](https://remix-ide.readthedocs.io/en/latest/unittesting.html) - Profile name: **solidityUnitTesting** ::: :::{grid-item-card} Vyper Compiler :columns: 12 6 4 4 :class-card: plugin-card sd-border-1 sd-rounded-2 :link-type: url :link: https://app.remix.live/?#activate=vyper :img-top: images/plugin-list/vyperLogo2.webp Compile Vyper code using local or remote Vyper compiler. - [Documentation](https://remix-ide.readthedocs.io/en/latest/vyper.html) - Profile name: **vyper** ::: :::{grid-item-card} Workspace Templates :columns: 12 6 4 4 :class-card: plugin-card sd-border-1 sd-rounded-2 :link-type: url :link: https://app.remix.live/?#activate=templateSelection :img-top: images/plugin-list/bgRemi.webp Create workspaces from existing templates like the OpenZeppelin ERC20 template. - Profile name: **templateSelection** ::: :::{grid-item-card} Plugin Manager :columns: 12 6 4 4 :class-card: plugin-card sd-border-1 sd-rounded-2 :link-type: url :img-top: images/plugin-list/pluginManager.webp :link: https://app.remix.live/?#activate=pluginManager Displays a list of all available plugins. Profile name: **pluginManager** ::: :::{grid-item-card} Slither :columns: 12 6 4 4 :class-card: plugin-card sd-border-1 sd-rounded-2 :link-type: url :img-top: images/plugin-list/slither-logo.png :link: https://app.remix.live/?#activate=solidityStaticAnalysis This plugin is now part of the Solidity Analyzers plugin. ::: :::{grid-item-card} Solhint :columns: 12 6 4 4 :class-card: plugin-card sd-border-1 sd-rounded-2 :link-type: url :img-top: images/plugin-list/solhint.png :link: https://app.remix.live/?#activate=solidityStaticAnalysis This plugin is now part of the Solidity Analyzers plugin. ::: :::{grid-item-card} LearnEth :columns: 12 6 4 4 :class-card: plugin-card sd-border-1 sd-rounded-2 :link-type: url :link: https://app.remix.live/?#activate=LearnEth :img-top: images/plugin-list/learnEthLogo.webp Remix, Solidity, & blockchain tutorials with quizzes teaching Solidity and Remix features. - Profile name: **LearnEth** ::: :::{grid-item-card} Circom Compiler :columns: 12 6 4 4 :class-card: plugin-card sd-border-1 sd-rounded-2 :link-type: url :link: https://app.remix.live/?#activate=circuit-compiler :img-top: images/plugin-list/circom-compiler-logo.png Write, compile, and generate proofs for Zero-Knowledge (ZK) circuits using the Circom language. - [Documentation](https://iden3.io/circom) - Profile name: **circuit-compiler** ::: :::{grid-item-card} Noir Compiler :columns: 12 6 4 4 :class-card: plugin-card sd-border-1 sd-rounded-2 :link-type: url :link: https://app.remix.live/?#activate=noir-compiler :img-top: images/plugin-list/noir-compiler.png Enables support for Noir circuit compilation. - [Documentation](https://noir-lang.org/docs/) - Profile name: **noir-compiler** ::: :::: ## External plugins These are the plugins that are managed by external teams. ::::{grid} 3 :gutter: 4 :::{grid-item-card} Arbitrum Stylus :columns: 12 6 4 4 :class-card: plugin-card sd-border-1 sd-rounded-2 :link-type: url :link: https://app.remix.live/?#activate=remix-plugin-arbitrum :img-top: images/plugin-list/arbitrum-arb-logo.png Deployment and execution of smart contracts via Arbitrum Stylus. - [Website](https://docs.welldonestudio.io/code) - Profile name: **remix-plugin-arbitrum** ::: :::{grid-item-card} BuildBear :columns: 12 6 4 4 :class-card: plugin-card sd-border-1 sd-rounded-2 :link-type: url :link: https://app.remix.live/?#activate=buildbear :img-top: images/plugin-list/build_bear.jpg Create private, forked testnets from any EVM chain with explorer, faucet, and RPC. - [Documentation](https://www.buildbear.io/resources/guides-and-tutorials/remix_plugin) - Profile name: **buildbear** ::: :::{grid-item-card} Cookbook.dev — Find any contract :columns: 12 6 4 4 :class-card: plugin-card sd-border-1 sd-rounded-2 :link-type: url :link: https://app.remix.live/?#activate=cookbook.dev :img-top: images/plugin-list/cookbook.svg Find any smart contract, build your project faster. - [Website](https://github.com/CookbookDev/cookbook-remix-plugin) - Profile name: **cookbook.dev** ::: :::{grid-item-card} COTI Plugin :columns: 12 6 4 4 :class-card: plugin-card sd-border-1 sd-rounded-2 :link-type: url :link: https://app.remix.live/?#activate=coti-remix-plugin :img-top: images/plugin-list/coti-logo.webp Develop and test privacy-preserving smart contracts on the COTI network. - [Documentation](https://docs.coti.io/coti-documentation) - Profile name: **coti-remix-plugin** ::: :::{grid-item-card} Contract Deployer :columns: 12 6 4 4 :class-card: plugin-card sd-border-1 sd-rounded-2 :link-type: url :link: https://app.remix.live/?#activate=contract_deployer :img-top: images/plugin-list/contract-deployer.webp Deploy a contract to multiple chains (one at a time) with the same address. - [Documentation](https://github.com/groksmith/remix-contract-deployer-plugin) - Profile name: **contract_deployer** ::: :::{grid-item-card} Defender Deploy :columns: 12 6 4 4 :class-card: plugin-card sd-border-1 sd-rounded-2 :link-type: url :link: https://app.remix.live/?#activate=defender-deploy Deploy smart contracts using OpenZeppelin Defender from Remix IDE. - [Documentation](https://docs.openzeppelin.com/defender/remix-plugin) - Profile name: **defender-deploy** ::: :::{grid-item-card} Klaytn :columns: 12 6 4 4 :class-card: plugin-card sd-border-1 sd-rounded-2 :link-type: url :link: https://app.remix.live/?#activate=klaytn-remix-plugin :img-top: images/plugin-list/klatyn-logo.webp Deploy and interact with smart contracts on the Klaytn public network and local nodes. - [Website](https://github.com/klaytn-ozys/plug-and-klay) - Profile name: **klaytn-remix-plugin** ::: :::{grid-item-card} Nahmii compiler :columns: 12 6 4 4 :class-card: plugin-card sd-border-1 sd-rounded-2 :link-type: url :link: https://app.remix.live/?#activate=nahmii-compiler :img-top: images/plugin-list/nahi-compiler-logo.png Compile Solidity contracts for the Nahmii network. - [Documentation](https://docs.n3.nahmii.io/docs/category/nahmii-30) - [Open an issue](https://github.com/nahmii-community/remix-nahmii-compiler-plugin/issues) - Profile name: **nahmii-compiler** ::: :::{grid-item-card} Sentio :columns: 12 6 4 4 :class-card: plugin-card sd-border-1 sd-rounded-2 :link-type: url :link: https://app.remix.live/?#activate=sentio :img-top: images/plugin-list/sentio-logo.png Monitor and analyze your smart contracts inside Remix using Sentio. - [Documentation](https://docs.sentio.xyz/docs/remix-ide-plugin) - Profile name: **sentio** ::: :::{grid-item-card} SolidityScan :columns: 12 6 4 4 :class-card: plugin-card sd-border-1 sd-rounded-2 :link-type: url :link: https://app.remix.live/?#activate=solidityscan Real-time security analysis of your Solidity smart contracts. - [Documentation](https://docs.solidityscan.com/remix/) - Profile name: **solidityscan** ::: :::{grid-item-card} Starknet :columns: 12 6 4 4 :class-card: plugin-card sd-border-1 sd-rounded-2 :link-type: url :link: https://app.remix.live/?#activate=Starknet :img-top: images/plugin-list/starknetlogo.webp Compile contracts written in Cairo to Starknet. - [Website](https://github.com/NethermindEth/starknet-remix-plugin) - Profile name: **Starknet** ::: :::{grid-item-card} Tenderly :columns: 12 6 4 4 :class-card: plugin-card sd-border-1 sd-rounded-2 :link-type: url :link: https://app.remix.live/?#activate=tenderly :img-top: images/plugin-list/tenderly-logo.png Verify contracts and import from your Tenderly project. - [Documentation](https://docs.tenderly.co/introduction) - Profile name: **tenderly** ::: :::{grid-item-card} Wallet Connect (Main Panel) :columns: 12 6 4 4 :class-card: plugin-card sd-border-1 sd-rounded-2 :link-type: url :link: https://app.remix.live/?#activate=walletconnect Approve transactions on your mobile device. - [Website](https://github.com/yann300/remix-walletconnect/issues) - Profile name: **walletconnect** ::: :::{grid-item-card} Zokrates :columns: 12 6 4 4 :class-card: plugin-card sd-border-1 sd-rounded-2 :link-type: url :link: https://app.remix.live/?#activate=ZoKrates :img-top: images/plugin-list/zokrates-logo.png Zokrates is a toolbox for zkSNARKs on Ethereum. - [Website](https://zokrates.github.io/) - Profile name: **ZoKrates** ::: :::: ### [Remix as code viewer](https://remix-ide.readthedocs.io/en/latest/remix_as_code_viewer.html) > Use Remix IDE as a code viewer to inspect verified smart contracts from Etherscan or any GitHub repository. # Remix as code viewer ## Through Etherscan Verified contracts on Etherscan can be viewed in Remix by making a simple change to the URL. Mostly for a multiple part contract verification, Remix provides a quick way to load all the contracts. A typical Etherscan URL for a contract address looks like this: `https://etherscan.io/address/0xdac17f958d2ee523a2206206994597c13d831ec7` In the URL, change `etherscan.io` to `app.remix.live` `https://app.remix.live/address/0xdac17f958d2ee523a2206206994597c13d831ec7` and reload. It will fetch the contracts verified on Etherscan. Contracts verified on Ethereum mainnet and on other test networks (Ropsten, Rinkeby, Kovan & Goerli) will be loaded in respective directories under `etherscan-code-sample` workspace. ![Remix IDE showing contracts loaded from Etherscan in the Etherscan-code-sample workspace](images/code-viewer/a-code-viewer-etherscan.png) This works for Etherscan testnet URLs `https://ropsten.etherscan.io`, `https://goerli.etherscan.io/` etc. If they are similarly updated, contracts will be loaded in Remix. ## Through GitHub Solidity files in GitHub can be loaded on Remix with a similar tweak. For a file with URL like: `https://github.com/remix-project-org/remix-project/blob/master/apps/remix-ide/contracts/app/solidity/mode.sol` change `github.com` to `app.remix.live` like: `https://app.remix.live/ethereum/remix-project/blob/master/apps/remix-ide/contracts/app/solidity/mode.sol` and reload. It will open the same file in Remix IDE. ![Remix IDE showing a Solidity file loaded from a GitHub URL](images/code-viewer/a-code-viewer-github.png) ### [Code Contribution Guide](https://remix-ide.readthedocs.io/en/latest/code_contribution_guide.html) > Guide for contributing to Remix IDE's open source codebase including how to report issues, submit PRs, and set up the dev environment. # Code Contribution Guide Remix is an open source tool. Please help us improve it by: - Opening issues in our [GitHub repository](https://github.com/remix-project-org/remix-project). - Writing some code and making a pulling request. The Remix application is built with Typescript and React. To learn more, please visit our [GitHub page](https://github.com/remix-project-org/remix-project). ### [Community Support](https://remix-ide.readthedocs.io/en/latest/community.html) > Get help with Remix IDE and connect with the community through Discord, Twitter, and other channels. # Community Support Do you have questions about Remix? Join our [Discord](https://discord.com/invite/qhpCQGWkmf) server and get some help! We post announcements and tips on [X](https://x.com/ethereumremix). For those interested in contributing to our codebase, make a PR to the [Remix Project repository](https://github.com/remix-project-org/remix-project/). If you'd like to develop a plugin for Remix, check this [guide](https://remix-plugins-directory.readthedocs.io/en/latest/).