AI prompts
base on Template starter for IBC enabled contracts in Solidity for use with vibc-core-smart-contracts # βοΈπβοΈ Template for IBC enabled Solidity contracts
This [IBC app in Solidity template repo](https://github.com/open-ibc/ibc-app-solidity-template/tree/main) provides a starter project that serves as a starting point for building multichain smart contracts that leverage Polymer Hub to connect across rollups through our [vIBC core contracts](https://github.com/open-ibc/vibc-core-smart-contracts).
The repository is a _GitHub template_ repository so you can click "Use this template" to create your own project repository without having the entire commit history of the template.
![GitHub template](./img/gh_template.png)
## π Documentation
There's some basic information here in the README but a more comprehensive documentation can be found in [the official Polymer documentation](https://docs.polymerlabs.org/docs/category/build-ibc-dapps-1).
## π Prerequisites
The repo is **compatible with both Hardhat and Foundry** development environments.
- Have [git](https://git-scm.com/downloads) installed
- Have [node](https://nodejs.org) installed (v18+)
- Have [Foundry](https://book.getfoundry.sh/getting-started/installation) installed (Hardhat will be installed when running `npm install`)
- Have [just](https://just.systems/man/en/chapter_1.html) installed (recommended but not strictly necessary)
You'll need some API keys from third party's:
- [Optimism Sepolia](https://optimism-sepolia.blockscout.com/account/api-key) and [Base Sepolia](https://base-sepolia.blockscout.com/account/api-key) Blockscout Explorer API keys
- Have an [Alchemy API key](https://docs.alchemy.com/docs/alchemy-quickstart-guide) for OP and Base Sepolia
Some basic knowledge of all of these tools is also required, although the details are abstracted away for basic usage.
## π§° Install dependencies
To compile your contracts and start testing, make sure that you have all dependencies installed.
From the root directory run:
```bash
just install
```
to install the [vIBC core smart contracts](https://github.com/open-ibc/vibc-core-smart-contracts) and the [Polymer registry](https://github.com/polymerdao/polymer-registry) as a dependency.
Additionally Hardhat will be installed as a dev dependency with some useful plugins. Check `package.json` for an exhaustive list.
> Note: In case you're experiencing issues with dependencies using the `just install` recipe, check that all prerequisites are correctly installed. If issues persist with forge, try to do the individual dependency installations...
### Version compatibility
| IBC-App-Solidity | vIBC core | Polymer Registry | Supported? |
|-------------------|-----------|-----------| --------|
| v0.1.0 | v1.0.0 | X | Deprecated |
| v0.2.0 | v1.0.0 | v0.1.0* | Deprecated |
| v1.0.0 | v2.0.0 | v0.0.1 | Yes |
Note (*): v0.2.0 uses a [POC version](https://github.com/tmsdkeys/polymer-registry-poc/releases/tag/v0.1.0)
## βοΈ Set up your environment and configuration
The idea is to ensure that most configuration to add Polymer's vIBC is added as custom data in the configuration file of your development environment, e.g. Hardhat or Foundry. (Note that at the time of writing, only Hardhat is fully supported).
Make sure to add network information to the Hardhat configuration for all supported networks you're interested in building on, following this schema:
```javascript
networks: {
// for OP testnet
optimism: {
url: 'https://sepolia.optimism.io',
alchemyRPC: `https://opt-sepolia.g.alchemy.com/v2/${process.env.OP_ALCHEMY_API_KEY}`,
accounts: [process.env.PRIVATE_KEY_1],
chainId: 11155420,
}
}
```
Especially make sure the chain ID is added as it will be used to fetch the correct data from the Polymer registry by ID, while you can locally refer to the chain as the name you've specified in the Hardhat config.
### Environment variables
Convert the `.env.example` file into an `.env` file. This will ignore the file for future git commits as well as expose the environment variables. Add your private keys and update the other values if you want to customize (advanced usage feature).
```bash
cp .env.example .env
```
This will enable you to sign transactions with your private key(s). If not added, the scripts from the justfile will fail.
### Configuration file
The configuration file is where all important data is stored for the just commands and automation. We strive to make direct interaction with the config file as little as possible.
By default the configuration file is stored in the config folder as `config.json`.
> π‘ However, it is recommended to split up different contracts/projects in the same repo into different config files in case you want to switch between them.
Store alternate config files in the /config directory and set the path in the Hardhat coniguration file:
```javascript
// path to configuration file the scripts will use for Polymer's vibc, defaulting to config/config.json when not set
vibcConfigPath: 'config/alt-config.json',
```
to use a different config file.
Contrary to previous version, you have to build the default configuration file by specifying the networks (from the Hardhat config) you want it to include:
```sh
# Usage: just build-config SOURCE DESTINATION
just build-config optimism base
```
### Obtaining testnet ETH
The account associated with your private key must have both Base Sepolia and Optimism Sepolia ETH. To obtain the testnet ETH visit:
- [Optimism Sepolia Faucet](https://www.alchemy.com/faucets/optimism-sepolia)
- [Base Sepolia Faucet](https://www.alchemy.com/faucets/base-sepolia)
## ππ½ππ»ββοΈ Quickstart
The project comes with a built-in dummy application called x-counter (which syncrhonizes a counter across two contracts on remote chains). You can find the contracts in the `/contracts` directory as XCounterUC.sol and XCounter.sol (the former when using the [universal channel](https://docs.polymerlabs.org/docs/build/executing-messages/universal-channels), the latter when creating a [custom/private channel](https://docs.polymerlabs.org/docs/build/executing-messages/private-channels)).
### Universal channels
The easiest way to get onboarded is to use Universal channels. Universal channel is like an open port already deployed by Polymer to allow anyone to call a remote contracts. Universal channels utilize a contract which is known as Universal channel handler (UCH).
Users can utilize universal channels through deploying a Universal channel compatible contract. This can be done either from deploying a contract which inherits the [UniversalChanIbcApp](./contracts/base/UniversalChanIbcApp.sol) base contract) or implements the [IbcUniversalPacketReceiver and IbcUniversalPacketSender interfaces](https://github.com/open-ibc/vibc-core-smart-contracts/blob/main/contracts/interfaces/IbcMiddleware.sol#L100-L112). Once deployed, the dapp will be able to connect to the Universal Channel handler, define Universal packets which will then be wrapped into a regular IBC packet by the Universal Channel Handler and unwrapped by its counterparty on the destination chain. The Universal channel handler on the destination will then unwrap the the packet and send the data to defined address.
The configuration file that comes as default in the template repository, allows to quickly send a packet by running:
```sh
just send-packet base
```
To send a packet between the XCounterUC contract on Base Sepolia to OP Sepolia and vice versa.
### Custom IBC channel
There is a quick guide available that helps you send packets over a custom/private IBC channel. The channel is established through a session setup process, known as a handshake, which typically takes less than five minutes to complete. Once established, the private channel provides fault isolation from other applications, ensuring that only your contracts can communicate with each other, unlike universal channels.
To have your application be compatible with custom IBC channels, have it inherit the [CustomChanIbcApp](./contracts/base/CustomChanIbcApp.sol) base contract.
Run the following command to go through a full E2E sweep of the project, using the default XCounter.sol contract:
```bash
# Usage: just do-it
just do-it
```
It does the following under the hood:
```bash
# Run the full E2E flow by setting the contracts, deploying them, creating a channel, and sending a packet
# Usage: just do-it
do-it:
echo "Running the full E2E flow..."
just set-contracts optimism XCounter false && just set-contracts base XCounter false
just deploy optimism base
just create-channel
just send-packet optimism
echo "You've done it!"
```
It makes sure you've got the correct contracts set, deploys new instances, creates a channel and sends a packet over the channel once created.
## π» Develop your custom application
The main work for you as a developer is to develop the contracts that make up your cross-chain logic.
You can use the contracts in the "/contracts/base" directory as base contracts for creating IBC enabled contracts that can either send packets over the universal channel or create their own channel to send packets over.
A complete walkthrough on how to develop these contracts is provided in the [Developer Launchpad](https://docs.polymerlabs.org/docs/build/dev-launchpad).
## πΉοΈ Interaction with the contracts
When the contracts are ready, you can go ahead and interact with the contracts through scripts. There is a Justfile too for the most common commands, with the underlying scripts in the `/scripts` folder.
The `/private` folder within the scripts folder has scripts that you're unlikely to need to touch. The only scripts you'll (potentially) be interacting with are:
- The `deploy.js` allows you to deploy your application contract. You may want to add additional deployment logic to the Hardhat script.
- In the `/contracts` folder you'll find `arguments.js` to add your custom constructor arguments for automated deployment with the `deploy.js` script.
- The `send-packet.js` script sends packets over an existing custom channel, and `send-universal-packet.js` is specifically for sending packets over a universal channel. You might want to add additional logic before or after sending the packet to cusotmize your application.
For most of the actions above and more, there are just recipes that combine related logic and update the configuation file in an automated way.
> **Note**: These are the default scripts provided. They provide the most generic interactions with the contracts to deploy, create channels and send packets. For more complicated use cases you will want to customize the scripts to your use case. See [advanced usage](#π¦Ύ-advanced-usage) for more info.
### Deploy
Before deploying, make sure to update the config.json with your contract type to deploy for each of the chains you wish to deploy to.
#### Set contracts to config
Do this by running:
```bash
# Usage: just set-contracts [chain] [contract_type] [universal]
just set-contracts optimism MyContract true
```
to deploy _MyContract_ artefact to the Optimism (Sepolia) chain.
> **IMPORTANT**: This is where you set if your contract uses universal or custom channels. Make sure this corresponds to the base contract you've inherited from when developing your application (UniversalChanIbcApp or CustomChanIbcApp).
#### Constructor arguments
By default any application inheriting a base IBC application contract will need a dispatcher or universal channel handler address passed into the constructor. Obviously you might have other constructor arguments you may want to add. To still make use of the `just deploy source destination` recipe, add your arguments to the arguments.js file
```javascript title="/contracts/arguments.js"
module.exports = {
"XCounter": [],
"XCounterUC": [],
// Add your contract types here, along with the list of custom constructor arguments
// DO NOT ADD THE DISPATCHER OR UNIVERSAL CHANNEL HANDLER ADDRESSES HERE!!!
// These will be added in the deploy script at $ROOT/scripts/deploy.js
};
```
#### Finally: deploy
Then run:
```bash
# Usage: just deploy [source] [destination]
just deploy optimism base
```
where the script will automatically detect whether you are using custom or universal IBC channels.
The script will take the output of the deployment and update the config file with all the relevant information.
Before moving on, you'll want to check if the variables in your .env and config files line up with what is stored in the actual deployed contracts... especially when you're actively playing around with different configuration files and contracts.
To do a sanity check, run:
```bash
# Usage: just sanity-check
just sanity-check
```
### Create a channel
If you're **using universal channels, channel creation is not required**. Your contract will send and receive packet data from the Universal channel handler contract which already has a universal channel to send packets over. You can directly proceed to sending (universal) packets in that case.
To create a custom channel, run:
```bash
just create-channel
```
This creates a channel between base and optimism. Note that the **ORDER MATTERS**; if you picked optimism as the source chain (first argument) above, by default it will create the channel from optimism and vice versa.
The script will take the output of the channel creation and update the config file with all the relevant information.
### Send packets
Finally Run:
```bash
# Usage: just send-packet
just send-packet optimism
```
to send a packet over a channel (script looks at the config's isUniversal flag to know if it should use the custom or universal packet). You can pick either optimism or base to send the packet from.
## π€ Contributing
We welcome and encourage contributions from our community! Hereβs how you can contribute.
Take a look at the open issues. If there's an issue that has the _help wanted_ label or _good first issue_, those are up for grabs. Assign yourself to the issue so people know you're working on it.
Alternatively you can open an issue for a new idea or piece of feedback.
When you want to contribute code, please follow these steps:
1. **Fork the Repository:** Start by forking this repository.
2. **Apply the improvements:** Want to optimize something or add support for additional developer tooling? Add your changes!
3. **Create a Pull Request:** Once you're ready and have tested your added code, submit a PR to the repo and we'll review as soon as possible.
## π‘ Questions or Suggestions?
Feel free to open an issue for questions, suggestions, or discussions related to this repository. For further discussion as well as a showcase of some community projects, check out the [Polymer developer forum](https://forum.polymerlabs.org).
Thank you for being a part of our community!
", Assign "at most 3 tags" to the expected json: {"id":"8454","tags":[]} "only from the tags list I provide: [{"id":77,"name":"3d"},{"id":89,"name":"agent"},{"id":17,"name":"ai"},{"id":54,"name":"algorithm"},{"id":24,"name":"api"},{"id":44,"name":"authentication"},{"id":3,"name":"aws"},{"id":27,"name":"backend"},{"id":60,"name":"benchmark"},{"id":72,"name":"best-practices"},{"id":39,"name":"bitcoin"},{"id":37,"name":"blockchain"},{"id":1,"name":"blog"},{"id":45,"name":"bundler"},{"id":58,"name":"cache"},{"id":21,"name":"chat"},{"id":49,"name":"cicd"},{"id":4,"name":"cli"},{"id":64,"name":"cloud-native"},{"id":48,"name":"cms"},{"id":61,"name":"compiler"},{"id":68,"name":"containerization"},{"id":92,"name":"crm"},{"id":34,"name":"data"},{"id":47,"name":"database"},{"id":8,"name":"declarative-gui "},{"id":9,"name":"deploy-tool"},{"id":53,"name":"desktop-app"},{"id":6,"name":"dev-exp-lib"},{"id":59,"name":"dev-tool"},{"id":13,"name":"ecommerce"},{"id":26,"name":"editor"},{"id":66,"name":"emulator"},{"id":62,"name":"filesystem"},{"id":80,"name":"finance"},{"id":15,"name":"firmware"},{"id":73,"name":"for-fun"},{"id":2,"name":"framework"},{"id":11,"name":"frontend"},{"id":22,"name":"game"},{"id":81,"name":"game-engine "},{"id":23,"name":"graphql"},{"id":84,"name":"gui"},{"id":91,"name":"http"},{"id":5,"name":"http-client"},{"id":51,"name":"iac"},{"id":30,"name":"ide"},{"id":78,"name":"iot"},{"id":40,"name":"json"},{"id":83,"name":"julian"},{"id":38,"name":"k8s"},{"id":31,"name":"language"},{"id":10,"name":"learning-resource"},{"id":33,"name":"lib"},{"id":41,"name":"linter"},{"id":28,"name":"lms"},{"id":16,"name":"logging"},{"id":76,"name":"low-code"},{"id":90,"name":"message-queue"},{"id":42,"name":"mobile-app"},{"id":18,"name":"monitoring"},{"id":36,"name":"networking"},{"id":7,"name":"node-version"},{"id":55,"name":"nosql"},{"id":57,"name":"observability"},{"id":46,"name":"orm"},{"id":52,"name":"os"},{"id":14,"name":"parser"},{"id":74,"name":"react"},{"id":82,"name":"real-time"},{"id":56,"name":"robot"},{"id":65,"name":"runtime"},{"id":32,"name":"sdk"},{"id":71,"name":"search"},{"id":63,"name":"secrets"},{"id":25,"name":"security"},{"id":85,"name":"server"},{"id":86,"name":"serverless"},{"id":70,"name":"storage"},{"id":75,"name":"system-design"},{"id":79,"name":"terminal"},{"id":29,"name":"testing"},{"id":12,"name":"ui"},{"id":50,"name":"ux"},{"id":88,"name":"video"},{"id":20,"name":"web-app"},{"id":35,"name":"web-server"},{"id":43,"name":"webassembly"},{"id":69,"name":"workflow"},{"id":87,"name":"yaml"}]" returns me the "expected json"