Untitled notebook
Ganache Smart Contract Deployment and Testing
Setup
We’ll use the project’s existing blockchain setup:
Mix.install([
{:ethers, "~> 0.5"},
{:ex_abi, "~> 0.6"},
{:jason, "~> 1.4"}
])
# Configure Ethers for Ganache
:ok = Application.put_env(:ethers, :rpc_client,
url: "http://localhost:8545",
network_id: 1337
)
alias Ethers.{Contract, Provider}
## Configure Web3 Connection
# Your Ganache account details
deployer_address = "0xCF1D964Fc2E8893894457aeB54E59bBC25B973f6"
deployer_private_key = "0xdd597f7b8189603af8e5f1098e31e3ac7347fd75785f196fd9e51edb57a7220b"
# Test account for transfers
test_account = "0xD2caB5cBaC2DdE2EEbac96892245841d8785B59C"
# Test connection
{:ok, provider} = Provider.connect()
{:ok, balance} = Provider.get_balance(provider, deployer_address)
IO.puts("Connected to Ganache!")
IO.puts("Deployer balance: #{balance} wei")
## Simple Token Contract
Here's our simple ERC20-like token contract:
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0;
contract SimpleToken {
string public name;
string public symbol;
uint8 public decimals;
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
event Transfer(address indexed from, address indexed to, uint256 value);
constructor(string memory _name, string memory _symbol) {
name = _name;
symbol = _symbol;
decimals = 18;
totalSupply = 1000000 * 10**uint256(decimals); // 1 million tokens
balanceOf[msg.sender] = totalSupply;
}
function transfer(address to, uint256 value) public returns (bool) {
require(balanceOf[msg.sender] >= value, "Insufficient balance");
balanceOf[msg.sender] -= value;
balanceOf[to] += value;
emit Transfer(msg.sender, to, value);
return true;
}
}
## Compile Contract
To compile the contract, you can use:
1. Remix IDE (https://remix.ethereum.org/) - paste the contract and compile
2. Or local solc compiler: `solc --abi --bin SimpleToken.sol`
Paste the results here:
Contract ABI and Bytecode (paste after compiling)
contract_abi = # Paste ABI here bytecode = # Paste bytecode here
Deploy contract
= Contract.deploy( abi: contract_abi, bin: bytecode, args: [“VEIX Token”, “VEIX”], from: deployer_address )
IO.puts(“Contract deployed at: #{contract_address}”)
## Interact with Contract
Create contract instance
contract = Contract.at(contract_address)
Get token info
= Contract.call(contract, “name”) {:ok, symbol} = Contract.call(contract, “symbol”) {:ok, total_supply} = Contract.call(contract, “totalSupply”)
IO.puts(“”” Token Info: Name: #{name} Symbol: #{symbol} Total Supply: #{total_supply} “””)
Get deployer balance
= Contract.call(contract, “balanceOf”, [deployer_address]) IO.puts(“Deployer balance: #{balance}”)
## Transfer Tokens
Transfer 100 tokens to test account
amount = 100 * Float.pow(10, 18) |> round() {:ok, tx_hash} = Contract.send(contract, “transfer”, [test_account, amount], from: deployer_address)
IO.puts(“”” Transfer executed: From: #{deployer_address} To: #{test_account} Amount: 100 tokens Transaction: #{tx_hash} “””)
Check new balances
= Contract.call(contract, “balanceOf”, [deployer_address]) {:ok, to_balance} = Contract.call(contract, “balanceOf”, [test_account])
IO.puts(“”” New balances: Deployer account: #{from_balance} Test account: #{to_balance} “””)
## Next Steps
1. To use this notebook:
* Start LiveBook (`livebook server`)
* Open this notebook
* Make sure Ganache is running (which it is!)
* Compile the contract (use Remix IDE or solc)
* Paste the ABI and bytecode
* Run each section sequentially
2. Try modifying the contract:
* Add new functions
* Change the token parameters
* Add more ERC20 features
3. Experiment with:
* Different transfer amounts
* Multiple acts
* Error conditions (e.g., insufficient balance)