Better Programming

Advice for programmers.

Follow publication

Deploy EVM-Based dApp on Algorand With Milkomeda A1

Using (mostly) Python

David Duarte
Better Programming
Published in
7 min readOct 23, 2022

In this article, I will show how simple it is to deploy an EVM-based dApp on Algorand-Milkomeda A1, using mostly Python.

Milkomeda is a new protocol that brings EVM capabilities to non-EVM blockchains. At the time of writing, there are L2 solutions for Algorand, through the EVM-based Rollup Algorand-Milkomeda A1, and Cardano, through the EVM-based sidechain Cardano-Milkomeda C1.

The A1 Rollup uses wrapped ALGOs (milkALGOs) as its base currency, which can be easily bridged using the Milkomeda permission-less bridge. Users can wrap their ALGOs and other Algorand native assets (ASAs) onto the A1 Rollup with a few simple steps. This enables them to use their milkALGOs to interact with the EVM-based dApps deployed on the A1 Rollup.

I will assume the user has never even used Algorand and will show all the steps starting from scratch:

Table of ContentsSetup an Algorand Wallet
Get Some Testnet ALGO
Add the Milkomeda Algorand Testnet to Metamask
Create a Dummy EVM Account To Test
Bridge Testnet ALGO to Milkomeda A1
Compile and Deploy to Milkomeda A1 a SimpleStorage Contract Written in Solidity Using Brownie
BONUS: Compile the Same Contract Using Vyper and Deploy Using web3py

STEP 1 — Setup an Algorand Wallet

There are several wallets one can use in Algorand. For an almost complete list, I point readers to the discover > wallets section on the Algorand Developer portal, but in this example, I will use MyAlgo wallet.

MyAlgo is an Algorand web wallet with a non-custodial and secure mechanism. It helps users interact directly with the Algorand blockchain while handling their own private keys by either storing them securely and encrypted in their local browser or by using a Ledger hardware wallet.

To set up a wallet, (i) visit https://wallet.myalgo.com/new-account, (ii) choose a password to protect your wallet, and (iii) click Add a New Account and follow the steps to save your Mnemonic Phrase securely.

You should now have an Algorand address like the following image:

Screenshot of MyAlgo wallet

STEP 2 — Get Some Testnet ALGO

Now on the top right of your MyAlgo wallet, change from MAINNET to TESTNET, and then visit the Algorand Testnet Dispenser (https://testnet.algoexplorer.io/dispenser) and paste your newly created account to get some testnet ALGOs.

You should now be able to see ten testnet ALGOs in your MyAlgo wallet.

STEP 3 — Add the Milkomeda Algorand Testnet to Metamask

In Metamask, go to Settings > Networks > Add Networks and fill in the following information:

Network Name: Milkomeda Algorand Testnet
New RPC URL: https://rpc-devnet-algorand-rollup.a1.milkomeda.com
Chain ID: 200202
Currency Symbol (Optional): milkTALGO
Block Explorer URL (Optional): https://testnet-algorand-rollup.a1.milkomeda.com

STEP 4 — Create a Dummy EVM Account To Test

To test the bridging of wrapped ALGOs to Milkomeda, let’s create a dummy EVM account with a simple Python snippet.

This will generate a private key which you can now use to import the account into Metamask.

IMPORTANT: Please do not use an account generated like this for real funds. The randomness of the proposed process is insufficient to ensure the security of your funds.

STEP 5 — Bridge Testnet ALGO to Milkomeda A1

Go to the Milkomeda A1 bridge page https://algorand-bridge-dev.milkomeda.com/ and follow these steps:

  1. Select “Devnet” in top right select box
  2. On Network Origin, select “Algorand to Milkomeda”
  3. On Token, select “ALGO”
  4. Click “Connect Wallet” Algorand, select MyAlgo Wallet, enter your password, and then select your Algorand account
  5. Click “Connect Wallet” Metamask to connect to your EVM address on A1
  6. Click “Next,” then “Sign and Send”

If all went well, you will see the following screen and should now see your bridged ALGOs in Metamask. Following the link will show the transaction on the A1 Bridge Explorer.

STEP 6 — Compile and Deploy to Milkomeda A1 a SimpleStorage Contract Written in Solidity Using Brownie

Assuming one doesn’t have Brownie installed, create a virtual environment and install Brownie by:

python -m venv venv
source venv/bin/activate
pip install eth-brownie

Initialize a brownie project in a new working directory:

brownie init milkomeda && cd milkomeda

Now let’s create a very simple Solidity contract. In the contracts folder, create a file called Storage.sol, and add the following solidity code:

Run the following command from the root of the created working directory to compile the contract:

brownie compile

To check the available networks that are configured in your brownie installation, run:

brownie networks list

Milkomeda A1 will not be available by default, so we need to add it. To do that, either edit the file ~/.brownie/network-config.yaml and add the following lines:

- name: Milkomeda
networks:
- name: Algorand Testnet
id: milkomeda-algorand-testnet
host: https://rpc-devnet-algorand-rollup.a1.milkomeda.com
chainid: 200202
explorer: https://testnet-algorand-rollup.a1.milkomeda.com

OR use the brownie CLI:

brownie networks add Milkomeda milkomeda-algorand-testnet chainid=200202 explorer=https://testnet-algorand-rollup.a1.milkomeda.com host=https://rpc-devnet-algorand-rollup.a1.milkomeda.com name="Milkomeda Testnet"

If successful, one should now see it in the list, which can be queried with complete details by:

brownie networks list true

We will add the private key to use the created (EVM) account. Create a file called brownie-config.yml in the root directory and add the private key directly.

Or save the private key in a .env file and point to it in the brownie config.

Now, we have everything ready to deploy our Storage smart contract on Milkomeda A1. In the scripts folder, create a file named deploy.py, and add the following code:

From brownie, we are importing Storage to be able to use the compiled contract, accounts so we can add the account by private key and config to be able to access the key/value pairs stored in the brownie-config.yml file.

Then, we can create the signer account and deploy the contract in the main function.

We can now deploy the contract on Milkomeda A1 by running the script from the terminal and indicating the A1 network:

brownie run scripts/deploy.py --network milkomeda-algorand-testnet

The output should be:

The contract has been deployed, and you can check the transaction on the A1 Milkomeda Devnet explorer:

To interact with the smart contract, let’s create a separate file called call.py in the scripts directory and add the following code:

The only new import here is the Contract class to create the contract object by calling the .from_abi method, which takes name, abi, and contract address as inputs. The contract address was copied from the deployment output and hard coded here.

We then call the retrieve method on our contract to read the stored value in the “number” variable. Then we store a new value and read it again. To call this script from the terminal, run the following:

brownie run scripts/call.py --network milkomeda-algorand-testnet

The output should be something like this:

And we are done! We have deployed and interacted with a contract on Milkomeda A1, so in a way, we have used an EVM-based smart contract on Algorand.

I admit this tutorial could be easily adapted to any EVM-compatible chain, so it’s not really Algorand-specific, but it just goes to show how seamless it can be to port an existing EVM dApp to Algorand.

BONUS: Compile the Same Contract Using Vyper and Deploy Using web3py

We can now look at an example of deploying the same smart contract but written in Vyper, using only web3py.

First, we will need the abi and bytecode of the contract:

Now let’s connect to the Milkomeda A1 through the RPC URL.

Set up the account from the generated private key (assuming it’s in the .env file)

Create the contract object from the abi and bytecode and call the constructor function.

Until this point, the code would produce the following output:

and we can look up the transaction or the deployed contract on the A1 devnet explorer:

Now to interact with the contract, we can call the retrieve function to get the stored value, change the value with the “store” function and then retrieve the value again.

and the output…

Thanks for reading!

Stay tuned for more.

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

No responses yet

Write a response