Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
c13ad8b
Feat: Implement the todo contract
Mac-5 Feb 16, 2026
5ab0b38
feat: Initialize the Milestone escrow contract
Mac-5 Feb 18, 2026
c5dbade
feat: Initialize the TimeLock contract
Mac-5 Feb 18, 2026
302755d
feat: Initialize the Escrow contract
Mac-5 Feb 18, 2026
51ef79c
Remove fallback function from Escrow contract
Mac-5 Feb 24, 2026
c8be813
chore: merge PR #140 from Mac-5/submission/assignment-02/Mac-5
sprtd Feb 24, 2026
9197110
chore: Update .gitignore to exclude artifacts and non-code files
Mac-5 Feb 24, 2026
7ec99cd
chor: merge pull request #166 from BlockheaderWeb3-Community/as-w3-d3
sprtd Feb 25, 2026
f34db7b
Add MarketPlace NFT marketplace implementation
Mac-5 Feb 25, 2026
a529767
Change payment transfer to use call method
Mac-5 Feb 25, 2026
b5e8f2e
Fix call syntax for transferring sellerAmount
Mac-5 Feb 25, 2026
8a99712
chore: add test in package.json
sprtd Feb 25, 2026
6892733
chore: merge PR #168 from Mac-5/features/tokens
sprtd Feb 25, 2026
e532bef
chore: merge PR #174 from BlockheaderWeb3-Community/tokens
sprtd Feb 25, 2026
1da58f1
chore: set up for testing
sprtd Feb 25, 2026
7d751f3
chore: merge PR #178 from BlockheaderWeb3-Community/intro-to-testing
sprtd Feb 25, 2026
0a3ce5c
test: validate Timelock deployment
sprtd Feb 25, 2026
06c1a7b
test: revert 0 ETH deposit
sprtd Feb 25, 2026
0beb97a
test: validate reverts
sprtd Feb 25, 2026
5047801
test: revert past unlock time
sprtd Feb 25, 2026
ebcee19
test: validate multiple deposits
sprtd Feb 25, 2026
72c3a67
chore: merge PR #183 from BlockheaderWeb3-Community/intro-to-test-vault
sprtd Feb 25, 2026
5c02189
Todo assignment
Kingsman-99 Mar 2, 2026
0e03eb7
Escrow-v1
Kingsman-99 Mar 2, 2026
c1d6758
Merge branch 'BlockheaderWeb3-Community:main' into submission/assignm…
Kingsman-99 Mar 12, 2026
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
15 changes: 15 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,18 @@ node_modules
# Rust build artifacts
/target
**/target
artifacts/
cache/
typechain-types/

# Logs
*.log

# OS files
.DS_Store
Thumbs.db

# IDE
.idea/
*.swp
*.swo
33 changes: 33 additions & 0 deletions assignments/9-Escrow V1/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Dependencies
/node_modules
/lib
# Build outputs
/dist
/bundle
/artifacts
/cache
/coverage
/types
/typechain
/typechain-types

# Hardhat Ignition deployment output (keep ignition/modules tracked)
/ignition/deployments

# Local environment/secrets
.env
.env.*
!.env.example

# Logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*

# OS/editor files
.DS_Store
Thumbs.db
.vscode/*
!.vscode/extensions.json
57 changes: 57 additions & 0 deletions assignments/9-Escrow V1/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Sample Hardhat 3 Beta Project (`mocha` and `ethers`)

This project showcases a Hardhat 3 Beta project using `mocha` for tests and the `ethers` 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 `mocha` and ethers.js
- 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 `mocha` tests:

```shell
npx hardhat test solidity
npx hardhat test mocha
```

### 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
```
53 changes: 53 additions & 0 deletions assignments/9-Escrow V1/contracts/Escrow-V1.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.28;

contract Escrow {
address public buyer;
address public seller;
address public escrowAgent;
bool public deliveryConfirmed;

enum EscrowState { AWAITING_PAYMENT, AWAITING_DELIVERY, COMPLETE }
EscrowState public state;

constructor(address _buyer, address _seller) {
require(_buyer != address(0) && _seller != address(0), "Invalid address");
require(_buyer != _seller, "Buyer and seller must differ");
buyer = _buyer; seller = _seller; escrowAgent = msg.sender;
state = EscrowState.AWAITING_PAYMENT;
}

modifier onlyBuyer() { require(msg.sender == buyer, "Only buyer"); _; }
modifier onlyEscrow() { require(msg.sender == escrowAgent, "Only escrow agent"); _; }
modifier inState(EscrowState s) { require(state == s, "Invalid state"); _; }

function deposit() external payable onlyBuyer inState(EscrowState.AWAITING_PAYMENT) {
require(msg.value > 0, "Must deposit ETH");
state = EscrowState.AWAITING_DELIVERY;
}

// Important fix: buyer confirms delivery, not seller.
function confirmDelivery() external onlyBuyer inState(EscrowState.AWAITING_DELIVERY) {
deliveryConfirmed = true;
}

// Important fix: funds can only be released after delivery is confirmed.
function releaseFunds() external onlyEscrow inState(EscrowState.AWAITING_DELIVERY) {
require(deliveryConfirmed, "Delivery not confirmed");
uint256 amount = address(this).balance;
require(amount > 0, "No funds");
state = EscrowState.COMPLETE;
(bool ok, ) = payable(seller).call{value: amount}("");
require(ok, "Release failed");
}

function refundBuyer() external onlyEscrow inState(EscrowState.AWAITING_DELIVERY) {
uint256 amount = address(this).balance;
require(amount > 0, "No funds");
state = EscrowState.COMPLETE;
(bool ok, ) = payable(buyer).call{value: amount}("");
require(ok, "Refund failed");
}

function getEscrowBalance() external view returns (uint256) { return address(this).balance; }
}
38 changes: 38 additions & 0 deletions assignments/9-Escrow V1/hardhat.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import hardhatToolboxMochaEthersPlugin from "@nomicfoundation/hardhat-toolbox-mocha-ethers";
import { configVariable, defineConfig } from "hardhat/config";

export default defineConfig({
plugins: [hardhatToolboxMochaEthersPlugin],
solidity: {
profiles: {
default: {
version: "0.8.28",
},
production: {
version: "0.8.28",
settings: {
optimizer: {
enabled: true,
runs: 200,
},
},
},
},
},
networks: {
hardhatMainnet: {
type: "edr-simulated",
chainType: "l1",
},
hardhatOp: {
type: "edr-simulated",
chainType: "op",
},
sepolia: {
type: "http",
chainType: "l1",
url: configVariable("SEPOLIA_RPC_URL"),
accounts: [configVariable("SEPOLIA_PRIVATE_KEY")],
},
},
});
9 changes: 9 additions & 0 deletions assignments/9-Escrow V1/ignition/modules/Counter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { buildModule } from "@nomicfoundation/hardhat-ignition/modules";

export default buildModule("CounterModule", (m) => {
const counter = m.contract("Counter");

m.call(counter, "incBy", [5n]);

return { counter };
});
28 changes: 28 additions & 0 deletions assignments/9-Escrow V1/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"name": "9-escrow-v1",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@nomicfoundation/hardhat-ethers": "^4.0.5",
"@nomicfoundation/hardhat-ignition": "^3.0.8",
"@nomicfoundation/hardhat-toolbox-mocha-ethers": "^3.0.3",
"@types/chai": "^5.2.3",
"@types/chai-as-promised": "^8.0.2",
"@types/mocha": "^10.0.10",
"@types/node": "^22.19.13",
"chai": "^6.2.2",
"ethers": "^6.16.0",
"forge-std": "github:foundry-rs/forge-std#v1.9.4",
"hardhat": "^3.1.10",
"mocha": "^11.7.5",
"typescript": "~5.8.0"
},
"type": "module"
}
22 changes: 22 additions & 0 deletions assignments/9-Escrow V1/scripts/send-op-tx.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { network } from "hardhat";

const { ethers } = await network.connect({
network: "hardhatOp",
chainType: "op",
});

console.log("Sending transaction using the OP chain type");

const [sender] = await ethers.getSigners();

console.log("Sending 1 wei from", sender.address, "to itself");

console.log("Sending L2 transaction");
const tx = await sender.sendTransaction({
to: sender.address,
value: 1n,
});

await tx.wait();

console.log("Transaction sent successfully");
39 changes: 39 additions & 0 deletions assignments/9-Escrow V1/test/Escrow-V1.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { expect } from "chai";
import { network } from "hardhat";

const { ethers } = await network.connect();

describe("Escrow", function () {
const one = ethers.parseEther("1");
const setup = async () => {
const [agent, buyer, seller, other] = await ethers.getSigners();
const e = await ethers.deployContract("Escrow", [buyer.address, seller.address]);
return { e, agent, buyer, seller, other };
};

it("buyer deposits, confirms delivery, escrow releases to seller", async function () {
const { e, buyer, seller } = await setup();
await e.connect(buyer).deposit({ value: one });
await e.connect(buyer).confirmDelivery();
await e.releaseFunds();
expect(await ethers.provider.getBalance(await e.getAddress())).to.equal(0n);
expect(await e.state()).to.equal(2n);
});

it("enforces roles and requires delivery confirmation before release", async function () {
const { e, buyer, other } = await setup();
await expect(e.connect(other).deposit({ value: one })).to.be.revertedWith("Only buyer");
await e.connect(buyer).deposit({ value: one });
await expect(e.releaseFunds()).to.be.revertedWith("Delivery not confirmed");
await expect(e.connect(other).confirmDelivery()).to.be.revertedWith("Only buyer");
});

it("escrow can refund buyer in delivery stage", async function () {
const { e, buyer, other } = await setup();
await e.connect(buyer).deposit({ value: one });
await e.refundBuyer();
expect(await ethers.provider.getBalance(await e.getAddress())).to.equal(0n);
await expect(e.refundBuyer()).to.be.revertedWith("Invalid state");
await expect(e.connect(other).releaseFunds()).to.be.revertedWith("Only escrow agent");
});
});
13 changes: 13 additions & 0 deletions assignments/9-Escrow V1/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/* Based on https://github.com/tsconfig/bases/blob/501da2bcd640cf95c95805783e1012b992338f28/bases/node22.json */
{
"compilerOptions": {
"lib": ["es2023"],
"module": "node16",
"target": "es2022",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"moduleResolution": "node16",
"outDir": "dist"
}
}
33 changes: 33 additions & 0 deletions assignments/Assignment/8-todo-contract/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Dependencies
/node_modules
/lib
# Build outputs
/dist
/bundle
/artifacts
/cache
/coverage
/types
/typechain
/typechain-types

# Hardhat Ignition deployment output (keep ignition/modules tracked)
/ignition/deployments

# Local environment/secrets
.env
.env.*
!.env.example

# Logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*

# OS/editor files
.DS_Store
Thumbs.db
.vscode/*
!.vscode/extensions.json
Loading