EVM Smart Contract
Develop and deploy your first Solidity smart contract on Mandala EVM, bridging Ethereum development with the Polkadot ecosystem.
Overview
Mandala Testnet provides full Ethereum Virtual Machine (EVM) compatibility, allowing you to deploy existing Ethereum smart contracts and use familiar tools like Remix, Hardhat, and MetaMask.
EVM Environment Setup
Network Configuration
Mandala EVM Details:
- Network Name: Mandala Testnet EVM
- RPC URL:
https://rpc1.paseo.mandalachain.io
- Chain ID: 4818
- Currency: KPGT
MetaMask Configuration
Add Mandala to MetaMask:
-
Open MetaMask → Click network dropdown
-
Select "Add Network" → "Add a custom network"
-
Enter network details:
Field Value Network Name Metamask Testnet EVM New RPC URL https://rpc1.paseo.mandalachain.io
Chain ID 4818 Currency Symbol KPGT -
Click "Save" and switch to Mandala network
Development Environment
Tool Options
Choose your preferred development environment:
Option 1: Remix IDE (Recommended for beginners)
- Browser-based, no installation required
- Built-in compiler and debugger
- Direct deployment to networks
Remix IDE Setup
Accessing Remix:
- Visit: https://remix.ethereum.org
- Accept privacy policy and close welcome screen
- Open file in contracts folder:
Storage.sol
Building Your First Contract
Storage Contract
Create a basic contract that stores and retrieves a number:
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.8.2 <0.9.0;
/**
* @title Storage
* @dev Store & retrieve value in a variable
* @custom:dev-run-script ./scripts/deploy_with_ethers.ts
*/
contract Storage {
uint256 number;
/**
* @dev Store value in variable
* @param num value to store
*/
function store(uint256 num) public {
number = num;
}
/**
* @dev Return value
* @return value of 'number'
*/
function retrieve() public view returns (uint256){
return number;
}
}
Contract Features
Key Components:
State Variables:
uint256 number; // Public storage variable for storing a number
Functions:
store(uint256 num)
- Store a value in the number variableretrieve()
- Read and return the stored number value
Function Details:
Store Function:
function store(uint256 num) public {
number = num;
}
- Visibility: Public (can be called by anyone)
- Purpose: Updates the stored number with a new value
- Parameter:
num
- the new value to store
Retrieve Function:
function retrieve() public view returns (uint256){
return number;
}
- Visibility: Public view (read-only, doesn't modify state)
- Purpose: Returns the currently stored number
- Returns: The value stored in the
number
variable
Compiling the Contract
Using Remix
-
Select Solidity Compiler tab (left sidebar)
-
Choose compiler version: 0.8.19 or later
-
Enable optimization (optional)
-
Click "Compile Storage.sol"
Compilation artifacts:
- Bytecode: Contract's compiled code
- ABI: Application Binary Interface
- Metadata: Contract information
Deploying to Mandala
Remix Deployment
-
Go to "Deploy & Run Transactions" tab
-
Set environment to "Injected Provider - MetaMask"
-
Verify network shows "Mandala Testnet EVM (4818)"
-
Select Storage contract
-
Click "Deploy"
MetaMask Transaction
-
MetaMask popup will show transaction details
-
Review gas fee and contract creation
-
Click "Confirm" to deploy
-
Wait for confirmation (usually 12-24 seconds)
Deployment Success
After successful deployment:
-
Contract address is generated (0x...)
-
Contract appears in Remix deployed contracts
-
Transaction hash is provided
-
Gas used is displayed
-
On metamask Activity section will show the Contract deployment as well
Interacting with Your Contract
Using the Deployed Contract
Once deployed, you can interact with your Storage contract:
Storing a Value:
- In the deployed contracts section, find your Storage contract
- Expand the contract to see available functions
- Enter a number in the
store
function input field - Click the
store
button - Confirm the transaction in MetaMask
Retrieving the Value:
- Click the
retrieve
button (no input needed) - The stored number will be displayed immediately
- This is a view function, so no gas is required
Security Best Practices
Common Vulnerabilities
Reentrancy protection:
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
contract SecureContract is ReentrancyGuard {
function withdraw() public nonReentrant {
// Safe withdrawal logic
}
}
Integer overflow protection:
// Use SafeMath or Solidity ^0.8.0 built-in checks
function safeAdd(uint256 a, uint256 b) public pure returns (uint256) {
return a + b; // Automatically checks for overflow
}
Access control:
import "@openzeppelin/contracts/access/Ownable.sol";
contract ControlledContract is Ownable {
function sensitiveFunction() public onlyOwner {
// Only owner can call
}
}
Additional Resources:
Congratulations! You've successfully deployed your first EVM smart contract on Mandala Testnet, demonstrating the power of Polkadot's multi-virtual machine architecture!