# Getting started

Welcome to the Acala EVM+ development documentation. Here you can find all of the information needed in order to develop, test and deploy your smart contracts to the Acala EVM+.

If you are unable to find an answer to your question or need further explanation, please contact us on [Discord](https://discord.gg/5JJgXKSznc) in our #evm channel and we will be happy to provide the answers.


# About Acala EVM+

## Introduction

The vision of Acala is to build a decentralized permissionless DeFi platform. Ethereum is currently the largest DeFi platform. We would like to integrate with it by bridging the assets and liquidity of it. Our goal is to be compatible with Ethereum’s toolchains and tap into its large developer community. By building Acala EVM+, Ethereum developers will be able to deploy their solutions to Acala without friction.

Many blockchains also aims to be the better Ethereum. Aiming to providing full Ethereum compatibility to allow developers to reuse their existing toolchains and deploy existing contracts with no or minimal changes to deploy on their network. However, Ethereum is not yet perfect and it wouldn’t make sense for us to just ignore all of the issues that Ethereum users are experiencing currently and just build another, faster, Ethereum.

It is clear to us that just building a faster Ethereum is not what we want. With all the powerful and advanced features from Substrate, we aim to do better. All the while being friendly to existing Ethereum and Solidity developer community. EVM compatibility on Acala will be a stepping stone for the Solidity developers to tap into Polkadot ecosystem and have a taste of the new features that are simply not possible on Ethereum, such as bring your own gas (pay transaction fee with any supported token, powered by Acala Swap), powerful governance tools (no more locked funds) and full interoperability with the Polkadot ecosystem (no more centralized bridges).

> *Learn once, write anywhere.*

Note that *“write once, run anywhere”* is not our goal. Instead, we are inspired by the React Native approach *“learn once, write anywhere”*. Acala, and all Substrate based chains, are fundamentally different from Ethereum. We have our own trade-offs and therefore restrictions (in exchange for some other benefits). If we are trying to emulate an Ethereum node, we will be suffering from the worst of both worlds. It will be a step backwards for us to inherit all the restrictions from a legacy blockchain platform. Therefore it makes more sense to make some necessary compatibility sacrifices, to not be limited by decisions made by Ethereum developers many years ago. As a result, developers can take advantage of all of the advanced features that we are offering, while still using a familiar language (Solidity or another compile-to-evm languages). This means changes are likely required to port over existing projects. However with many new advanced features added to EVM via precompiles from Acala runtime, we hope the contracts can be significantly simplified and offer improved features and better usability to users.

## Challenges <a href="#challenges" id="challenges"></a>

There were two categories of challenges we were facing when design & building Acala EVM+. The first area stemed from the things we do not want to inherit from the legacy decisions of Ethereum. The second area originated from the inherent conflicts between Substrate and Ethereum.

### Issues <a href="#issues" id="issues"></a>

#### **Storage**

One of the main issues preventing people from running their own Ethereum nodes is that it requires a very large storage. This is partially due to the cost of on-chain storage being uneconomic.

On-chain storage is always expensive because it has to be replicated by every node and stored for many years, potentially forever. This is an ongoing cost and therefore the token economics should factor it in to avoid state explosion problem.

On Ethereum, the cost of inserting data into on-chain state is a one-off payment based on the gas price at the time when the transaction is processed. It doesn’t consider future costs and has a poor incentive to remove unused stored data. As a result, very little smart contracts actively purge unused states and no one actively removes unused contracts. The poorly designed storage gas refund makes [Gas Token](https://cointelegraph.com/news/a-new-token-lets-you-save-on-ethereum-fees-by-storing-gas) possible, which encourages people to store useless data when gas prices are low and to remove them when gas prices are high. This benefits individuals and miners, but raises the transaction cost for everyone else and increases the cost of operating Ethereum nodes at the same time. There are also a lot of dust accounts containing too little funds to send a transaction, and therefore no one is willing to reclaim those dust funds and these accounts just waste the on-chain storage.

#### **Gas price**

Another usability issue of Ethereum is that it is hard estimate how much gas price to pay. There are multiple services available ([\[1\]](https://ethgas.watch/), [\[2\]](https://gitcoin.co/gas/intro), [\[3\]](https://ethgasstation.info/), [\[4\]](https://www.gasnow.org/), [\[5\]](https://etherscan.io/gastracker)), but it is still not easy for people to balance between high gas prices and long confirmation times. Most of the people are just using the whatever value is provided by their wallet and wallets usually overestimate the gas price to ensure a fast confirmation time. However the throughput of the network is limited and this means everyone is overpaying and no one is getting faster confirmation times.

[EIP-1559](https://eips.ethereum.org/EIPS/eip-1559) is one of the solution that addresses this issue. It proposes an algorithm to calculate a base fee for transaction, using the gas usage of previous blocks, instead of requiring users to estimate and supply the gas price. This is very similar to the [Fee Adjustment](https://wiki.polkadot.network/docs/en/learn-transaction-fees#fee-adjustment) mechanism implemented by Polkadot. Acala will adapt the slow-adjusting fee mechanism with tips from Polkadot to provide a better UX. This mechanism will be incorporated into the Acala EVM+ so the smart contract developers and users will not need to worry about gas price anymore.

### Conflicts <a href="#conflicts" id="conflicts"></a>

#### **Dust accounts**

While Substrate is indeed very customisable, it still comes with constraints and technical limitations. Some of those constraints are due to lessons learnt from building Ethereum and it is not something we would like to revert. For example, Polkadot implements [Existential Deposit](https://wiki.polkadot.network/docs/build-protocol-info#existential-deposit) which aims to solve the dust account issue. However, this also comes with a trade-off that when a dust account is wiped, the storage and dust fund are reclaimed. It means nonce can be reset and introduce a possibility of a replay attack. To prevent replay attacks, Polkadot supports mortal transactions (expiring transactions), so that it is no longer possible to replay old transactions. This fundamentally conflicts with Ethereum’s account model and transaction format.

#### **Compatible extensions**

There are few multi-chain wallets that support both Ethereum and Polkadot, but the most commonly used wallets, for both Ethereum and Polkadot, are still a single network wallets, namely MetaMask and Polkadot.js extension. This creates an issue where Polkadot.js extension cannot handle Ethereum transaction format and MetaMask cannot handle Substrate transaction format. As the result, user may need to use two browser extensions at same time, one for the Substrate runtime and one for EVM interactions. This is not something that is acceptable.

#### **Forkless upgrades**

One of the most advanced features offered by Substrate is forkless upgrades, that allow blockchain to evolve without forks. This reduces amount of coordination required and risk of network instability when performing upgrades. We also have an experimental Karura network that holds real value, on which we can try out new features. This means we are actually able to quickly (yet securely) iterate features, to improve the user’s and developer’s experiences of the network. We can try a lot of new things that are simply not feasible on Ethereum, which means we are no longer limited by what Ethereum is able to offer. This requires a change of mindset (why copy what Ethereum did, if we can do it better?) and opens a lot of possibilities and increases potential of the Acala EVM+.

## Solutions & Enhancements <a href="#solutions-amp-enhancements" id="solutions-amp-enhancements"></a>

We would like to implement a smart contract platform that takes the best of both worlds, while avoiding all of the pitfalls. This is actually very hard because we need to carefully balance all of the decisions and incompatibilities. Remember, most of the issues are not due to incompetent developers, but instead of people balancing trade-offs due to technical limitations. A solution of one problem usually leads to another set of problems. The art of Engineering is balancing trade-offs and building something best suited for the target audiences. Therefore we do not aim to build a perfect solution, but instead trying to make the right trade-offs to avoid all the pitfalls while keeping as much of the compatibility as possible.

### bodhi.js <a href="#bodhijs" id="bodhijs"></a>

One key component to be Ethereum compatible is RPC compatibility. i.e. Support Ethereum RPC. This is not easy to achieve due to many low level decisions made by Substrate. e.g. Ethereum RPC supports to get transaction by hash, which is not supported by Substrate RPC. This is because Substrate aims to be as lightweight as possible, and decided to not store those extra information by default. It is possible to customize Substrate to support all those extra requirements by using [Frontier](http://github.com/paritytech/frontier), but it does add a lot of extra complexity to the node and undos a lot of work to make the node lightweight. Therefore, we decided to go with an alternative approach.

Instead of emulating the full Ethereuem RPC on node side and to solve the problem of requiring multiple extensions, we have developed [bodhi.js](http://github.com/AcalaNetwork/bodhi.js), a JS SDK that offers an implementation of [Web3Provider](https://docs.ethers.io/v5/api/providers/) using polkadot.js and Substrate RPC. This means existing dApps that can use the Web3Provider offered by bodhi.js just like any other providers, such as the one provided by MetaMask. This will allow dApps to use bodhi.js to sign transactions using Polkadot.js extension as well as querying data from Acala nodes. As a result, a minimal change is required to port an existing Ethereum-based dApp to support Acala EVM+.

### Weight system <a href="#weight-system" id="weight-system"></a>

Substrate offers a weight system which is somewhat similar to gas fee system. We decided to use the weight system for charging gas fees by defining a gas-to-weight conversion ratio. As the result, we can completely ignore the gas price and use the weight system to handle the fees. The priority fee from EIP-1559 can be directly translated to the tip of the Substrate transaction. This allows the blockchain to handle EVM transactions like any other standard transactions. Some changes will be required on the dApp side to handle the transaction fee estimation and display, but it should be very straightforward.

### Renting storage <a href="#renting-storage" id="renting-storage"></a>

There are many researches on how to solve the state explosion problem and some of the possible solutions are [storage rent](https://wiki.polkadot.network/docs/build-smart-contracts#storage-rent) (which is deprecated) and [state expiry](https://notes.ethereum.org/@vbuterin/verkle_and_state_expiry_proposal). Both of them are complicated and not battle tested yet so we are not comfortable with using them in Acala EVM+ at this stage. Therefore we decided to use a much simpler model that charges a storage deposit for every byte used by the smart contract and refund the deposit upon clearing the storage used. This is able to create an incentive to free up unused storage while keeping compatibility with existing EVM smart contracts. The storage deposit in some sense can be viewed as the gas use/refund for storage operations, but the cost is a fixed amount of tokens per byte, instead of depending on the gas price, which depends on the block fullness utilisation. Similarly, the state deposit is also required for the code of new contracts, and encourage developers to remove any unused contracts from the on-chain storage.

### Storage meter <a href="#storage-meter" id="storage-meter"></a>

In order to accurately handle the storage deposit, we have implemented a storage meter in Acala EVM+. Similar to gas meter, which measures the gas usage, storage meter measures the storage usage and handles the storage deposit. This also adds a new input to transaction: storage limit. Gas limit is used to limit how much gas can be consumed by a transaction and storage limit is used to ensure the contract does not incur more than specified storage deposit.

### Developer mode <a href="#developer-mode" id="developer-mode"></a>

Being a DeFi chain, Acala always considers the security of our user’s funds the top priority. In Ethereum network, deploying a fraudulent contract is rather cheap. There is only an upfront development cost and even if the contract is banned or shunned by the users, the malicious developer can always deploy a new smart contract.

We feel that censorship is the wrong approach, so we developed a different approach to solving this issue. Our solution is to raise the bar of deploying new publicly accessible contracts, so that it becomes expensive to deploy malicious token contracts and useless forks. Contracts will initially only be accessible by the contract developers, a special role that anyone can opt-in to. Once the contracts have been deployed and tested, they can be made public by paying a relatively large amount of ACA (the exact value still has to be determined) in order for them to become publicly accessible. Genuine teams that want to deploy contracts but cannot pay the upfront cost, can request a grant from the Acala Treasury. This means that there is no additional cost of deploying contracts for internal testing and personal usage, but iteratively deploying fraudulent contracts to be publicly used will be expensive. Our hope is that this approach achieves the right balance between permissionlessness and security of network user’s funds.

In the future we expect to be able to work with Identity parachains in order to give identity to the contracts. This should greatly improve the trustworthiness of verified contracts, because users will know they are interacting with a canonical contract instead of a malicious fork.

### Custom precompiles and predeploys <a href="#custom-precompiles" id="custom-precompiles"></a>

One of the things differentiating Acala EVM+ from the EVM is custom precompiles. Custom precompiles are smart contracts that are already compiled and deployed to the Acala EVM+ and available to the developers to incorporate within their own smart contracts. Additionally we are able to update these contracts via governance, which means that they will always be up to date with the latest security features and fixes. These predeploy contracts include [ERC-20 contracts](https://wiki.acala.network/build/development-guide/smart-contracts/advanced/use-native-tokens), like ACA, AUSD, DOT, LDOT and many more, as well as systemic contracts, like [State Rent](https://wiki.acala.network/build/development-guide/smart-contracts/advanced/use-flexi-fee#state-rent), [Oracle Price Feed](https://github.com/AcalaNetwork/acala-evm-dev-docs/blob/master/general/https/wiki.acala.network/build/development-guide/smart-contracts/advanced/use-oracle-feeds/README.md), [Scheduler](https://wiki.acala.network/build/development-guide/smart-contracts/advanced/use-on-chain-scheduler), [DEX](https://wiki.acala.network/learn/basics/dex). We expect DeFi contracts to join the list shortly.

Usage of these precompiled contracts opens a whole new area of possibilities for smart contract developers. The built-in Scheduler allows for automation of the smart contract business logic execution (no more external scripts to call smart contract functions periodically) and the Oracle can be used to set a stable price for services which are in turn paid with unstable tokens. The possibilities are truly endless.

Differences between EVM and Acala EVM+ mean that not every aspect of a transaction is compatible. If we wish for the users to be able to use Metamask, we have to provide a mechanic for it to work with the storage limit and expiration information. To do that we aim to use an [ERC-712](https://eips.ethereum.org/EIPS/eip-712) standard to sign the transactions and provide these kinds of information using it. This introduces another step when sending a transaction, compared to EVM, but allows us to support the existing extensions and browsers that are used on the Ethereum network rather than forcing the end user to migrate to another extension and/or wallet.

## Decisions <a href="#decisions" id="decisions"></a>

We had to make some decisions that are not fully compatible with EVM to make the step forward. These have been carefully considered and we want to share why we did them.

### Disable native token <a href="#disable-native-token" id="disable-native-token"></a>

Native token in Ethereum has 18 decimal spaces and Karura’s native token has 12 decimal spaces. This means that the two are incompatible. We could have used a conversion logic where we would multiply or divide the value by 1,000,000, depending on the way in which we are converting the tokens, but that could cause some serious errors. Imagine having to handle a value of 1 wei (the lowest possible value of Ethereum’s native token). Converting this to Karura’s we would divide this by 1,000,000 and get the value of 10^(-6). Since we are operating in a space where we don’t deal with floating point, the value would be rounded down, so the value would be 0. This could potentially break the flow of the operation that is running. Instead of accepting such a risk, we decided to disable native token in the Acala EVM+. This way we don’t compromise robustness of our virtual machine for support of an inherited trait.

Additionally we have taken into account that many of the DeFi contracts don’t operate using the native token, but all of them use ERC-20 tokens. Which means we are not disabling any of their functionality, while improving the operation of the EVM+.

### Dust accounts clearing <a href="#dust-accounts-clearing" id="dust-accounts-clearing"></a>

Clearing the dust accounts opens these addresses to a possibility of a replay attack, since the nonce is reset alongside the assets. To prevent that, each transaction has an expiration time. It would be easy to implement it as an additional parameter that has to be passed when calling a function, but that would put additional stress to the developers. We can’t add an additional field to Metamask and we can not force it to have a default value for the transaction expiration. Thus we devised a solution that uses the existing and supported operation by Metamask. Using ERC-712 typed signing standard will allow people to sign Acala EVM+ transaction with Metamask in a user friendly way. This allow us to provide the mechanics that we need, to provide as much security to user’s funds as possible, while serving users with an operation they already know when using Metamask.

### ERC-712 transactions <a href="#erc-712-transactions" id="erc-712-transactions"></a>

Using ERC-712 format of the transaction allows us to store storage limit within it as well. Since the user is paying a per-byte fee for the data they are storing, it is important to support a mechanic where the user has control over the maximum amount they are willing to deposit to rent the storage, much like the maximum amount of gas they are prepared to pay for in Ethereum network.

#### Embedding storage limit and transaction expiry into gas params <a href="#embedding-storage-limit-and-transaction-expiry-into-gas-price" id="embedding-storage-limit-and-transaction-expiry-into-gas-price"></a>

In addition to the ERC-712 transactions we foresee a method that both, storage limit and transaction expiry information, within the gas params of the transaction. This would allow for smoother network usage for bots and servers, as the transaction would be streamlined for programmatic usage.

Additionally we are able to use gas params to set the storage limit, since we’ve adopted the slow-adjusting fee mechanism with tips from Polkadot to provide a better UX for users. This mechanism will be incorporated into Acala EVM+, so the contract developers and users won’t have to worry about the gas price. This in turn sets the stage for using the gas params for something else, like the before-mentioned passing of the storage limit in the gas params field of the transaction. What is known as a priority fee value in Ethereum transactions, directly corresponds to Acala EVM+ tips, providing an additional familiarity for users and developers coming over from the Ethereum network.


# Security considerations of developing in Acala EVM+

## Introduction

As Acala EVM+ is not a simple copy-paste clone of the Ethereum's EVM, there are additional security considerations to the ones from Ethereum's EVM. The SWCs still apply and you should familiarise yourself with them if you haven't already. The directory can be found [here](https://swcregistry.io/).

Acala EVM+ interacts with Substrate layer of the chain, so this introduces some of the considerations that we have to be aware of. We also refined some of the settings and mechanics of the chain, so some of these differences may impact your smart contracts. You also need to be aware how storage rent and storage deposit work when building, deploying and maintaining your smart contracts. There is more and we will analyse as much as we can in this article.

This article assumes you have familiarised yourself with the Acala EVM+ and its functions.

## Considerations

While we will to outline as much of the security considerations as we can, there is still a possibility that additional ones exist. We will expand the list if that is the case.

### 1. Double entry consideration

Our native tokens ACA and KAR have a mirrored [predeployed smart contract](/network/predeployed-smart-contracts/details), which means that a change in balance of the native currency is also reflected in the mirrored ERC20 predeployed smart contract and vice versa. A DeFi protocol that supports operation of the native currency as well as the predeployed ERC20 smart contracts may encounter unexpected or unreliable behaviour because of this.

We suggest to disable operations with native currency and only support the mirrored ERC20 version.

### 2. Dust balance consideration

All of our mirror tokens and native tokens, have [existential deposit](https://wiki.acala.network/get-started/acala-network/acala-account#existential-deposit). This means that the balance of an account that falls below the threshold will be 'dusted'. This preserves space of chaindata and ensures that there are no accounts with balances lower than the cost of transferring these balances; if an account has balance lower than the transaction cost needed to clear the balance, the record of this balance can never be cleared.

Not accounting for existential deposit can lead to mismatched numbers in your own protocol records or to transactions failing unexpectedly.

We suggest implementing a mechanic for verification of these tokens being successfully received and not dusted or to enforce a minimum value of tokens being transferred to ensure that the tokens are not dusted upon receipt when transferring the mirror tokens.

### 3. Storage deposit consideration

[Storage deposit](/general/about-acala-evm+#renting-storage) is used to protect against chain bloat. It represents a staked amount of tokens that are returned upon clearing of storage. Having unbounded storage write ability could potentially allow for users causing a state of smart contact to require a change so big, that the interaction with the smart contract is too expensive.

We suggest ensuring that the users are unable to put the smart contract in a state that could lead to so many states having to be changed at once, that the smart contract becomes unusable.

On top of that, removing storage entries or destructing smart contracts will refund storage deposits. Smart contracts that allow potentially large storage removals, may also need to be gated, to ensure the storage deposit refund can be handled appropriately.

Additionally we suggest that you design your smart contracts to change as little states as possible as this will reduce the cost of storage deposit incurred on users.

### 4. Unexpected upgrades consideration

Acala EVM+ supports [publication](broken://pages/TGJbPC5orpKZWopUvuyq#mark-a-given-contract-as-published-in-the-developer-section-of-the-polkadot-app) of smart contracts. This allows the team deploying the smart contract to verify, test and configure the smart contract before the non-developer users are able to interact with it. This also means that the unpublished smart contract can be upgraded even if it is not upgradeable in a smart contract upgradeable sense (e.g. written in a proxy-upgrade or diamond pattern).

We suggest [verifying](broken://pages/TGJbPC5orpKZWopUvuyq#verify-that-the-smart-contract-has-been-published-successfully) that the smart contract, your smart contract is interacting with, is published before interacting with it.

### 5. Decimals consideration

Both ACA and KAR have 12 decimal points natively, however the native token decimals in EVM is always 18. This means that if you transfer `1000000 wei` in your smart contract, you are transferring the lowest denomination of ACA or KAR. Transfer of `1 ether` will result transfer of 1 ACA or KAR. Additionally, in order to avoid unexpected transfer amounts, any transfer with value that cannot be exactly represented with 12 decimals will fail. This means any transfer of value that is not a multiple of `10^6 wei` will be reverted. If you rely on such calls for transferring the native currency in your smart contract, your calls might potentially fail.

We suggest reviewing your code for the `transfer()` calls and making sure you are transferring the expected amounts. The contracts needs to gracefully handle transfer amounts that are either result of user input or arithmetic operations, because the value may not be a valid transferable amount.

### 6. Two management accounts consideration

EVM and the Substrate accounts [bound](broken://pages/cwKBrbZbcJJOcekWL7AO#bind-accounts) to each other in more that just sharing the balances of the native tokens. They are used to manage the deployed smart contracts. The EVM account can manage a smart contract using the owned smart contract development pattern while the Substrate account can [publish](broken://pages/TGJbPC5orpKZWopUvuyq) or [delete](broken://pages/jcOHJpfXqcTCEYtg2ChR) the smart contract.

We suggest that, in case you are transfer the ownership of your smart contract in the EVM to another account, you transfer the management of the smart contract to the corresponding substrate account as well.

{% hint style="info" %}
**NOTE: This only applies to unpublished contracts.**
{% endhint %}

### 7. Duplicated transaction hashes consideration

There is no possibility for two or more transactions to share a same transaction hash. In Substrate based chains this is possible due to non-zero existential deposit. Once the account is [*dusted*](#2.-dust-balance-consideration), its nonce is reset to 0. This means that people can craft replayable transactions, which could have the same transaction hash.

We suggest that, if your dApp processes the transaction hashes, make sure that it can handle the replayed transactions gracefully.

### 8. Unintended address binding consideration

The intertwining of the Substrate level and the EVM level means that, for users to access the full functionality of Acala's networks, their Substrate and EVM accounts need to be bound. Some of the Substrate assets might return an EVM asset to the account. When this happens the EVM assets are allocated to the EVM account associated to the Substrate account. If no such binding exists, the default EVM account will be bound to it.

{% hint style="info" %}
The default EVM account can only be used to [interact with the EVM through Substrate calls](/special-features/using-bodhi.js-to-deploy-smart-contract-and-interact-with-it) and cannot be imported into an EVM wallet as no private key nor mnemonic are available.
{% endhint %}

The assets associated with the default EVM address are fully interactable with, but can't be managed by the EVM wallet. This means that unlocking their full functionality might require user to transfer them, to a wallet they are able to restore, one by one.

We suggest you implement a check in your dApp to verify that the user has bound their own EVM address and if they didn't, direct them to instructions on how to do that. As any smart contract interaction from a Substrate account binds the default EVM account, make sure to implement this check even if no EVM assets are allocated and the user is just interacting with a smart contract.

## Conclusion

While the preexisting security considerations of developing in the EVM still apply, Acala EVM+'s improvements also introduce new ones. The list of security considerations in this article should give you a good overview on what to expect.


# Network configuration

Addressing and identification information of Acala networks.

The following tables contain the information necessary to connect to Acala networks.

## Acala Mainnet

| **Name**             | Acala                                       |
| -------------------- | ------------------------------------------- |
| **Node Endpoint**    | `wss://acala-rpc.aca-api.network`           |
| **ETH RPC Endpoint** | `https://eth-rpc-acala.aca-api.network`     |
| **WS Endpoint**      | `wss://eth-rpc-acala.aca-api.network`       |
| **Subquery**         | `https://subql-query-acala.aca-api.network` |
| **Explorer**         | <https://blockscout.acala.network>          |
| **Chan ID**          | 787                                         |
| **Symbol**           | ACA                                         |

There is also a developer-facing beta version that usually contains some latest features, but might be unstable.

| **Name**             | Acala Beta                                  |
| -------------------- | ------------------------------------------- |
| **ETH RPC Endpoint** | `https://eth-rpc-acala.aca-staging.network` |
| **WS Endpoint**      | `wss://eth-rpc-acala.aca-staging.network`   |

## Karura Mainnet

| **Name**             | Karura                                       |
| -------------------- | -------------------------------------------- |
| **Node Endpoint**    | `wss://karura-rpc.aca-api.network`           |
| **ETH RPC Endpoint** | `https://eth-rpc-karura.aca-api.network`     |
| **WS Endpoint**      | `wss://eth-rpc-karura.aca-api.network`       |
| **Subquery**         | `https://subql-query-karura.aca-api.network` |
| **Explorer**         | <https://blockscout.karura.network>          |
| **Chan ID**          | 686                                          |
| **Symbol**           | KAR                                          |

There is also a developer-facing beta version that usually contains some latest features, but might be unstable.

| **Name**             | Karura Beta                                  |
| -------------------- | -------------------------------------------- |
| **ETH RPC Endpoint** | `https://eth-rpc-karura.aca-staging.network` |
| **WS Endpoint**      | `wss://eth-rpc-karura.aca-staging.network`   |

## Local Development Network

This section assumes you are using the dockerized local development network described in the [node setup](/network/network-setup/local-development-network) section.

| **Name**             | Mandala Local           |
| -------------------- | ----------------------- |
| **Node Endpoint**    | `ws://127.0.0.1:9944`   |
| **ETH RPC Endpoint** | `http://127.0.0.1:8545` |
| **WS Endpoint**      | `ws://127.0.0.1:8545`   |
| **Chain ID**         | 595                     |
| **Symbol**           | mACA                    |

## Mandala Testnet TC9

| **Name**             | Mandala TC9                                      |
| -------------------- | ------------------------------------------------ |
| **Node Endpoint**    | `wss://mandala-tc9-rpc.aca-staging.network`      |
| **ETH RPC Endpoint** | `https://eth-rpc-tc9.aca-staging.network`        |
| **WS Endpoint**      | `wss://eth-rpc-tc9.aca-staging.network`          |
| **Subquery**         | `https://subql-query-tc9.aca-staging.network`    |
| **Explorer**         | <https://blockscout.mandala.aca-staging.network> |
| **Chan ID**          | 595                                              |
| **Symbol**           | mACA                                             |

## Karura Testnet

| **Name**             | Karura Testnet                                           |
| -------------------- | -------------------------------------------------------- |
| **Node Endpoint**    | `wss://karura-testnet.aca-staging.network/rpc/karura/ws` |
| **ETH RPC Endpoint** | `https://eth-rpc-karura-testnet.aca-staging.network`     |
| **WS Endpoint**      | `wss://eth-rpc-karura-testnet.aca-staging.network`       |
| **Subquery**         | `https://subql-query-karura-testnet.aca-staging.network` |
| **Explorer**         | <https://blockscout.karura-testnet.aca-staging.network>  |
| **Chan ID**          | 596                                                      |
| **Symbol**           | KAR                                                      |

## Acala Testnet

| **Name**             | Acala Testnet                                           |
| -------------------- | ------------------------------------------------------- |
| **Node Endpoint**    | `wss://acala-dev.aca-dev.network/rpc/ws`                |
| **ETH RPC Endpoint** | `https://eth-rpc-acala-testnet.aca-staging.network`     |
| **WS Endpoint**      | `wss://eth-rpc-acala-testnet.aca-staging.network`       |
| **Subquery**         | `https://subql-query-acala-testnet.aca-staging.network` |
| **Explorer**         | <https://blockscout.acala-dev.aca-dev.network>          |
| **Chan ID**          | 597                                                     |
| **Symbol**           | ACA                                                     |


# Network setup

Instructions on how to run a node in each of the networks

As we have public production networks, public test networks as well as local development network for developers to interact with, this section contains instructions on how to use them:

{% content-ref url="/pages/tLTPSxSKiyYZnx72m8dz" %}
[Local development network](/network/network-setup/local-development-network)
{% endcontent-ref %}

{% content-ref url="/pages/ARQc1bHT7YiAmh9eXXiS" %}
[Connecting to a public network with local RPC node](/network/network-setup/connecting-to-a-public-network-with-local-rpc-node)
{% endcontent-ref %}


# Local development network

Instructions on how to run a full local development network

The local development network consists of following services:

* Local Acala Fork
* Eth Rpc Adapter
* \*Subquery Services
  * Postgres database
  * Subquery node
  * GraphQL engine

## Starting the stack

You can download or copy + paste this [docker compose file](https://github.com/AcalaNetwork/bodhi.js/blob/master/docker-compose.yml), and then

```
docker compose up
```

Once you see logs like this, the local development stack is ready.

```
--------------------------------------------
             🚀 SERVER STARTED 🚀
--------------------------------------------
version         : bodhi.js/eth-rpc-adapter/2.9.4
endpoint url    : ws://node:9944
subquery url    : undefined
server host     : localhost
server port     : 8545
max blockCache  : 200
max batchSize   : 50
max storageSize : 5000
cache capacity  : 1000
safe mode       : false
local mode      : false
http only       : false
verbose         : true
--------------------------------------------
```

This stack contains a local Acala fork, and an eth rpc adapter.

It does not contain a subquery services, since for local testing purpose, we usually do not need subquery services, and if you would like to setup a local subquery service, you can refer to the [subquery docs](https://github.com/AcalaNetwork/bodhi.js/tree/master/packages/evm-subql#run-with-docker).

{% hint style="info" %}
**In order to have a clean start after every shutdown of the node, run the following command after the node was shut down:**

**`docker compose down -v`**
{% endhint %}

## The local development network services

Once the local development network is up and running, the following services are available:

* A local mandala node: <ws://localhost:9944>
* \*A subquery service: <http://localhost:3001>
* An ETH JSON-RPC service:
  * <http://localhost:8545>
  * <ws://localhost:8545>
* Local network substrate chain explorer: [Polkadot.js App](https://polkadot.js.org/apps/?rpc=ws%3A%2F%2Flocalhost%3A9944%2Fws#/explorer)

You can now setup [Metamask on localhost](/tooling/metamask#localhost) and interact with your local setup, or try to deploy or interact with a smart contract.


# Connecting to a public network with local RPC node

Instructions on how to setup local RPC node that connects to a public network

Except from connecting to local development network, we can also run a local RPC node connecting to public networks.

```
npx @acala-network/eth-rpc-adapter@latest \
  --endpoint <node-endpoint-ws-url> \
  --subql <subquery-url>
```

Node endpoints and subquery urls can be found in [network configuration](/network/network-configuration).

For example to connect to acala mainnet:

```
npx @acala-network/eth-rpc-adapter@latest \
  --endpoint wss://acala-rpc.aca-api.network \
  --subql https://subql-query-acala.aca-api.network
```

Also checkout the help command for more details

```
npx @acala-network/eth-rpc-adapter@latest --help
```

{% hint style="info" %}
**If you wish to learn more about the RPC adapter, you can find more info in the** [**RPC adapter documentation**](https://github.com/AcalaNetwork/acala-evm-dev-docs/blob/master/tooling/rpc-adapter/running-the-rpc-adapter.md)**.**
{% endhint %}


# Predeployed smart contracts

Section detailing the precompiled and predeployed smart contracts of the Acala EVM+.

One of the great features of Acala EVM+ is the precompiled and the predeployed smart contracts.

## Precompiled smart contracts

The precompiled smart contracts allow for the use of the predeployed smart contracts within your project's smart contracts and scripts. Just import the `@acala-network/contracts` package and import them into your project. The package includes the smart contracts to import into the smart contracts of your project as well as their compiled versions in order to import them into the deploy, test and interaction scripts.

To add them to your project simply use:

```
yarn add --dev @acala-network/contracts
```

Once you add the dependency to the project you can simply import the contracts included in it like this:

```solidity
import "@acala-network/contracts/token/Token.sol";
```

And to use the precompiled smart contract within your script use the:

```javascript
const TokenContract = require("@acala-network/contracts/build/contracts/Token.json");
```

## Predeployed smart contracts

Predeployed smart contracts in Acala EVM+ allow for the reliable use of the smart contracts that are always deployed at the same address no matter the chain. The predeployed smart contracts include Tokens smart contracts, the native on chain scheduler called Schedule, Oracle, DEX and StateRent.

### ADDRESS utility

The `@acala-network/contracts` dependency contains the [`ADDRESS`](https://github.com/AcalaNetwork/predeploy-contracts/blob/master/contracts/utils/MandalaAddress.sol) utility which can be used in your smart contracts as well as scripts to access the predeployed smart contracts. It allows for using the addresses of the predeployed smart contracts without the need to copy-paste and hardcode these addresses into your project. There is an `ADDRESS` utility for each of the networks. The local development network and Mandala public test network use `MandalaAddress`, the Acala network uses the `AcalaAddress` and the Karura network uses the `KaruraAddress` to provide the correct addresses.

To use the utility within your smart contract simply import it using (for Mandala):

```solidity
import "@acala-network/contracts/utils/MandalaAddress.sol";
```

Make sure to set the inheritance of your contract to be able to interact with the `ADDRESS` utility:

```solidity
contract YourContract is ADDRESS {

}
```

To get the address of the DEX predeployed smart contract you can now simply use:

```solidity
ADDRESS.DEX
```

If you want to refer to the addresses of the predeployed smart contracts, take a look at the following page.


# Details

This section contains details about each of predeployed contracts, including their addresses, explanation, and deployment status.

deployment status:

* <img src="/files/3AMGup1zB8eRSRWlNkD4" alt="" data-size="line"> the predeployed smart contract is enabled and interactable with in the given network.
* <img src="/files/ZFSqrq1xwuRKP5gRnmph" alt="" data-size="line"> the predeployed smart contract has not been enabled in the given network yet.

## ERC20

The predeployed ERC20 smart contracts allow you to interact with these token contract reliably on all of the Acala EVM+ chain. You can also use these addresses to add the tokens to your MetaMask or any other EVM wallet you might use with the Acala EVM+.

The most up to date list of ERC20 addresses can be found in the [predeploy-contracts repository](https://github.com/AcalaNetwork/predeploy-contracts/tree/master/contracts/utils)

|                              Acala                              |                              Karura                             |                             Mandala                             |
| :-------------------------------------------------------------: | :-------------------------------------------------------------: | :-------------------------------------------------------------: |
| <img src="/files/3AMGup1zB8eRSRWlNkD4" alt="" data-size="line"> | <img src="/files/3AMGup1zB8eRSRWlNkD4" alt="" data-size="line"> | <img src="/files/Ys4fO9UKnrvwev4Sermw" alt="" data-size="line"> |

{% tabs %}
{% tab title="Acala" %}

| Token            | Address                                    |
| ---------------- | ------------------------------------------ |
| ACA              | 0x0000000000000000000100000000000000000000 |
| aSEED            | 0x0000000000000000000100000000000000000001 |
| DOT              | 0x0000000000000000000100000000000000000002 |
| LDOT             | 0x0000000000000000000100000000000000000003 |
| LCDOT            | 0x000000000000000000040000000000000000000d |
| SA\_DOT          | 0x0000000000000000000300000000000000000000 |
| FA\_GLMR         | 0x0000000000000000000500000000000000000000 |
| FA\_PARA         | 0x0000000000000000000500000000000000000001 |
| FA\_ASTR         | 0x0000000000000000000500000000000000000002 |
| FA\_IBTC         | 0x0000000000000000000500000000000000000003 |
| FA\_INTR         | 0x0000000000000000000500000000000000000004 |
| FA\_WBTC         | 0x0000000000000000000500000000000000000005 |
| FA\_WETH         | 0x0000000000000000000500000000000000000006 |
| FA\_EQ           | 0x0000000000000000000500000000000000000007 |
| FA\_EQD          | 0x0000000000000000000500000000000000000008 |
| LP\_ACA\_aSEED   | 0x0000000000000000000200000000000000000001 |
| LP\_LDOT\_aSEED  | 0x0000000000000000000200000000010000000003 |
| LP\_LCDOT\_aSEED | 0x000000000000000000020000000001020000000D |
| LP\_LCDOT\_DOT   | 0x000000000000000000020000000002020000000d |
| {% endtab %}     |                                            |

{% tab title="Karura" %}

| Token           | Address                                    |
| --------------- | ------------------------------------------ |
| KAR             | 0x0000000000000000000100000000000000000080 |
| aSEED           | 0x0000000000000000000100000000000000000081 |
| KSM             | 0x0000000000000000000100000000000000000082 |
| LKSM            | 0x0000000000000000000100000000000000000083 |
| TAI             | 0x0000000000000000000100000000000000000084 |
| BNC             | 0x00000000000000000001000000000000000000a8 |
| VSKSM           | 0x00000000000000000001000000000000000000A9 |
| PHA             | 0x00000000000000000001000000000000000000Aa |
| KINT            | 0x00000000000000000001000000000000000000AB |
| KBTC            | 0x00000000000000000001000000000000000000aC |
| FA\_USDT        | 0x0000000000000000000500000000000000000007 |
| SA\_KSM         | 0x0000000000000000000300000000000000000000 |
| SA\_3USD        | 0x0000000000000000000300000000000000000001 |
| FA\_RMRK        | 0x0000000000000000000500000000000000000000 |
| FA\_ARIS        | 0x0000000000000000000500000000000000000001 |
| FA\_QTZ         | 0x0000000000000000000500000000000000000002 |
| FA\_MOVR        | 0x0000000000000000000500000000000000000003 |
| FA\_HKO         | 0x0000000000000000000500000000000000000004 |
| FA\_CSM         | 0x0000000000000000000500000000000000000005 |
| FA\_KICO        | 0x0000000000000000000500000000000000000006 |
| FA\_USDT        | 0x0000000000000000000500000000000000000007 |
| FA\_TEER        | 0x0000000000000000000500000000000000000008 |
| FA\_NEER        | 0x0000000000000000000500000000000000000009 |
| FA\_KMA         | 0x000000000000000000050000000000000000000a |
| FA\_BSX         | 0x000000000000000000050000000000000000000b |
| FA\_AIR         | 0x000000000000000000050000000000000000000c |
| FA\_CRAB        | 0x000000000000000000050000000000000000000d |
| FA\_GENS        | 0x000000000000000000050000000000000000000E |
| FA\_EQD         | 0x000000000000000000050000000000000000000f |
| FA\_TUR         | 0x0000000000000000000500000000000000000010 |
| FA\_PCHU        | 0x0000000000000000000500000000000000000011 |
| FA\_SDN         | 0x0000000000000000000500000000000000000012 |
| FA\_LT          | 0x0000000000000000000500000000000000000013 |
| LP\_KAR\_aSEED  | 0x0000000000000000000200000000800000000081 |
| LP\_KSM\_aSEED  | 0x0000000000000000000200000000810000000082 |
| LP\_LKSM\_aSEED | 0x0000000000000000000200000000810000000083 |
| LP\_BNC\_aSEED  | 0x00000000000000000002000000008100000000a8 |
| LP\_PHA\_aSEED  | 0x00000000000000000002000000008100000000aa |
| LP\_KINT\_aSEED | 0x00000000000000000002000000008100000000Ab |
| LP\_KBTC\_aSEED | 0x00000000000000000002000000008100000000aC |
| LP\_RMRK\_aSEED | 0x0000000000000000000200000000810300000000 |
| LP\_QTZ\_aSEED  | 0x0000000000000000000200000000810300000002 |
| LP\_CSM\_aSEED  | 0x0000000000000000000200000000810300000005 |
| LP\_AIR\_aSEED  | 0x000000000000000000020000000081030000000c |
| LP\_LKSM\_KAR   | 0x0000000000000000000200000000800000000083 |
| LP\_QTZ\_KAR    | 0x0000000000000000000200000000800300000002 |
| LP\_KAR\_KSM    | 0x0000000000000000000200000000800000000082 |
| LP\_LKSM\_KSM   | 0x0000000000000000000200000000820000000083 |
| LP\_RMRK\_KSM   | 0x0000000000000000000200000000820300000000 |
| LP\_ARIS\_KSM   | 0x0000000000000000000200000000820300000001 |
| LP\_RMRK\_TAI   | 0x0000000000000000000200000000840300000000 |
| {% endtab %}    |                                            |

{% tab title="Mandala" %}

| Token         | Address                                    |
| ------------- | ------------------------------------------ |
| ACA           | 0x0000000000000000000100000000000000000000 |
| DOT           | 0x0000000000000000000100000000000000000002 |
| LDOT          | 0x0000000000000000000100000000000000000003 |
| LCDOT         | 0x000000000000000000040000000000000000000d |
| {% endtab %}  |                                            |
| {% endtabs %} |                                            |

## DEX

The DEX smart contract allows you to interact with the built in DEX of the Acala EVM+. You can take a look at [DEX tutorial](https://github.com/AcalaNetwork/acala-evm-dev-docs/blob/master/examples/truffle-tutorials/dex-tutorial.md) in order to see it in action.

|                              Acala                              |                              Karura                             |                             Mandala                             |
| :-------------------------------------------------------------: | :-------------------------------------------------------------: | :-------------------------------------------------------------: |
| <img src="/files/3AMGup1zB8eRSRWlNkD4" alt="" data-size="line"> | <img src="/files/3AMGup1zB8eRSRWlNkD4" alt="" data-size="line"> | <img src="/files/Ys4fO9UKnrvwev4Sermw" alt="" data-size="line"> |

| Smart contract | Address                                    |
| -------------- | ------------------------------------------ |
| DEX            | 0x0000000000000000000000000000000000000803 |

## EVM

The EVM smart contract allows you to manage the development aspect of you account and the smart contracts that you deployed or are in control of. If you wish to see more about how the EVM predeployed smart contract works, you can take a look at the [EVM tutorial](https://github.com/AcalaNetwork/acala-evm-dev-docs/blob/master/examples/hardhat-tutorials/evm-tutorial.md).

|                              Acala                              |                              Karura                             |                             Mandala                             |
| :-------------------------------------------------------------: | :-------------------------------------------------------------: | :-------------------------------------------------------------: |
| <img src="/files/uo5ccvrinPYotDlcLyzx" alt="" data-size="line"> | <img src="/files/ax79lNwmcggP8Ai6rhBk" alt="" data-size="line"> | <img src="/files/Ys4fO9UKnrvwev4Sermw" alt="" data-size="line"> |

| Smart contract | Address                                    |
| -------------- | ------------------------------------------ |
| EVM            | 0x0000000000000000000000000000000000000800 |

## Oracle

The Oracle predeployed smart contract allows you to get the prices of the supported tokens.

|                              Acala                              |                              Karura                             |                             Mandala                             |
| :-------------------------------------------------------------: | :-------------------------------------------------------------: | :-------------------------------------------------------------: |
| <img src="/files/uo5ccvrinPYotDlcLyzx" alt="" data-size="line"> | <img src="/files/ax79lNwmcggP8Ai6rhBk" alt="" data-size="line"> | <img src="/files/Ys4fO9UKnrvwev4Sermw" alt="" data-size="line"> |

| Smart contract | Address                                    |
| -------------- | ------------------------------------------ |
| ORACLE         | 0x0000000000000000000000000000000000000801 |

## Schedule

The Schedule smart contract allows you to schedule the on-chain calls without the need for the off-chain interaction. To see the Schedule in action, you can take a look at the [Advanced escrow](https://github.com/AcalaNetwork/acala-evm-dev-docs/blob/master/examples/hardhat-tutorials/advancedescrow-tutorial.md) tutorial.

|                              Acala                              |                              Karura                             |                             Mandala                             |
| :-------------------------------------------------------------: | :-------------------------------------------------------------: | :-------------------------------------------------------------: |
| <img src="/files/ZFSqrq1xwuRKP5gRnmph" alt="" data-size="line"> | <img src="/files/ZFSqrq1xwuRKP5gRnmph" alt="" data-size="line"> | <img src="/files/Ys4fO9UKnrvwev4Sermw" alt="" data-size="line"> |

| Smart contract | Address                                    |
| -------------- | ------------------------------------------ |
| SCHEDULE       | 0x0000000000000000000000000000000000000802 |

## Stable asset

The Stable asset smart contract can be found at the address available above and you can take a look at it [here](https://github.com/AcalaNetwork/predeploy-contracts/blob/master/contracts/stable-asset/StableAsset.sol).

|                              Acala                              |                              Karura                             |                             Mandala                             |
| :-------------------------------------------------------------: | :-------------------------------------------------------------: | :-------------------------------------------------------------: |
| <img src="/files/3AMGup1zB8eRSRWlNkD4" alt="" data-size="line"> | <img src="/files/ZFSqrq1xwuRKP5gRnmph" alt="" data-size="line"> | <img src="/files/ZFSqrq1xwuRKP5gRnmph" alt="" data-size="line"> |

| Smart contract | Address                                    |
| -------------- | ------------------------------------------ |
| STABLE\_ASSET  | 0x0000000000000000000000000000000000000804 |

## Homa

The Homa smart contract can be found at the address available above and you can take a look at it [here](https://github.com/AcalaNetwork/predeploy-contracts/blob/master/contracts/homa/Homa.sol).

|                              Acala                              |                              Karura                             |                             Mandala                             |
| :-------------------------------------------------------------: | :-------------------------------------------------------------: | :-------------------------------------------------------------: |
| <img src="/files/3AMGup1zB8eRSRWlNkD4" alt="" data-size="line"> | <img src="/files/3AMGup1zB8eRSRWlNkD4" alt="" data-size="line"> | <img src="/files/ZFSqrq1xwuRKP5gRnmph" alt="" data-size="line"> |

| Smart contract | Address                                    |
| -------------- | ------------------------------------------ |
| HOMA           | 0x0000000000000000000000000000000000000805 |

## EVM Accounts

The EVM Accounts smart contract is used for simple account management and its source code can be found [here](https://github.com/AcalaNetwork/predeploy-contracts/blob/master/contracts/evm-accounts/EVMAccounts.sol).

|                              Acala                              |                              Karura                             |                             Mandala                             |
| :-------------------------------------------------------------: | :-------------------------------------------------------------: | :-------------------------------------------------------------: |
| <img src="/files/3AMGup1zB8eRSRWlNkD4" alt="" data-size="line"> | <img src="/files/3AMGup1zB8eRSRWlNkD4" alt="" data-size="line"> | <img src="/files/3AMGup1zB8eRSRWlNkD4" alt="" data-size="line"> |

| Smart contract | Address                                    |
| -------------- | ------------------------------------------ |
| EVM\_ACCOUNTS  | 0x0000000000000000000000000000000000000806 |

## Honzon

The Honzon bridge smart contract can be reached at the address above and its source code is available [here](https://github.com/AcalaNetwork/predeploy-contracts/blob/master/contracts/honzon/Honzon.sol).

|                              Acala                              |                              Karura                             |                             Mandala                             |
| :-------------------------------------------------------------: | :-------------------------------------------------------------: | :-------------------------------------------------------------: |
| <img src="/files/ZFSqrq1xwuRKP5gRnmph" alt="" data-size="line"> | <img src="/files/ZFSqrq1xwuRKP5gRnmph" alt="" data-size="line"> | <img src="/files/ZFSqrq1xwuRKP5gRnmph" alt="" data-size="line"> |

| Smart contract | Address                                    |
| -------------- | ------------------------------------------ |
| HONZON         | 0x0000000000000000000000000000000000000807 |

## Incentives

The Incentives smart contract can be reached at the address above and its source code is available [here](https://github.com/AcalaNetwork/predeploy-contracts/blob/master/contracts/incentives/Incentives.sol).

|                              Acala                              |                              Karura                             |                             Mandala                             |
| :-------------------------------------------------------------: | :-------------------------------------------------------------: | :-------------------------------------------------------------: |
| <img src="/files/3AMGup1zB8eRSRWlNkD4" alt="" data-size="line"> | <img src="/files/3AMGup1zB8eRSRWlNkD4" alt="" data-size="line"> | <img src="/files/ZFSqrq1xwuRKP5gRnmph" alt="" data-size="line"> |

| Smart contract | Address                                    |
| -------------- | ------------------------------------------ |
| INCENTIVES     | 0x0000000000000000000000000000000000000808 |

## XTokens

The XTokens smart contract allows you to use XCM to transfer tokens between parachains.

|                              Acala                              |                              Karura                             |                             Mandala                             |
| :-------------------------------------------------------------: | :-------------------------------------------------------------: | :-------------------------------------------------------------: |
| <img src="/files/3AMGup1zB8eRSRWlNkD4" alt="" data-size="line"> | <img src="/files/3AMGup1zB8eRSRWlNkD4" alt="" data-size="line"> | <img src="/files/ZFSqrq1xwuRKP5gRnmph" alt="" data-size="line"> |

| Smart contract | Address                                    |
| -------------- | ------------------------------------------ |
| XTokens        | 0x0000000000000000000000000000000000000809 |


# ACA token

Explanation on how ACA ERC20 ties into Acala native token.

ACA token is synced in 3 places:

* acala native token
* evm native token
* evm predeployed ACA ERC20 token

Any change in the balance of any of the above, is reflected in all.

The predeployed ACA ERC20 smart contract is tied directly into the native ACA token of the Acala network. This means that you can transfer the ACA as you would the native currency, but you can also transfer it as an ERC20 token.

{% hint style="info" %}
Balances of the EVM accounts bound to the Polkadot.js accounts can differ from reasons other than existential deposit. One of such instances is staking.
{% endhint %}


# Gas parameters

The primary distinction between Acala EVM+ and the legacy EVM lies in the usage of encoded `gasPrice` and `gasLimit`, together referred to as "gas parameters".

## Context

Acala EVM+ operates on a substrate chain. Consequently, the gas parameters must encode four substrate parameters: `gasLimit`, `storageLimit`, `validUntil`, and `tip`. It's crucial to supply precise `gasPrice` to `gasLimit` values to ensure accurate decoding into substrate parameters. Arbitrary changes to these parameters could lead to incorrect decoding.

For instance, when a user sends a transaction with the following gas parameters:

```
{
  gasPrice: 100.004623375 gwei,
  gasLimit: 100106,
}
```

These parameters are decoded into substrate parameters as follows:

```
{
  validUntil: 4623375,
  gasLimit: 30000,
  storageLimit: 64,
  tip: 0,
}
```

Despite being inconsistent with the legacy EVM, this aspect is advantageous for Acala EVM+. It utilizes features unavailable in the legacy EVM. For example, the `validUntil` parameter prevents transactions from indefinitely lingering in the transaction pool. Additionally, the `storageLimit` encourages developers to remove redundant data from the chain, thereby reducing chain bloat.

## Retrieving Gas Parameters

### for users

Users are not required to calculate gas parameters:

* When sending tokens, MetaMask automatically retrieves the correct gas parameters by calling ETH RPC endpoints.
* During transaction signing, dApps provide the correct gas parameters to MetaMask, enabling users to sign a valid transaction.

However, users should avoid arbitrary modification of transaction parameters within MetaMask, as it could lead to transaction failure due to incorrect decoding. We recommend highlighting this warning within your dApp's user interface.

### for developers

Most tools and libraries (like `ethers`, `hardhat`, `truffle`) automatically calculate the correct gas parameters when sending a transaction. Developers typically do not need to intervene.

If gas parameters are not auto-computed, developers can calculate them as follows:

```ts
const gasPrice = await provider.getGasPrice();
const gasLimit = await contractInstance.estimateGas.functionName(...args);
```

## Gas Decoding Details

### without tip (default case)

Assume the Ethereum gasLimit is encoded as `aaaabbbcc` and gasPrice is encoded as `100yyyyyyyyy`. They can be decoded into substrate gas parameters as follows:

* `validUntil = yyyyyyyyy`
* `gasLimit = 30000 * bbb`
* `storageLimit = 2^min(21, cc)`

for example:

```
{
  gasPrice: 100004623375,   // 100yyyyyyyyy, where yyyyyyyyy = 004623375
  gasLimit: 100106,         // aaaabbbcc, where bbb = 001 and cc = 06
}
```

will be decoded as

```
{
  validUntil: 4623375,  // yyyyyyyyy
  gasLimit: 30000,      // 30000 * bbb = 30000 * 1 = 30000
  storageLimit: 64,     // 2 ^ min(21, cc) = 2 ^ 6 = 64
  tip: 0,
}
```

### with tip

The `gasLimit` remains unaffected by the tip, as the tip is encoded into `gasPrice` as `ab0yyyyyyyyy`.

* `tip = (ab0 / 100 - 1)% of the original cost`

for example:

```
{
  gasPrice: 120004623375,   // ab0yyyyyyyyy, where ab0 = 120
  gasLimit: 100106,         // same as above
}
```

will be decoded as

```
{
  validUntil: 4623375,  // same as above
  gasLimit: 30000,      // same as above
  storageLimit: 64,     // same as above
  tip: 20%,             // ab0 / 100 - 1 = 120 / 100 - 1 = 20%
}
```

## Modifying Gas Parameters

### for users

Users generally should avoid manually modifying gas parameters to prevent incorrect decoding. dApps should initiate signature requests with valid gas parameters, relieving users of any concern about gas calculation. Nonetheless, knowledgeable users can manually modify the `ab0` part of the gasPrice to increase the tip, which can expedite the transaction when the network is busy.

### for developers

Developers can offer different priority options to users and compute the corresponding `gasPrice`, eliminating the need for users to manually modify gas parameters. For instance:

* default priority: `ab0 = 100`, in which case gasPrice is calculated automatically by the toolings
* high priority: `ab0 = 120`, in which case tip = 20% of the original cost
* super high priority: `ab0 = 200`, in which case tip = 100% of the original cost

If developers choose not to offer such options, they can use the default gasPrice directly.

When prompting user signatures, developers should also calculate a valid gasLimit. Most often, the tools should auto-calculate the gasLimit. If not, developers can hardcode a valid gasLimit (a rare occurrence, but if it happens, please report to the Acala team). For example, if an auto-calculated `gasLimit = 100106` fails the transaction with an error like `storage limit not enough`, it implies the transaction requires more storage than the auto-computed storageLimit = `2 ^ 6 = 64`. If the actual storage cost is `100`, developers can use `cc = 7`, making `gasLimit = 100107`.


# Tooling

The following pages require information about tooling available to the developers developing on Acala EVM+.


# Faucet

The Mandala faucet is located in the [#acala-testnet-faucet channel on Discord](https://discord.gg/5JJgXKSznc). Send a `!drip` command with your Mandala address to receive testnet ACA, DOT, KSM and LKSM.


# RPC adapter

What is it and how to use it to debug your project

Many of the EVM tools rely on [JSON-RPC](https://ethereum.github.io/execution-apis/api-documentation/) to communicate with the chain. Acala chain node doesn't provide these RPCs out of the box, so we implemented the EVM+ RPC Adapter, which is a service that wrap substrate RPC calls to provide these ETH JSON-RPCs. As a result, existing Ethereum dApp and tools can interact with EVM+ with minumum changes.

For more information, checkout [eth rpc adapter docs](https://github.com/AcalaNetwork/bodhi.js/tree/master/packages/eth-rpc-adapter#acala-networketh-rpc-adapter).


# Chain explorer

Instructions on how to use the chain explorers of Acala EVM+

## Polkadot.js app

* [Acala](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Facala-rpc-0.aca-api.network#/explorer)
* [Karura](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fkarura-rpc-0.aca-api.network#/explorer)
* [Local](https://polkadot.js.org/apps/?rpc=ws%3A%2F%2F127.0.0.1%3A9944#/explorer)
* [Mandala](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fmandala-tc9-rpc.aca-staging.network%2Fws#/explorer)
* [Karura Testnet](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fkarura-testnet.aca-staging.network%2Frpc%2Fkarura%2Fws#/explorer)
* [Acala Testnet](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Facala-dev.aca-dev.network%2Frpc%2Fws#/explorer)

Alternatively you can go to <https://polkadot.js.org/apps/#/explorer>, and select the desired network from the top left corner's menu

## EVM chain explorer

Blockscout is our first official EVM chain block explorer.

* [Acala](https://blockscout.acala.network)
* [Karura](https://blockscout.karura.network)
* [Mandala](https://blockscout.mandala.aca-staging.network/)
* [Karura Testnet](https://blockscout.karura-testnet.aca-staging.network/)
* [Acala Testnet](https://blockscout.acala-dev.aca-dev.network/)

## Substrate chain explorer

You can put your EVM transaction hash at the end of these link to get the details:

* [Acala](https://acala.subscan.io)
* [Karura](https://karura.subscan.io)
* [Mandala](https://acala-testnet.subscan.io)


# MetaMask

MetaMask or any similar EVM wallet can be used to interact with the Acala EVM+. The next pages illustrate how you can connect to a network that has Acala EVM+ and how you can initiate transactions with it as well as how you can interact with the smart contracts deployed on it.


# Connect to the network

Instructions on how to connect MetaMask to Mandala EVM+ in order to interact with the smart contracts deployed on it.

You can add the network to the MetaMask using the [Chainlist service](https://chainlist.org/?search=acala) or follow the instructions on how to add the network manually.

## Automated process

Follow the link to the network you are trying to add, connect your wallet and the network will be added to your wallet.

{% embed url="<https://chainlist.org/chain/595>" %}
Automated process of adding the Mandala EVM+ network to your wallet
{% endembed %}

{% embed url="<https://chainlist.org/chain/686>" %}
Automated process of adding the Karura EVM+ network to your wallet
{% endembed %}

{% embed url="<https://chainlist.org/chain/787>" %}
Automated process of adding the Acala EVM+ network to your wallet
{% endembed %}

## Manual process

{% hint style="info" %}
NOTE: The manual process example connects to the Mandala EVM+. For other networks can substitute the values with any of the values provided at the [network configuration](/network/network-configuration) section.
{% endhint %}

In order to be able to interact with the Acala EVM+ in Mandala TC9, you first need to navigate to the **Add network** section of the MetaMask. You can find it at the bottom of the list of available networks after clicking on the currently active network.

![MetaMask => Currently active network => Add network](https://1503523808-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MAz4EenwXLth_HO_hmJ-887967055%2Fuploads%2FWz1rByJAVVr5MOdxgEaS%2FScreenshot%202022-03-02%20at%2002.22.49.png?alt=media\&token=365d2c22-49d2-4952-94cf-54a7fe154ad8)

This should open up a form to add a new network to your MetaMask (you might have to unlock MetaMask before it opens). Once the form is opened, use the following information to add the Mandala TC9 network.


# Simple transactions

Example on how to transfer ACA using MetaMask.

MetaMask can be used to transfer ACA in the same manner, you would transfer Ether in Ethereum network:

1. Open and unlock the MetaMask
2. Click on **Send** option
3. Paste the EVM account address that you want to send the ACA to and input the amount of ACA you want to send and click **Next**
4. Verify that the transaction data is correct and click **Confirm**
5. You are done! The ACA has been sent to the desired address

![MetaMask => Send => Input amount & Next => Confirm](/files/smMZgMHwuPj4X8cyvwlA)

{% hint style="info" %}
before sending any transaction, please don't change the default `gasPrice` or `GasLimit`, otherwise transaction will fail. ([why?](/miscellaneous/faqs#why-tx-failed-after-i-manually-changed-gas-params-in-metamask))
{% endhint %}

{% hint style="info" %}
if we are using local mandala, everytime we restart the local mandala node, we need to reset metamask for local network, so the nonce and cache will be cleared: `settings => advanced => reset account`. ([why?](/miscellaneous/faqs#why-metamask-tx-doesnt-confirm-with-local-mandala))
{% endhint %}


# EVM playground

{% hint style="warning" %}
evm playground is a legacy UI to interact with EVM+, and is no longer under maintainance. Using toolings such as hardhat or remix is recommended. ([examples](/examples/examples))
{% endhint %}

The EVM playground can be found here: <https://evm.acala.network/>


# Deploy smart contracts

Instructions on how to deploy a smart contract using EVM playgrounds

{% hint style="info" %}
This entry assumes that you have already [configured your Metamask](/tooling/metamask/connect-to-the-network) to connect to Acala EVM+.
{% endhint %}

To deploy a smart contract using [EVM playgrounds](https://evm.acala.network/), you need to compile your smart contract in your preferred development framework so that you have the ABI bundle available to upload.

## Upload the ABI bundle

Open the [Upload tab](https://evm.acala.network/#/upload) in the EVM playgrounds. Here you can upload an ABI bundle of the smart contract that you want to deploy. This will allow you to use it to deploy the smart contract:

![EVM playgrounds => Upload](/files/RZHTa78tCMk6fpBEj9QE)

Assign the `Name` of your smart contract. You will be able to identify the smart contract in the `Deploy` tab with it, once it gets uploaded.

To upload the ABI bundle itself, you can either drag and drop it into the upload section, or click on the section and select the file.

![EVM playgrounds => Upload => Add file](/files/zU23N2swe2p2wfhviPVp)

Once you have selected the correct ABI bundle, the methods of the smart contract should be displayed. You can verify that the correct methods are listed and press `Upload` to upload the ABI bundle.

## Deploy the smart contract

Smart contracts can be deployed under the [Deploy tab](https://evm.acala.network/#/deploy) of the EVM playgrounds.

The ABI bundles that you uploaded in the `Upload` tab can be seen here:

![EVM playgrounds => Deploy](/files/wKwoGJRyYDtfqKB6uGK0)

The methods available for an ABI bundle can be seen by expanding the `ABI` menu. This can be helpful if you have multiple bundles uploaded and you want to be sure that you will be interacting with the right one.

![EVM playgrounds => Deploy => Expand ABI section ](/files/55cL6n4ZZlI38Ud66IWP)

When you have verified that you are interacting with the ABI bundle that has the correct methods available, you can click `Deploy`, which should open a deployment interface:

![EVM Playgrounds => Deploy => Deploy selected ABI bundle](/files/PCVcJrldQum69Xg8bCDK)

The interface consists of the following components:

* Button to connect to your EVM wallet (this is why connecting MetaMask to the EVM+ is a prerequisite for this entry)
* Smart contract name, that can be changed, so you can deploy the same ABI bundle multiple times and easily differentiate between them
* ABI bundle identifications
* Fields to input the smart contract constructor parameters
* Value field to determine wether to send some of the native currency with the deploy transaction
* Fields to override the [`gas parameters`](/network/gas-parameters)
* `Deploy` button to deploy the smart contract once you are satisfied with the deployment parameters

### 1. Connect your EVM wallet

Pressing the <img src="/files/mpcWfAWhyri19g06lEU5" alt="" data-size="line"> button will prompt your EVM wallet to connect to the site. You can select the account that you want to use with the EVM playgrounds and connect it.

![](/files/GYFlrwjFOdvLs4W1fnyy)<img src="/files/ab7GbUxQA8Xeiukbmi3S" alt="" data-size="original">

The selected account should be displayed at the top of the page now:

![Displayed deployment account](/files/VsatL74MjSUU9fLz9b1Z)

### 2. Update the required deployment parameters

Depending on the requirements, you can modify the deployment parameters of your smart contract. It is required to fill out the constructor parameters, but modifying other values is optional.

![Filled out deployment values](/files/llrblPjdiM6HPiQmhwnz)

Once the values are filled out and double checked, the smart contract is ready to be deployed.

{% hint style="warning" %}
The `validUntil` field value has to be higher than the current block number, or the deployment transaction will fail, due to the validator treating it as outdated. You can verify the current block number in a [block explorer](/tooling/chain-explorer).
{% endhint %}

### 3. Deploy the smart contract

Once the parameters of deployment are ready, you can deploy the smart contract by pressing the `Deploy` button. This should prompt your EVM wallet to confirm your deployment transaction:

![Confirming the deployment transaction](/files/PitYQq8BvJHl0OG6BAKu)

The deployed smart contract can now be seen in the `Execute` tab, which is [further explained](/tooling/evm-playground/interacting-with-smart-contracts) in the next entry.


# Interacting with smart contracts

Instructions on how to use EVM playgrounds to interact with smart contracts deployed on Acala EVM+.

You can use the [EVM playground](https://evm.acala.network/) in order to interact with smart contracts that have been deployed to the Acala EVM+.

To do that, open <https://evm.acala.network/#/execute>:

![EVM Playground => Execute](/files/yytWawYMfcfuc4le0f01)

Select the **Add and Existing Contract** option, which will open the form to add an existing smart contract to the collection of the executable smart contracts. For the sake of the documentation, aUSD ERC20 smart contract will be added. You can get its address from the [ADDRESS utility](https://github.com/AcalaNetwork/predeploy-contracts/blob/master/contracts/utils/Address.sol) and the precompiled ABI of the smart contract within the [AcalaNetwork/predeploy-contracts](https://github.com/AcalaNetwork/predeploy-contracts) repository. Once you fill out the form you can click **Save** and the smart contract will be added to your collection.

![Filled out form for adding aUSD smart contract to the EVM Playground](/files/k4Zimsjsm2Z2XL4y1ap1)

{% hint style="info" %}
In some rare cases, the collection page won't load after you save a new smart contract, so you need to refresh the page.
{% endhint %}

Once you locate your newly saved smart contracts to the executable smart contracts collection, you can interact with it by pressing the **Execute** button below its address.

![Saved Executable smart contract](/files/OdZMFu2c36fRroVMKvFv)

If you are using the EVM Playground for the first time you will need to connect your MetaMask to it in order to be able to use it. To connect your MetaMask, click the **Connect to MetaMask** button, which will prompt the MetaMask to open and you can select the desired account that you want to connect with the EVM Playgrounds.

![Connect MetaMask before you interact with the EVM Playgrounds](/files/UWpajyq8S8FH8OSj2cel)

Once your MetaMask is connected to the EVM Playgrounds, you can interact with the smart contract, by selecting the function that you would like to call from the **Message to Send** dropdown menu and filling out the required parameters (if there are any). Once you are satisfied with the call and the values passed to it, you can press the **Call** button, which will initiate the transaction.

![Selecting the Message to Send and sending the Call](/files/VfgT4i13qrTjdt5apv0y)


# Remix IDE

Introduction into using Remix IDE with Acala EVM+.

You can use the [Remix IDE](https://remix.ethereum.org/), online smart contract development IDE, to deploy and interact with your smart contracts on Acala EVM+. Prerequisite for using Remix with Acala EVM+ is that you have your MetaMask wallet connected to the network. If you haven't done it yet, you can follow the [MetaMask setup guide](/tooling/metamask).

## Connecting Remix IDE to MetaMask

To connect the Remix IDE to your MetaMask, and subsequently to the Acala EVM+, you have to first go to [Remix IDE](https://remix.ethereum.org/) and open the `Deploy & run transactions` tab.

{% hint style="info" %}
The `Deploy & run transactions` tab is represented by ![](/files/oZw8hp9tu2ZhMl2FTDHy) icon.
{% endhint %}

Once the tab opens, locate the `Environment menu` and select the `Injected Web3` option.

![](/files/WhaCPY8kqh6k27A8seNy)

As you select the `Injected Web3` option, MetaMask window should pop up and prompt you to select accounts that you want to connect to Remix IDE.

![](/files/HOJyZbl9iFHKQ8WzrJfH)

The second screen should provide which information is received by Remix and you can finally connect the two. Once you do, the account should appear in the side `Deploy & run transactions` menu, as well as it's balance.

![](/files/Kyv8PfK73aex0Ipdmjsf)

Now that we are ready to use the Remix IDE, we can take a look on how to interact with the smart contracts that are already deployed on the network and how to deploy our own.


# Deploying a smart contract

Walk through on deploying a smart contract to Acala EVM+ using Remix IDE.

Assuming you have already connected Remix IDE to MetaMask and added the `Echo` smart contract from the [`Interacting with the deployed smart contracts`](/tooling/remix-ide/interacting-with-the-deployed-smart-contracts) walk through, we can take a look at how to deploy the `Echo` smart contract using Remix IDE.

{% hint style="info" %}
This walk through focuses on specifics of deploying a smart contract to Acala EVM+ using Remix IDE. If you wish to learn more about deploying smart contracts using Remix IDE, please refer to the [official documentation](https://remix-ide.readthedocs.io/en/latest/create_deploy.html#deploy-the-contract).
{% endhint %}

You should see a `scripts` folder under your `File explorers` section. We will be modifying the `deploy_ethers.js` in this walk through.

As the example smart contract is called `Echo`, we have to modify the 6th line in the file, so that the value of `contractName` variable is `'Echo'`.

```javascript
        const contractName = 'Echo'
```

This finishes up the modifications we need to do to the `deploy_ethers.js` file. We are now able to run the script, by option-clicking on it in the `File explorers` menu and selecting the `Run` option. This will open a MetaMask prompt, where we have to confirm the deploy transaction.

![](/files/plZFVFj9ZExOy6Yr2XrV)

After the deployment transaction is included in a block, we can start interacting with our newly deployed smart contract, just like we did in the `Interacting with the deployed smart contracts` walk through.


# Interacting with the deployed smart contracts

Walk through on how to interact with an already deployed smart contract.

Now that Remix IDE is connected to the Mandala test network, we can interact with the smart contracts deployed on it. As you complete the setting up, you can take a look at the `File explorers` section. It should already include folders named `contracts`, `scripts` and `tests`, as well as `REAMDE.txt`.

{% hint style="info" %}
File explorers section is represented by the <img src="/files/E1OYXQrEqdWbLGH4UN7x" alt="" data-size="line"> icon.
{% endhint %}

We can use a very simple smart contract that is further explained in the tutorials section and is already deployed on the Mandala TC9 network. The smart contract is called Echo and it has one function that stores a value passed to it in a public variable, which we are able to get using it's getter function. In order to use Remix IDE to interact with it, we need to add it into the `contracts` folder. We do this by option-clicking onto the folder and selecting `New file` option. the file should be named `Echo.sol`. You can now copy-paste the following code into the file:

{% code title="Echo.sol" %}

```solidity
pragma solidity =0.8.9;

contract Echo{
    string public echo;
    uint echoCount;

    event NewEcho(string message, uint count);

    constructor() {
        echo = "Deployed successfully!";
    }

    function scream(string memory message) public returns(string memory){
        echo = message;
        echoCount += 1;
        emit NewEcho(message, echoCount);
        return message;
    }
}
```

{% endcode %}

Once you save the file, the Remix IDE built-in compiler will run and compile the smart contract. If the compilation fails (you can see that by a red error indicator appearing over the Solidity compiler section <img src="/files/HmQt8uVW03ZuJ0bcb99Z" alt="" data-size="line">), you might have to manually set the compiler version to `0.8.9.`

![](/files/IaoJQ5YjleeketLyT3uU)

As the smart contract compiles as expected, we need to point to the address to which it is deployed to. There is an instance deployed at `0x87c8Dc09548195A3B1222ab5c3905c01595D5516`, so you can use this one. To use it, navigate to `Deploy & run transactions` tab and paste the address into the `At Address` section.

{% hint style="info" %}
The Deploy & run transactions is represented by <img src="/files/QnXLP0wYjlTcUtRdJlj1" alt="" data-size="line"> icon.
{% endhint %}

![](/files/M91c5aiKK39tesW6FrqA)

Once you click on the `At Address` button, you should see `ECHO` in the `Deployed contracts` section.

![](/files/1EiIZ4Njd8IFYt2dzHSV)

Once you expand the view, you can interact with the smart contract. If you select the `echo` getter, there will be no MetaMask confirmation needed, as no transaction is executed. If you select scream, then you should pass a string to it within the `""` and confirm the transaction in MetaMask as the prompt appears.


# Examples

Start using your preferred development framework and toolings with Acala EVM+.

Acala EVM+ is built in a way that is developer-friendly, this means that you can use any development framework that you prefer and develop, test and deploy onto our network.

Depending on which framework/tooling you prefer, there are slight modifications you need to implement in order to get access to the full power of the Acala EVM+. To understand them, check out the following guides and start your development journey on Acala EVM+.

* Framework Examples
  * [hardhat](https://github.com/AcalaNetwork/hardhat-tutorials)
  * [truffle](https://github.com/AcalaNetwork/truffle-tutorials)
  * [foundry](https://github.com/AcalaNetwork/bodhi.js/tree/master/examples/foundry/counter)
* Tooling Examples
  * [subquery](https://github.com/AcalaNetwork/acala-evm-indexer-examples/tree/master/subquery)
  * [chopsticks](https://github.com/AcalaNetwork/bodhi.js/tree/master/examples/chopsticks)
  * [the graph](https://github.com/AcalaNetwork/acala-evm-indexer-examples/tree/master/the-graph) (deprecated)
  * [subsquid](https://github.com/AcalaNetwork/acala-evm-indexer-examples/tree/master/subsquid) (WIP)


# Special features

The following section showcases the special features available in the Acala EVM+, such as using a Polkadot wallet to interact with the EVM+ and much more.


# Using polkadot wallet to interact with EVM+

In traditional EVM world, usually the only way to interact with DApps is through Metamask. One cool feature that EVM+ provides is that users can also use polkadot wallets.

Check out the [basic example](https://github.com/AcalaNetwork/bodhi-examples/tree/master/deploy-contract) on how to sign Acala EVM+ transactions with a Polkadot wallet with the [bodhi.js](https://github.com/AcalaNetwork/bodhi.js/tree/master/packages/bodhi#create-a-wallet) SDK.


# Batch EVM transactions

One of the advanced feature of EVM+, compared to traditional EVM, is the ability to do batch transaction.

This example will show how to batch transactions with polkadot wallet and [bodhi.js](https://github.com/AcalaNetwork/bodhi.js/tree/master/packages/bodhi#create-a-wallet) SDK，so users can deploy multiple contracts at once, and perform approve token and add liquidity transactions within a single transaction.

{% hint style="info" %}
Before diving into this advanced example, we suggest going over the [basic example](/special-features/using-bodhi.js-to-deploy-smart-contract-and-interact-with-it) first
{% endhint %}

The example is [here](https://github.com/AcalaNetwork/bodhi-examples/tree/master/batch-transactions).


# Acala Multichain Asset Router

## What is the Acala Multichain Asset Router?

Acala Multichain Asset Router is a cross-chain asset transfer protocol built on Acala EVM+. It links the Wormhole Bridge and Cross-Consensus Message (XCM), enabling users to seamlessly transfer assets between any EVM chain and parachains in the Polkadot ecosystem.

<figure><img src="/files/1HFTdtUkg4iErkm7Hc6J" alt=""><figcaption></figcaption></figure>

**Benefits for users:** use one application rather than multiple, better efficiency in transactions and fees.\
**Benefits for applications/networks:** integrate with Asset Router and expose to liquidity on networks supported by Wormhole, and Polkadot/Kusama networks supported by Acala/Karura.

## Routing User Experience (UX)

Users can navigate to the Acala DApps UI, select the source and target chains, and choose the token to transfer. If the token is from EVM chains, the user will sign a transaction on MetaMask to approve the transfer. Conversely, if the token is from parachains, the user will sign a transaction with polkadot wallet. After the transaction confirmation, the user can click the "route" button on the UI to automatically transfer the asset to the target chain.

## Technical Details

### Components

The routing process involves several components:

* **Wormhole protocol**: This allows users to transfer assets between EVM chains and Acala/Karura.
* **Relayer**: This service automates wormhole token transfers, so users do not need to send extra redeem transactions on the target chain. It also encapsulates all interactions with the wormhole and asset router contracts, so the UI only needs to call its endpoints to complete the routing process, without worrying about low level details.
* **Asset router contracts**:
  * A router address on Acala/Karura, which is computed by the factory contract.
  * A factory contract, which calculates the router address based on the XCM or wormhole instructions. After the asset arrives at the router address, it deploys the router contract to the router address, and calls it to execute the routing.
* **Xtokens contracts**: A pre-deployed contract on Acala/Karura, which empowers EVM+ to call XCM that transfers tokens among parachains.

### Routing Process

The endpoints mentioned below are all associated with the relayer's endpoints.

#### EVM => Parachain

1. The user selects the source and target chains, as well as the token to transfer.
2. UI calls [/shouldRouteXcm](#shouldroutexcm) with the encoded config to get the router address on Acala/Karura.
3. UI prompts the user to sign a transaction with MetaMask that bridges through the wormhole from the EVM chain to the Acala/Karura router address.
4. UI fetches the Wormhole VAA.
5. UI calls [/relayAndRoute](#relayandroute) with the VAA. This performs two actions behind the scenes:
   * Relays (redeems) the token from the wormhole to the Acala/Karura router address.
   * Performs routing, which involves calling the Xtokens contract to XCM the token to the target parachain.

#### Parachain => EVM

1. The user selects the source and target chains, as well as the token to transfer.
2. UI calls [/shouldRouteWormhole](#shouldroutewormhole) with the encoded config to get the router address on Acala/Karura.
3. UI prompts the user to sign a transaction with the Polkadot wallet that XCMs the token from the source parachain to the router address on Acala/Karura.
4. UI calls [/routewormhole](#routewormhole). This sends the tokens to the wormhole from the router address.
5. UI fetches the Wormhole VAA.
6. UI prompts the user to sign a transaction with MetaMask that redeems the token on the target EVM chain.

## More References

* [asset router contracts](https://github.com/AcalaNetwork/asset-router/tree/master/src)
* [relayer source code](https://github.com/AcalaNetwork/wormhole-relayer)
* [wormhole docs](https://docs.wormhole.com/wormhole/)
* [wormhole development book](https://book.wormhole.com/)
* [Cross-Consensus Message (XCM)](https://wiki.polkadot.network/docs/learn-xcm)
* [xtokens pre-deployed contracts](https://github.com/AcalaNetwork/predeploy-contracts/blob/master/contracts/docs/xtokens/Xtokens.md)


# FAQs

## when do I need to provide subquery url for `eth-rpc-adpater` or `EvmRpcProvider`?

**short answer**

you need it when you ...

* need to query for historical logs or tx receipts that exist **before** you start the provider or rpc adapter
* OR need to query for logs or tx receipts that's older than [MAX\_CACHE\_SIZE](broken://pages/hRcjzWtzeo4O32FWL3Yb#list-of-options), which defaults to 200.

**explanation**

Transactions and logs from unfinalized blocks only live in cache, so new transactions will usually be in the cache first (for a couple blocks), then live in both the cache and the subquery, later, after the cache expires, they only live in subquery.

Developers who run a mandala node and eth-rpc-adaptor locally, usually won’t need to start any subquery or database services for testing, since new transaction receipts and logs will be in cache and findable without subquery.

For simple local testing setup, we can set a large `MAX_CACHE_SIZE` for rpc adapter, such as 10000 blocks. So even without subquery, we should be able to query for receipts and logs for as many as 10000 blocks.

![Cache vs. SubQuery representation](/files/aHo4IuMrs9fqlH00lQf1)

## why tx failed after I manually changed gas params in metamask?

Acala EVM+ uses encoded `gasPrice` and `gasLimit`, so manually inputting random gas parameters might fail to decode. Please refer to [gas parameter](/network/gas-parameters) section for detailed explanations.

## why metamask tx doesn't confirm with local mandala?

Metamask will sometimes cache the nonce locally, which is used to infer next tx nonce. For example, if we send a tx with nonce 3, metamask will set nonce 4 for next tx. However, after we restart the local mandala node, all accounts are reset and the nonce is back to 0, but metamaks doesn't know it!

As a result, the account with nonce 0 send a tx with nonce 4, which won't be mined and got stuck!

To solve this, we need to reset metamask after restarting local Mandala, so the nonce and cache will be cleared: `settings => advanced => reset account`. Or we can simply manually override the nonce to `0` for the first metamask tx after restarting the network.

## I have balance in metamask, but transfer failed

Metamask shows **total balance**, which might include non-transferable balances. For example, if some of your ACA is staking, they will still show in metamask, but can't be transfered.

We can check the transferable balance in the `Accounts` section in [polkadot.js app](/tooling/chain-explorer#polkadotjs-app)

## tx failing reason not showing in blockscout

Every EVM+ transaction is essentially a substrate transaction, so we can find more details about it in [substrate chain explorer](/tooling/chain-explorer#substrate-chain-explorer).

For example, for [this failing tx](https://blockscout.acala.network/tx/0xec304c62a61c56680522c09a80c7280fe4d985038203df70435cc925a7fe877f/internal-transactions), we can copy and paste the tx hash into the [Acala Subscan](https://acala.subscan.io/), which takes us to the [tx details page](https://acala.subscan.io/extrinsic/0xec304c62a61c56680522c09a80c7280fe4d985038203df70435cc925a7fe877f), the exact error should show up in the bottom `Events` section.

In this case `ReserveStorageFailed` means account balance not enough.

![tx failed reason](/files/XHhWDPdOg8pp47v4qie6)

## how to check if a transaction is finalized?

there are 2 ways:

* use `eth_getBlockByNumber` with `finalized` block tag to get the latest finalized block number, and compare the tx block number with it.
* use EVM+ specific RPC calls: [eth\_isTransactionFinalized](broken://pages/5Xtilv8OmaovQAOqMzLq#custom-rpcs) or [eth\_isBlockFinalized](broken://pages/5Xtilv8OmaovQAOqMzLq#custom-rpcs).


# Common errors

This page summarises common errors that you might encounter while developing on Acala EVM+. If an error occurs that is not listed here, please reach out, so we might lend a hand and include it on this page.

## ProviderError: Error: -32603: execution fatal

### `{ index: 180, error: 0, message: None }`

**Error name:** AddressNotMapped

**Error explanation:** This means that maintenance features are called on a smart contract, that doesn't have an EVM address bound to it

**Common causes:**

* Should not happen, because even if no user account is associated with the smart contract, it should bind to the `0x0` address

**Suggested actions:**

* We suggest reaching out to us, so we can help you investigate the issue

### `{ index: 180, error: 1, message: None }`

**Error name:** ContractNotFound

**Error explanation:** This means that maintenance actions are being preformed on an address that is not a smart contract

**Common causes:**

* Usually happens when trying to maintain a non-existent or already deleted smart contract

**Suggested actions:**

* We suggest reviewing the address you are trying to maintain

### `{ index: 180, error: 2, message: None }`

**Error name:** NoPermission

**Error explanation:** This means that the account is not allowed to interact with the smart contract

**Common causes:**

* This means that the account is not allowed to interact with the smart contract

**Suggested actions:**

* If the user wants to interact with the smart contract before it is published, they can turn on the development mode
* It the smart contract maintainer wishes to enable non-developer users to interact with the smart contract, they can publish the smart contract

### `{ index: 180, error: 3, message: None }`

**Error name:** ContractDevelopmentNotEnabled

**Error explanation:** This means that the account doesn't have the development mode enabled

**Common causes:**

* Usually happens when account doesn't have development mode enabled and the user tries to disable the development mode

**Suggested actions:**

* If you wish for the development mode to be disabled, you don't need to do anything
* If you wish to enable the development mode, you can enable it by following the documentation

### `{ index: 180, error: 4, message: None }`

**Error name:** ContractDevelopmentAlreadyEnabled

**Error explanation:** This means that the account already has the development mode enabled

**Common causes:**

* Usually happens when account has development mode enabled and the user tries to enable the development mode

**Suggested actions:**

* If you wish for the development mode to be enabled, you don't need to do anything
* If you wish to disable the development mode, you can enable it by following the documentation

### `{ index: 180, error: 5, message: None }`

**Error name:** ContractAlreadyPublished

**Error explanation:** This means that the smart contract is already published

**Common causes:**

* Usually happens when trying to publish an already published smart contract

**Suggested actions:**

* If you wish for the smart contract to be published, you don't need to do anything
* If you wish that the smart contract wouldn't be reachable by users that don't have development mode enabled, you can delete it and redeploy it

### `{ index: 180, error: 6, message: None })&#x20`

**Error name:** ContractExceedsMaxCodeSize

**Error explanation:** This means that the smart contract file size is too big

**Common causes:**

* Usually happens when trying to deploy a smart contract that is too big

**Suggested actions:**

* We suggest refactoring your smart contract, so that the file size is decreased

### `{ index: 180, error: 7, message: None }`

**Error name:** ContractAlreadyExisted

**Error explanation:** This means that the same address has already been used and can't be used again

**Common causes:**

* Usually happens when the substrate account, to which the EVM+ account has been bound, has been reaped, which resulted in the EVM+ account nonce being reset. This in turn can cause the EVM+ to try and create a smart contract at an address that has already been used

**Suggested actions:**

* We suggest using another EVM+ account

{% hint style="warning" %}
**NOTE: This behaviour should be made obsolete. If you encounter this error, please reach out to us, so we can investigate.**
{% endhint %}

### `{ index: 180, error: 8, message: None }`

**Error name:** OutOfStorage

**Error explanation:** This means that the storage usage of the transaction is greater than the storage limit

**Common causes:**

* Usually happens when transaction changes a number of states and the storage limit value is too low

**Suggested actions:**

* We suggest increasing the storage limit value of the transaction
* If the storage limit exceeds the maximum storage limit we suggest reviewing the call initiated by the transaction and adapting it to change less states

### `{ index: 180, error: 9, message: None }`

**Error name:** ChargeFeeFailed

**Error explanation:** This means that the smart contract, that is trying to use Schedule predeployed smart contract, doesn't have enough funds to pay for the Schedule transaction fees

**Common causes:**

* Usually happens when either the smart contract has too low of a balance or the scheduled call is too complex

**Suggested actions:**

* We suggest additionally funding the smart contract or reviewing the scheduled call in order to make it more efficient

### `{ index: 180, error: 10, message: None }`

**Error name:** CannotKillContract

**Error explanation:** This means that killing the smart contract has failed

**Common causes:**

* Usually happens when trying to kill a non-existent function

**Suggested actions:**

* We suggest reviewing the address you are using to kill the smart contract and checking for typos or missed characters

### `{ index: 180, error: 11, message: None }`

**Error name:** ReserveStorageFailed

**Error explanation:** This means that the account doesn't have enough funds to put data into storage

**Common causes:**

* Usually happens when trying to change a lot of states in a single transaction

**Suggested actions:**

* We suggest reviewing the call and reducing the number of states that are changed within it
* If the number of states changed by the call can't be reduced, we suggest adding funds to the account

### `{ index: 180, error: 12, message: None }`

**Error name:** UnreserveStorageFailed

**Error explanation:** This means that releasing the storage has failed

**Common causes:**

* Usually happens when the storage rent is increased after the storage has been rented, but not before it has been released

**Suggested actions:**

* We suggest reaching out to the team as this shouldn't happen under normal circumstances

### `{ index: 180, error: 13, message: None }`

**Error name:** ChargeStorageFailed

**Error explanation:** This means that charging the storage rent has failed

**Common causes:**

* None

**Suggested actions:**

* We suggest reaching out to the team if you encounter this error

### `{ index: 180, error: 14, message: None }`

**Error name:** InvalidDecimals

**Error explanation:** This means that the value provided was too low

**Common causes:**

* Usually happens when trying to convert wei to ACA or KAR. As ACA and KAR have 12 decimal spaces and the EVM+ expects the native currency to have 18, this error might occur during the conversion.

**Suggested actions:**

* We suggest only using the values greater than `1_000_000` when referring to a native currency in wei

## Named Errors

### `Error: 1010: Invalid transaction: Transaction is outdated`

**Error name:** Transaction is outdated

**Error explanation:** This means that the transaction's `validUntil` value is too low or that there is already a transaction with the same nonce in the chain.

**Common causes:**

* `validUntil` value of the transaction is lower than current block number
* Transaction nonce is the same as one of the preexisting transactions had

**Suggested actions:**

* Verify that the transaction has a valid `validUntil` value and update it if the block number of the chain is higher
* Reset the account nonce, to make sure it corresponds to the one associated with the account nonce on chain

### `Error: 1012: Invalid transaction: Transaction is temporary banned`

**Error name:** Transaction is temporary banned

**Error explanation:** This means that an identic transaction to this one has already failed, so mining this transaction won't be attempted. This behaviour is narrated by Substrate and has to be supported.

**Common causes:**

* Transaction identic to this one has recently failed

**Suggested actions:**

* Review logs and identify the original error to address it
* If the previous error can't be found, wait for 15 minutes and re-attempt sending the transaction. The original error message should be returned

## Other Errors

### `invalid ETH gasLimit/gasPrice combination provided`

We don't support inputting random gasLimit/gasPrice combination. Please read through the [gas params](/network/gas-parameters) section, which has detailed explanation of how to provide valid gas params.

### `Transaction hash mismatch from Provider.sendTransaction`

**Common causes:**

This is usually cause by using `ethers.JsonRpcProvider` as provider when sending a transaction. `JsonRpcProvider` expects a pre-calculated ETH style tx hash. However, the algorithm we use to derive the result tx hash is different than traditional EVM world, causing the mismatch.

**Suggested actions:**

Use [AcalaJsonRpcProvider](https://github.com/AcalaNetwork/bodhi.js/tree/master/packages/eth-providers#acala-networketh-providers) as a drop-in replacement.

For example:

```ts
import { AcalaJsonRpcProvider } from "@acala-network/eth-providers";

// https://evmdocs.acala.network/network/network-configuration#karura-mainnet
const KARURA_ETH_RPC= 'https://eth-rpc-karura.aca-api.network';
const provider = new AcalaJsonRpcProvider(KARURA_ETH_RPC);

// send transaction
const wallet = new Wallet(PRIVATE_KEY, provider);
const contractInstance = new Contract(CONTRACT_ADDR, CONTRACT_ABI, wallet);
await contractInstance.someMethod();
```

Note that `JsonRpcProvider` should still work in most cases, such as getting account balance, etc... The only senario that this error occur is when sending a transaction with `Provider.sendTransaction`.

Also, such error only occurs with `ethers.JsonRpcProvider`, and using other providers (such as metamask's provider) should be fine.

### `Account cannot exist with the funds that would be given`

**Common causes:**

Each address needs a minimum balance of 0.1 ACA/KAR, this is called [Existential Deposit](https://wiki.acala.network/get-started/acala-network/acala-account#existential-deposit). Sending a transaction with value lower than ED to a **new address** will result in this error.

**Suggested actions:**

* when sending native token to a new EOA, make sure the value is greater than ED, which is 0.1 ACA/KAR.
* if target address is a contract that handles payments, we can send 0.1 ACA/KAR to the contract right after the it is deployed, so this error won't occur for any following transactions.


# ETHDenver

Acala at ETHDenver 2022 #BUIDLWeek

#### Join the EVM+ Workshop in-person & online during ETHDenver’s #BUIDLWeek <a href="#id-0d7b" id="id-0d7b"></a>

\
Project Submission: <https://share.hsforms.com/1woaQxNlJSA-EYJKe2cYJZA4h8qc>\
\
Tutorial: <https://aca.la/BUIDLWeek>\
\
Tutorial Video: <https://youtu.be/GI6OBZvRPGc>\
\
Link Metamask to Mandala: <https://acala-evm.netlify.app/><br>

**Beyond EVM: Building Sustainable dApps & L1 Networks With Acala**\
**Date/Time**: Tuesday, Feb 15, 2022, 3:00pm — 5:00pm MST (10pm UTC)\
**Location**: 1134 Broadway (2nd Floor), Denver CO, 80203\
\
In this workshop, you'll utilize familiar toolsets to deploy leading Ethereum DEX contracts while leveraging programmable DOT assets and cost-effective calls to Acala's native DEX, Acala Swap. Meet the team, pick up some Acala swag, and try for bounty rewards with our hands-on tutorial:\
\
**Bounty 1**

* **Objective**: Deploy a DApp on Polkadot using Acala EVM+
* **Reward:** $1000

**Bounty 2**

* **Objective**: Deploy a DApp on Acala EVM+ that integrates with Acala's decentralized stablecoin, aUSD
* **Reward:** $4000

**Judging Criteria**

* **Strength of aUSD stablecoin use case (25%)** — Includes how much utility and demand the DApp creates for aUSD.
* **Originality, Creativity, and Innovation (25%)** — Includes how new and novel the submission is versus existing technologies.
* **Technical Difficulty (25%)** — Includes the level of skill or knowledge required to build the DApp.
* **User Experience (25%)** — Includes how intuitive and understandable the submission is for potential users.

\ <br>


# Request support

Instructions how to request support for your project in a format that will allow for the most efficient support.

In order for us to be able to lend a hand when you hit a snag, we want to share a simple checklist of what to include in your support request.

## Brief description

A brief description of your issue that illustrates what issues you have encountered and how it impacts you. For example:

We have tried deploying a smart contract using Truffle framework, but the transaction has failed with `Error: 1010: Invalid Transaction: Transaction is outdated` error.

## Source

Providing us with the source code will allow for an easier debugging by our engineers. Being able to look at the code and manipulate it in order to provide a solution will eliminate the guesswork.

Source can be a link to a branch in your repository that encountered the issue or a mock of it (in case you don't feel comfortable sharing your source code with us). If you are sharing a mock branch it is important that you preserve the dependencies you are using and the configuration as well as the flow of the script that encounters the issue (you may change the contract and variable names and values, but keep the statements as close to the original as possible).

## Reproduction instructions

Step by step instructions on how to reproduce the issue. Be as detailed as possible. Reproduction instructions should start with cloning the source and end with reproducing the issue. For example:

1. `git clone REPOSITORY`
2. `yarn`
3. `yarn build`
4. `yarn reproduce-issue`

## Additional details

Details about your environment that could be specific to you are important. Make sure you have bound your Substrate and EVM accounts and enabled the development mode. Do you have sufficient balance? Hash of the transaction that failed (not screenshot, as the hash can be copy-pasted) can greatly increase the chances of resolving your issue.

## How to request support?

Remember to gather all of the information above and have it ready.

We encourage you to first post your question to [Substrate stack exchange](https://substrate.stackexchange.com/) or to check it out whether or not your question has already been answered. Please use `acala`, `karura` or `mandala` tags (depending on the network you are using) and the `evm+` tag, to make sure one of our engineers sees your question.

If you are unable to get sufficient support, reach out to us in one of our many channels of communication and we will assist you.


# Feedback or suggestions?

If you have any feedback or suggestions about the EVM+ documentations, feel free to open an issue or PR [here](https://github.com/AcalaNetwork/acala-evm-dev-docs/issues).


