Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions ASSIGNMENT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Client Contract Assignment

## Overview
This is the Client contract assignment (as-w3-d3). The Client contract provides functionality for [contract purpose].

## Setup
1. Install dependencies: `npm install`
2. Configure hardhat: See `hardhat.config.ts`
3. Run tests: `npm test`

## Contract Details
- **Location**: `Assignment/solidity-assignment7/contracts/client/`
- **Language**: Solidity

## Testing
```bash
npm test
```

## Deployment
```bash
npx hardhat run scripts/deploy.ts
```
13 changes: 13 additions & 0 deletions Assignment/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Blockchain Assignments

This repository contains a collection of blockchain-related assignments.

## Assignments

- [Assignment 1: Blockchain Utilities](assignment1/README.md) - Gas fee estimation and Merkle root calculation.
- [Assignment 2: Block Implementation](assignment2/README.md) - Implementation of blockchain blocks.
- [Assignment 3](assignment3/README.md) - Advanced topics in blockchain blocks.
- [Assignment 4: JSON-RPC Methods](assignment4/README.md) - Exploration of JSON-RPC methods.
- [Assignment 5: Consensus Clients](assignment5/README.md) - Key concepts on consensus clients.

Each assignment folder contains the relevant code and documentation.
54 changes: 54 additions & 0 deletions Assignment/assignment1/GasEstimation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@


// Convert ETH to GWEI (1 ETH = 1,000,000,000 GWEI)
function ethToGwei(eth) {
return eth * 1e9;
}

function calculateGas() {
const gasUsed = Number(document.getElementById("gasUsed").value);
let baseFee = Number(document.getElementById("baseFee").value);
let priorityFee = Number(document.getElementById("priorityFee").value);
let maxFee = Number(document.getElementById("maxFee").value);

if (baseFee < 1 && baseFee > 0) baseFee = ethToGwei(baseFee);
if (priorityFee < 1 && priorityFee > 0) priorityFee = ethToGwei(priorityFee);
if (maxFee < 1 && maxFee > 0) maxFee = ethToGwei(maxFee);

const result = estimateGasFee(
gasUsed,
baseFee,
priorityFee,
maxFee
);

alert(
"Effective Gas Price: " +
result.effectiveGasPriceGwei +
" Gwei\n" +
"Total Gas Fee: " +
result.totalGasFeeEth +
" ETH"
);
}

function estimateGasFee(
gasUsed,
baseFeeGwei,
priorityFeeGwei,
maxFeeGwei
) {
const effectiveGasPriceGwei = Math.min(
baseFeeGwei + priorityFeeGwei,
maxFeeGwei
);

const totalFeeGwei = gasUsed * effectiveGasPriceGwei;
const totalGasFeeEth = totalFeeGwei / 1000000000;

return {
effectiveGasPriceGwei,
totalGasFeeEth
};
}

34 changes: 34 additions & 0 deletions Assignment/assignment1/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@

# Assignment 1: Blockchain Utilities

This project provides a set of utilities for blockchain development, including Ethereum gas fee estimation and Merkle root calculation using various hashing algorithms.

## Features

- **Gas Fee Estimation**: Estimate Ethereum transaction gas fees in real-time based on network conditions.
- **Merkle Root Calculation**: Compute Merkle roots using SHA-256 or Keccak-256 hashing for transaction verification.

## Files

- `index.html`: Web interface for gas fee estimation.
- `GasEstimation.js`: JavaScript functions for gas fee calculations.
- `hash.js`: Implementation of Merkle root computation.
- `style.css`: Styling for the web interface.

## Installation

1. Clone the repository.
2. Install dependencies: `npm install`

## Usage

- Open `index.html` in a browser to use the gas fee estimator.
- Run `node hash.js` to see Merkle root examples.

## Theory

For the theory part related to question 1, see: https://hackmd.io/@luhrhenz/SJK0urCSbe




73 changes: 73 additions & 0 deletions Assignment/assignment1/hash.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// libraries
const crypto = require("crypto"); // For SHA-256
const { keccak256, toUtf8Bytes, getBytes } = require("ethers"); // For Keccak-256

function sha256(data) {
return crypto.createHash("sha256").update(data).digest("hex");
}

function keccak256HashBytes(data) {
// data can be a string or Uint8Array
const bytes = typeof data === "string" ? toUtf8Bytes(data) : data;
return keccak256(bytes); // returns 0x... hex string
}

// --- Generic Merkle Root function ---
function merkleRoot(transactions, algo = "sha256") {
if (!transactions || transactions.length === 0) return null;

// hashing of transactions
let hashes = transactions.map(tx => {
if (algo === "sha256") return sha256(tx);
else if (algo === "keccak256") return keccak256HashBytes(tx);
else throw new Error("Unknown algorithm: " + algo);
});

// iteratively compute parent hashes
while (hashes.length > 1) {
let temp = [];
for (let i = 0; i < hashes.length; i += 2) {
const left = hashes[i];
const right = i + 1 < hashes.length ? hashes[i + 1] : hashes[i]; // duplicate last if odd

if (algo === "sha256") {
temp.push(sha256(left + right)); // SHA-256: hex string concat
} else {
// Keccak-256: convert hex strings to bytes, then concatenate
const leftBytes = getBytes(left.startsWith("0x") ? left : "0x" + left);
const rightBytes = getBytes(right.startsWith("0x") ? right : "0x" + right);
const combined = new Uint8Array([...leftBytes, ...rightBytes]);
temp.push(keccak256(combined));
}
}
hashes = temp;
}

return hashes[0]; // final root
}

// demo transactions
const transactions = [
"Alice pays Bob 1 ETH",
"Carol pays Dave 2 ETH",
"Eve pays Frank 0.5 ETH",
"George pays Hannah 0.1 ETH"
];

console.log("=== Transaction Hashes ===");
console.log("\nSHA-256 Transaction Hashes:");
transactions.forEach((tx, index) => {
console.log(` [${index}] ${sha256(tx)}`);
});

console.log("\nKeccak-256 Transaction Hashes:");
transactions.forEach((tx, index) => {
console.log(` [${index}] ${keccak256HashBytes(tx)}`);
});

const shaRoot = merkleRoot(transactions, "sha256");
const keccakRoot = merkleRoot(transactions, "keccak256");

console.log("\n=== Merkle Roots ===");
console.log("SHA-256 Merkle Root:", shaRoot);
console.log("Keccak-256 Merkle Root:", keccakRoot);
28 changes: 28 additions & 0 deletions Assignment/assignment1/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h2>Gas Fee Estimator</h2>
<label>Gas Used</label>
<input id="gasUsed" type="number" value="21000" />

<label>Base Fee (ETH or GWEI)</label>
<input id="baseFee" type="number" value="" step="0.000000001" />

<label>Priority Fee (ETH or GWEI)</label>
<input id="priorityFee" type="number" value="" step="0.000000001" />

<label>Max Fee (ETH or GWEI)</label>
<input id="maxFee" type="number" value="25" step="0.000000001" />

<button onclick="calculateGas()">Estimate Gas Fee</button>

<div class="result" id="output"></div>
</body>
<script src="GasEstimation.js"></script>
</html>
9 changes: 9 additions & 0 deletions Assignment/assignment1/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"type": "module",
"dependencies": {
"dotenv": "^17.2.3",
"ether.js": "^1.0.0",
"ethers": "^6.16.0",
"git": "^0.1.5"
}
}
17 changes: 17 additions & 0 deletions Assignment/assignment1/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
body {
font-family: Arial, sans-serif;
padding: 30px;
max-width: 500px;
}
input, button {
width: 100%;
padding: 8px;
margin-top: 10px;
}
button {
cursor: pointer;
}
.result {
margin-top: 20px;
font-weight: bold;
}
2 changes: 2 additions & 0 deletions Assignment/assignment2/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.env
node_modules/
8 changes: 8 additions & 0 deletions Assignment/assignment2/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

# Assignment 2: Block Implementation

This assignment focuses on the implementation of blockchain blocks.

## Theory

For explanations and theory concerning assignment 2 or `block.js`, see: https://hackmd.io/@luhrhenz/rkXCcZMIbe
35 changes: 35 additions & 0 deletions Assignment/assignment2/block.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { ethers } from "ethers";
import dotenv from "dotenv";

// Load environment variables from .env file
dotenv.config({ path: ".env" });

// 1. Connect to Ethereum mainnet using secure API URL from .env
const apiUrl = process.env.ALCHEMY_API_URL;
if (!apiUrl) {
throw new Error("ALCHEMY_API_URL not found in .env file");
}

const provider = new ethers.JsonRpcProvider(apiUrl);

async function fetchBlock(blockNumber) {
// 2. Fetch real block data
const block = await provider.getBlock(blockNumber);

// 3. Display key block header fields
const date = new Date(block.timestamp * 1000);
console.log("Block Number:", block.number);
console.log("Parent Hash:", block.parentHash);
console.log("Timestamp:", date.toUTCString());
console.log("Gas Used:", block.gasUsed.toString());
console.log("Gas Limit:", block.gasLimit.toString());
console.log("Base Fee Per Gas:", block.baseFeePerGas.toString()/1e20, "Eth");
console.log("Receipts Root:", block.receiptsRoot);
console.log("State Root:", block.stateRoot);
console.log("Validator:", block.miner);
console.log("Logs Bloom:", block.logsBloom);

console.log("Block Hash:", block.hash);
}

fetchBlock("latest");
8 changes: 8 additions & 0 deletions Assignment/assignment3/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

# Assignment 3

This assignment covers advanced topics in blockchain blocks.

## Theory

For explanations and theory concerning assignment 3, see: https://hackmd.io/@luhrhenz/rkXCcZMIbe
8 changes: 8 additions & 0 deletions Assignment/assignment4/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

# Assignment 4: JSON-RPC Methods

This assignment explores JSON-RPC methods in blockchain contexts.

## Theory

For detailed information on JSON-RPC methods, see: https://hackmd.io/@luhrhenz/SyeXaxrLWx
8 changes: 8 additions & 0 deletions Assignment/assignment5/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

# Assignment 5: Key Concepts on Consensus Clients

This assignment covers key concepts related to consensus clients in blockchain networks.

## Theory

For detailed information on consensus clients, see: https://hackmd.io/@luhrhenz/ByeiKILUbg
57 changes: 57 additions & 0 deletions Assignment/solidity-assignment7/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Sample Hardhat 3 Beta Project (`node:test` and `viem`)

This project showcases a Hardhat 3 Beta project using the native Node.js test runner (`node:test`) and the `viem` library for Ethereum interactions.

To learn more about the Hardhat 3 Beta, please visit the [Getting Started guide](https://hardhat.org/docs/getting-started#getting-started-with-hardhat-3). To share your feedback, join our [Hardhat 3 Beta](https://hardhat.org/hardhat3-beta-telegram-group) Telegram group or [open an issue](https://github.com/NomicFoundation/hardhat/issues/new) in our GitHub issue tracker.

## Project Overview

This example project includes:

- A simple Hardhat configuration file.
- Foundry-compatible Solidity unit tests.
- TypeScript integration tests using [`node:test`](nodejs.org/api/test.html), the new Node.js native test runner, and [`viem`](https://viem.sh/).
- Examples demonstrating how to connect to different types of networks, including locally simulating OP mainnet.

## Usage

### Running Tests

To run all the tests in the project, execute the following command:

```shell
npx hardhat test
```

You can also selectively run the Solidity or `node:test` tests:

```shell
npx hardhat test solidity
npx hardhat test nodejs
```

### Make a deployment to Sepolia

This project includes an example Ignition module to deploy the contract. You can deploy this module to a locally simulated chain or to Sepolia.

To run the deployment to a local chain:

```shell
npx hardhat ignition deploy ignition/modules/Counter.ts
```

To run the deployment to Sepolia, you need an account with funds to send the transaction. The provided Hardhat configuration includes a Configuration Variable called `SEPOLIA_PRIVATE_KEY`, which you can use to set the private key of the account you want to use.

You can set the `SEPOLIA_PRIVATE_KEY` variable using the `hardhat-keystore` plugin or by setting it as an environment variable.

To set the `SEPOLIA_PRIVATE_KEY` config variable using `hardhat-keystore`:

```shell
npx hardhat keystore set SEPOLIA_PRIVATE_KEY
```

After setting the variable, you can run the deployment with the Sepolia network:

```shell
npx hardhat ignition deploy --network sepolia ignition/modules/Counter.ts
```
Empty file.
Loading