Portaldot Hacker House 2026 | Milestone Grants
PROJECT INTRODUCTION
Milestone Grants is a grant escrow on Portaldot V3. A funder locks the full grant in a smart contract. The recipient claims each milestone with a git commit as evidence. The money releases only when M of N reviewers approve. The contract supports native tPOT and ERC-20 tokens.
PROBLEM SOLVED
Grants are usually paid up front or in lump sums, so the money leaves before the work exists. Funders lose leverage, and contributors have no guarantee that finished work will be paid. Milestones live in chat threads and spreadsheets, and “done” means whoever last said it. Milestone Grants makes delivery, review and payment three separate, on-chain steps.
LINKS
Demo video: https://youtu.be/jUMyjCzC1kg
Live app: https://milestone-grants.vercel.app
GitHub: GitHub - orjinameh/milestone-grants · GitHub
Pitch deck: https://drive.google.com/file/d/1wvXaBcWoXvtm5xh8Fk9ZSMWLKhogYTBu/view?usp=sharing
TECHNICAL HIGHLIGHTS
- Escrow by milestone. The contract holds the whole grant and pays out one milestone at a time, directly to the recipient.
- Evidence and M of N review. A claim carries a git commit reference. A milestone releases only after enough distinct reviewers approve.
- Role separation. Funder, recipient and reviewers must be different accounts, so nobody approves their own payout.
- Safe token handling. Reentrancy guard on every function that moves funds. Fee on transfer tokens are rejected by a balance check before and after each transfer.
- Portaldot native. Runs on pallet-revive on Portaldot V3 (chain 420420777). Users sign with their own wallet and the app never holds a key. The contract pays native tPOT to Substrate accounts through Portaldot’s address mapping.
ON-CHAIN PROOF (Portaldot V3 testnet)
MilestoneGrants contract: 0x93ca24a53ec91488ff7841ac9a00cc0ce7ac82fa (EVM chain 420420777)
Deployed by: 0xf3a73e7fa1b01f0f77970fa81e922bac589b64a4
Deploy extrinsic: 354887-1, block 354887, event revive(Instantiated)
Block hash: 0x67e499b8fb6ee0418ba8d50bbf612691917c01a0e30b7e59eb01288d22e0602b
Live run from the deployed app in the MetaMask browser:
Grant funded: extrinsic 354987-1 (block 354987), GrantCreated event, grant ID 0, native tPOT
Funder: f3a73e7fa1b01f0f77970fa81e922bac589b64a4eeeeeeeeeeeeeeeeeeeeeeee
Recipient: f6643857982777192292a978baace96c58680095eeeeeeeeeeeeeeeeeeeeeeee
Milestone 1 approved and paid: extrinsic 355310-1 (block 355310), MilestoneApproved and MilestoneReleased events, balances transfer of 4 tPOT to the claimer
Milestone 2 approved and paid: extrinsic 355333-1 (block 355333), MilestoneApproved and MilestoneReleased events, balances transfer of 4 tPOT to the claimer
Total released: 8 tPOT across two milestones
Claimer: 5HdmQe3tt5uArpbctcJKxqVjKw6XkPT9hNrbqXbw1wQ388dZ
TEAM
Team name: Orjinameh
Builder: Peter Stephen, GitHub: orjinameh
Contact: peterstephen22000@gmail.com
Solo submission: yes
JUDGES
Contract deployed on Portaldot V3, with the funding and both payouts above visible in the explorer.
Event signatures in the explorer match the repository source. Full deployed bytecode comparison has not been done.
32 contract tests pass, including a hostile contract reentrancy test.
Licence: MIT
Known limits:
Expired grant reclaim and ERC-20 grants are covered by the contract tests but were not run on the live testnet.
In the live run the funder typed the repository name as Orjinameh/milestone-grant (missing the final “s”), so the GitHub commit check could not verify the evidence. Reviewer approval and payment still completed on chain.
On iPhone and iPad, transactions need the MetaMask app browser.
Portaldot folds the storage deposit into gas, so MetaMask shows large gas estimates and a “Review alert” on some transactions. They still succeed.
COMMUNITY VOTERS
Anyone with MetaMask can try it: open the live app in the MetaMask browser, connect, and create a small grant. You need test POT from the Portaldot faucet. Use three different accounts for funder, recipient and reviewer.