# Završni ispit - ISBIT
**Autori**: Bruno Grbac, Lorenzo Šamanić
**Datum**: 30. siječanj 2023.
**Predmet**: Informacijska sigurnost i blockchain tehnologije
**Ak. god**: 2022./2023.
**GitHub link**: https://github.com/BrunoG1121/ZavrsniIsbit
# Sadržaj
[ToC]
# Uvod
Napravljen je projektni zadatak za završni rad koristeći web3 modul za python te također kao dodatni zadatak koristeći web3js biblioteku. Stvoren je token "BrunoLorenzoToken" odnosno BLT u količini od 1 000 000 tokena. Kreirane su funkcije za mint i burn kao i prijenos s jedne adrese na drugu te provjera stanja prije i nakon transkacije.
# Pametni ugovor
Korišten je kompajler solidity 0.6.0 te su prvo definirane varijable owner, name, symbol, totalSupply i balanceOf
```
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
contract SimpleStorage {
address public owner;
string public name;
string public symbol;
uint256 public totalSupply;
mapping (address => uint256) public balanceOf;
```
Definiran je konstruktor kojemu šaljemo adresu vlasnika, ime i simbol tokena te totalnu količinu tokena. Potom dodjeljujemo varijablama dobivene vrijednosti.
```
constructor(string memory _name, string memory _symbol, uint256 _totalSupply) public {
owner = msg.sender;
name = _name;
symbol = _symbol;
totalSupply = _totalSupply;
balanceOf[msg.sender] = totalSupply;
}
```
#### Funkcija Transfer
Funkcija očekuje dobiti adresu na koju će se slati s vlasnikovog računa te samu vrijednost koja bi se trebala prebaciti. Ukoliko na računu vlasnika nema dovoljno tokena ispisuje se "Not enough balance".
```
function transfer(address _to, uint256 _value) public {
require(balanceOf[msg.sender] >= _value, "Not enough balance");
balanceOf[msg.sender] -= _value;
balanceOf[_to] += _value;
}
```
#### Funkcija checkBalanceOf
Funkcija očekuje dobiti adresu na kojoj će izvršiti provjeru te ispisati koliko se na adresi nalazi tokena.
```
function checkBalanceOf(address _owner) public view returns (uint256) {
return balanceOf[_owner];
}
```
#### Funkcija mint
Funkcija mint je funkcija koja kreira zadanu vrijednost tokena te ih pridodaje u dosadašnju totalnu količinu tokena koji postoje. Navedenu funkciju može koristiti samo vlasnik tokena.
```
function mint(uint256 _value) public {
require(msg.sender == owner, "Only owner can mint");
totalSupply += _value;
balanceOf[msg.sender] += _value;
}
```
#### Funkcija burn
Funkcija burn je funkcija koja briše zadanu vrijednost tokena te ih oduzima od dosadašnje totalne količine tokena koji postoje. Navedenu funkciju može koristiti samo vlasnik tokena te ne može izbrisati više tokena nego ih ima na računu vlasnika.
```
function burn(uint256 _value) public {
require(msg.sender == owner, "Only owner can burn");
require(balanceOf[msg.sender] >= _value, "Not enough balance");
totalSupply -= _value;
balanceOf[msg.sender] -= _value;
}
}
```
# Ganache testna mreža
Prateći upute na GitHubu (https://github.com/trufflesuite/ganache) pokrenuta je ganache testna mreža u terminalu.
```
ganache v7.7.3 (@ganache/cli: 0.8.2, @ganache/core: 0.8.2)
Starting RPC server
Available Accounts
==================
(0) 0xb918cA8Ce3d8B7055985Ccbe9e8308d9dffBb510 (1000 ETH)
(1) 0xD18a1B693d585fBE721e1ADBa9351f75C5711F03 (1000 ETH)
(2) 0xE3bC00cfd2060298438a3dA868063DBd52E96054 (1000 ETH)
(3) 0x1Ee5198B49FcF72eC7b164411F2Fda11068450cc (1000 ETH)
(4) 0xbfb7023B69F55C9b33de55740743f8631Ff6d454 (1000 ETH)
(5) 0x54B5a6d4dc9E55fC01b153D445906b3d716c5BB2 (1000 ETH)
(6) 0x35baeeaA1beec6609182a4eBFF6c632Ff6B527b7 (1000 ETH)
(7) 0xdb7c146EdB5b30D57D2acd7615eD4232cb077861 (1000 ETH)
(8) 0x1b48AaC0a47F852974c856eeE34ef2e5c996456A (1000 ETH)
(9) 0x24e2e5b0048ff912B48983d428c9B3aF78476098 (1000 ETH)
Private Keys
==================
(0) 0x992d3738d6348fcafe885e012974011b711ffce04c0e75a6744df7c9db8c069e
(1) 0xf837b4b08530ac4918c86a2dd9cf13785bf7a9b601d8b537c9188655ac904751
(2) 0x2205aae128eec61217c86ed5fb1fd38a51375b6fa81c163e5d7fb4f93ebe0d08
(3) 0xe26df98b35ca369715a4459bf02ef094b11c102774783a49bbf8d27086f86385
(4) 0x53aa64c002c515dc690467bf23f43bf2cc55f58522af31fd94a50dd2fd767aa0
(5) 0x925715e828ff7d48ed143ec94ddd64acc999e4d82b756a8ad6f5366709555921
(6) 0xd3f3691a59e54f0623d73aee04ad9ef8e45fb6b5585704b047b3a195a8388a80
(7) 0xc141df10408deb365a834530b430bd6ba3e62abbf49ba0e6c111639c8e767d9e
(8) 0xe329a046799ceb9c4908d4c0fc7bc5ed83b036684d925701c99f3a3e2ed68d2f
(9) 0xe8fde2401dcd98768621d78bf3fd62cecb52893c41728605f4d747ee4a2e6608
HD Wallet
==================
Mnemonic: excuse section meat assault elite drop cousin van circle lock sing infant
Base HD Path: m/44'/60'/0'/0/{account_index}
Default Gas Price
==================
2000000000
BlockGas Limit
==================
30000000
Call Gas Limit
==================
50000000
Chain Id
==================
1337
```
# web3 python
Inicijalizacija odnosno dodavanje potrebnih biblioteka.
```
from solcx import compile_standard, install_solc
# install_solc("0.6.0")
import json
from web3 import Web3
```
Čitanje i kompaliranje pametnog ugovora SimpleStorage.
```
# Read the contents of the SimpleStorage.sol contract file
with open("./SimpleStorage.sol", "r") as file:
simple_storage_file = file.read()
# Compile the Solidity contract using the solcx package
compiled_sol = compile_standard(
{
"language": "Solidity",
"sources": {"SimpleStorage.sol": {"content": simple_storage_file}},
"settings": {
"outputSelection": {
"*": {"*": ["abi", "metadata", "evm.bytecode", "evm.sourceMap"]}
}
},
},
solc_version="0.6.0",
)
```
Spremanje bytecode-a i ABI-a od pametnog ugovora te definiranje određenih parametara poput adrese vlasnika i njenog privatnog ključa.
```
# Save the compiled contract's bytecode and ABI to a local file
with open("compiled_code.json", "w") as file:
json.dump(compiled_sol, file)
# Extract the bytecode and ABI from the compiled contract
# bytecode
bytecode = compiled_sol["contracts"]["SimpleStorage.sol"]["SimpleStorage"]["evm"][
"bytecode"
]["object"]
# abi
abi = compiled_sol["contracts"]["SimpleStorage.sol"]["SimpleStorage"]["abi"]
w3 = Web3(Web3.HTTPProvider("http://127.0.0.1:8545"))
chain_id = 1337
my_addres = "0x0056941d2d8e96Ff0c586c7AF2f8becc2f7c212a"
private_key = "0x5def8119611261a8358c475f0d84c2f5c364954805cff7de8c95d766c08e83bd"
```
Kreiranje ugovora u pythonu te dobivanje nonce-a.
```
# Create the contract in python
SimpleStorage = w3.eth.contract(abi=abi, bytecode=bytecode)
# Get the nonce
nonce = w3.eth.getTransactionCount(my_addres)
```
Definiranje imena, simbola i količine tokena koji će se generirati. Kreirali smo token BrunoLorenzoToken sa simbolom BLT te početnom količinom od 1 000 000 tokena.
```
# Build a transaction
name = "BrunoLorenzoToken"
symbol = "BLT"
total_supply = 1000000
transaction = SimpleStorage.constructor(name, symbol, total_supply).buildTransaction(
{"chainId": chain_id, "from": my_addres, "nonce": nonce}
)
```
Inicijaliziranje tokena.
```
# Sign a transaction
signed_txn = w3.eth.account.sign_transaction(transaction, private_key=private_key)
# Send the signed transaction
tx_hash = w3.eth.send_raw_transaction(signed_txn.rawTransaction)
tx_receipt = w3.eth.wait_for_transaction_receipt(tx_hash)
contract_address = tx_receipt['contractAddress']
SimpleStorage2 = w3.eth.contract(address = contract_address, abi=abi)
```
Daljnje korišteni parametri. Količina koliko će se mintati i burnati, koja je druga adresa te broj tokena koje ćemo slati.
```
###---Parametars----
mint_amount = 10
burn_amount = 500
Druga_adresa ="0x48B19a1EEA50Ee5D0bd782bd3CaC0617822E3679"
BrojPoslanihTokena = 500
###----------------
```
Ispis totalnog broja tokena te broj tokena na vlasnikovom i drugom računu.
```
# Pregled pocetnog stanja
print("----Pregled pocetnog stanja----")
print("Initial total supply:", SimpleStorage2.functions.totalSupply().call())
balance2 = SimpleStorage2.functions.checkBalanceOf(my_addres).call()
print("Stanje našeg računa(owner):", balance2)
balance = SimpleStorage2.functions.checkBalanceOf(Druga_adresa).call()
print("Stanje drugog računa:", balance)
print("----------------------------")
```
Mintanje i burnanje tokena.
```
#Mintanje novih tokena
SimpleStorage2.functions.mint(mint_amount).transact({'from': my_addres})
print("Total supply nakon mintanja:", SimpleStorage2.functions.totalSupply().call())
# Burnanje tokena
SimpleStorage2.functions.burn(burn_amount).transact({'from': my_addres})
print("Total supply nakon burnanja:", SimpleStorage2.functions.totalSupply().call())
```
Slanje s vlasnikovog računa na drugi račun koji je definiran u parametrima.
```
#Slanje s našeg računa na drugi
print("---Slanje tokena s jednog računa na drugi---")
balance2 = SimpleStorage2.functions.checkBalanceOf(my_addres).call()
print("Stanje našeg računa:", balance2)
balance = SimpleStorage2.functions.checkBalanceOf(Druga_adresa).call()
print("Stanje drugog računa:", balance)
SimpleStorage2.functions.transfer(Druga_adresa,BrojPoslanihTokena).transact({'from': my_addres})
print("Transfered")
balance2 = SimpleStorage2.functions.checkBalanceOf(my_addres).call()
print("Stanje našeg računa:", balance2)
balance = SimpleStorage2.functions.checkBalanceOf(Druga_adresa).call()
print("Stanje drugog računa:", balance)
print("------------------------------------------")
balance = w3.eth.getBalance(my_addres)
```
Ispis vlasnikovog stanja u etheriumu nakon svih transakcija kako bi vidjeli koliko je ETH-a potrošeno na gas fee.
```
# Convert the balance from wei to ether
balance_ether = w3.fromWei(balance, 'ether')
# Print the balance in ether
print("Stanje ETH nakon odrađenih transakcija", my_addres, "je", balance_ether, "ether")
```
# Dodatni zadatak - web3js
## Sučelje:

## Funkcije u index.js-u
#### Funkcija SetupInitialContract
Funkcija za kreiranje tokena gdje upisujemo naziv, simbol i količinu tokena kojeg želimo kreirati.
```
async function SetupInitialContract()
{
const myAddress = OwnerAddress;
const constructorParams = [TokenN, TokenT, TokenS];
await SimpleStorage.deploy({
data: bytecode,
arguments: constructorParams,
})
.send({
from: myAddress,
gas: "1000000",
gasPrice: "1000000000",
})
.then((newContractInstance) => {
ContractInstance = newContractInstance
console.log(
`Contract deployed at address: ${newContractInstance.options.address}`
);
});
}
async function SolFunctions(){
await SetupInitialContract()
}
```
#### Funkcija MintFunction
Funkcija mintanja 100 tokena.
```
async function MintFunction(){
await ContractInstance.methods
.mint(100)
.send({
from: OwnerAddress,
gas: "1000000",
gasPrice: "1000000000",
})
.then(() => {
console.log("Mint transaction successful");
});
await ContractInstance.methods.totalSupply().call().then(function(result){TokenS= result})
}
```
#### Funkcija BurnFunction
Funkcija burnanja 100 tokena.
```
async function BurnFunction(){
await ContractInstance.methods
.burn(100)
.send({
from: OwnerAddress,
gas: "1000000",
gasPrice: "1000000000",
})
.then(() => {
console.log("Burn transaction successful");
});
await ContractInstance.methods.totalSupply().call().then(function(result){TokenS= result})
}
```
#### Funkcija SendFunction
Funkcija slanja u kojoj odabiremo adresu na koju se šalje te količinu tokena koju želimo poslati.
```
async function SendFunction(){
await ContractInstance.methods
.transfer(SecAddress,SendAmount)
.send({
from: OwnerAddress,
gas: "1000000",
gasPrice: "1000000000",
})
.then(() => {
console.log("Transfer succesful");
});
await ContractInstance.methods.totalSupply().call().then(function(result){TokenS= result})
}
```
#### Funkcija CheckFunction
Funkcija provjere gdje odabiremo adresu na kojoj želimo provjeriti broj pohranjenih tokena.
```
async function CheckFunction(){
await ContractInstance.methods.checkBalanceOf(AddressToCheck).call().then(function(result){BalanceOfAcc = result});
await ContractInstance.methods.totalSupply().call().then(function(result){TokenS= result})
}
```