diff --git a/.gitignore b/.gitignore
index 42061c0..e69de29 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +0,0 @@
-README.md
\ No newline at end of file
diff --git a/README.md b/README.md
index bd5d029..09d3034 100644
--- a/README.md
+++ b/README.md
@@ -1,72 +1,133 @@
-# ๐ฅโ๏ธ๐ฎ **Forge: Token Crafting Game**
+[](https://forge-tokens.vercel.app)
+
+
-*(README in progress...)*
+# ๐ฅโ๏ธ **Forge Token Crafting Game**
---
-## **Game Overview**
+**Forge** is a Web3 token crafting game where players mint, burn, and trade tokens to create rare items. Basic tokens can be minted directly, while forged tokens require burning combinations of basic tokens. The game includes a cooldown mechanism to prevent spamming.
-**Forge** is a Web3 token crafting game where players mint, burn, and trade tokens to create rare items. Basic tokens can be minted directly, while forged tokens require burning combinations of basic tokens.
+> I built Forge to challenge myself with full-stack Web3 development: **Solidity** + **Foundry** for on-chain game logic, and a modern **Next.js** dApp that handles **real-time blockchain events**. The goal was to create a complete, production-style project touching frontend, backend, smart contracts, deployment, and testing.
---
-## **Live Demo ๐**
+## ๐ Quick Start
-๐ [Play now](https://forge-tokens.vercel.app)
+### 1. Try the Demo: [๐ Live Demo](https://forge-tokens.vercel.app)
+
+### 2. Get Testnet ETH: [Sepolia Faucet](https://sepolia-faucet.pk910.de/)
+
+### 3. Connect your wallet to the DApp
+
+### 4. Start Forging
+
+- Mint basic tokens: IDs 0, 1, 2
+
+- Burn + combine basic tokens: to craft tokens 3, 4, 5, 6
+
+- Trade tokens: turn any token into a different basic token
+
+---
+
+## โจ Main Features
+
+- On-chain token crafting system (ERC-1155)
+- Event-driven gameplay: real-time updates via WebSocket
+- Cooldown-based minting for game balance
+- Full Web3 integration (Wagmi + RainbowKit)
+- Responsive dApp (desktop + mobile)
+- 100% contract test coverage (Foundry)
+- Deployed contracts on Sepolia
+- Verified contracts on Etherscan
---
-## **Game Rules**
+## ๐ฅ Demo Previews
-### **1. Token Categories**
+### ๐ฅ๏ธ Desktop Gameplay
+
+#### **1. Minting Basic Tokens**
+
+
+
+#### **2. Trading Tokens**
+
+
+
+#### **3. Forging Rare Tokens**
+
+
+
+#### **4. Burning Tokens**
+
+
+
+---
+
+### ๐ฑ Mobile Preview
+
+#### **Minting on Mobile**
+
+
+
+---
+
+## ๐ Game Rules
+
+### 1. Token Categories
| Token IDs | Type | Minting Rule |
|-----------|-----------|---------------------------------------|
-| 0, 1, 2 | Basic | Mint directly (1-minute cooldown). |
+| 0, 1, 2 | Basic | Mint directly (15 seconds cooldown). |
| 3, 4, 5, 6| Forged | Burn specific basic tokens to mint. |
-### **2. Minting Rules**
+### 2. Minting Rules
- **Basic Tokens (0, 1, 2):**
- - **Action:** `mint(_tokenId)`
- - **Cooldown:** 1 minute per user.
+ - **Cooldown:** 15 seconds per user.
- **Limit:** 1 token per call.
- **Forged Tokens (3, 4, 5, 6):**
- - **Action:** `mint(_tokenId)`
- **Requirements:**
- **Token 3:** Burn 1x token 0 + 1x token 1.
- **Token 4:** Burn 1x token 1 + 1x token 2.
- **Token 5:** Burn 1x token 0 + 1x token 2.
- **Token 6:** Burn 1x token 0 + 1x token 1 + 1x token 2.
-### **3. Burning & Trading**
-
-- **Burning:** Only tokens 3-6 can be burned directly.
-- **Trading:** Burn any token to mint tokens 0-2 (cannot trade a token for itself).
+### 3. Burning & Trading Rules
-### **Key Constraints**
-
-- **Cooldown:** Applies only to minting tokens 0-2.
-- **Single Mint:** Only 1 token per function call.
-- **Ownership:** Only the Forge contract can mint/burn tokens.
+- Tokens 3โ6 can be burned directly
+- Trading: burn any token to mint one of token 0, 1, or 2
+- Cannot trade a token into itself
+- Only the Forge contract can mint/burn tokens
---
-## **How to Play**
+## ๐งฐ Tech Stack
-1. **Connect your wallet** to the DApp.
-2. **Mint basic tokens** (0, 1, 2) to start crafting.
-3. **Burn combinations** of basic tokens to forge rare tokens (3, 4, 5, 6).
-4. **Trade tokens** to optimize your inventory.
+### Frontend
----
+| Technology | Purpose |
+| ---------------------------- | ------------------------------- |
+| Next.js + TypeScript | Core framework |
+| Tailwind + shadcn/ui | UI styling and components |
+| Zod + React Hook Form | Form validation and type safety |
+| React Context | State management |
+| Custom Hooks | `useMintEvents`, `useForgeEvents`, `useBurnEvents`, `useTradeEvents` (on-chain event-driven refetching) |
+| TanStack Query (React Query) | Caching and data sync |
+| **Wagmi** + RainbowKit | Web3 wallet connection & hooks |
+| pnpm | Frontend package manager |
-## **Tech Stack**
+### Backend
-- **Frontend:** Next.js, shadcn/ui, Wagmi, Viem, TanStack Query
-- **Blockchain:** Solidity, Foundry, Alchemy (WebSocket + HTTP RPC)
-- **State Management:** React Context, React Query
+| Layer | Technologies |
+ |----------------|----------------------------------|
+ | Contracts | **Solidity**, **Foundry**, ***Sepolia*** |
+ | Testing | **Foundry tests** |
+ | Storage | IPFS (NFT metadata) |
+ | Blockchain Access | **Alchemy** (HTTP + WebSocket) |
+ | Package Manager | forge |
---
@@ -82,10 +143,137 @@
[0x8281b01D35A70BDc17D85c6df3d45B67745a5F9f](https://sepolia.etherscan.io/address/0x8281b01D35A70BDc17D85c6df3d45B67745a5F9f#code)
*(Verified on Etherscan)*
-### **Testing**
+---
+
+## ๐ Setup & Deployment
+
+Below is everything needed to run, test, and deploy the Forge contracts and its frontend.
-- **100% Coverage:** Both Solidity contracts (Forge + FToken) are tested with **Foundry**.
+### Clone project
+
+```bash
+git clone git@github.com:SiegfriedBz/Forge-DApp.git
+```
---
-*(README in progress. More details coming soon!)*
+### ๐ง Backend Setup (Foundry)
+
+All global deployment parameters
+(e.g., `TOKEN_URI`, `MAX_TOKEN_ID`, `COOL_DOWN_DELAY`)
+are located in:
+
+```bash
+be/script/Forge_Constants.sol
+```
+
+#### 1. Environment Variables (Backend)
+
+Create a `.env` file in `/be`:
+
+```bash
+# Backend - Foundry
+ALCHEMY_SEPOLIA_RPC_URL=
+ETHERSCAN_API_KEY=
+PRIVATE_KEY=
+```
+
+#### 2. Deploy Contracts to *Sepolia* Testnet (auto-verify)
+
+```bash
+# Backend - Foundry
+cd be
+# Deploy Forge & FToken contracts
+forge script script/ForgeScript.s.sol \
+ --rpc-url $ALCHEMY_SEPOLIA_RPC_URL \
+ --broadcast \
+ --verify
+```
+
+This deploys:
+
+- Forge.sol (core forging logic)
+- FToken.sol (ERC1155 collection)
+
+---
+
+### ๐ฅ๏ธ Frontend Setup (Next.js)
+
+#### 1. Environment Variables (Frontend)
+
+Create a `.env` file in `/fe`:
+
+```bash
+# Frontend
+NEXT_PUBLIC_ETH_SEPOLIA_ALCHEMY_HTTP_URL=
+NEXT_PUBLIC_ETH_SEPOLIA_ALCHEMY_WS_URL= # For live onchain updates
+NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID=
+```
+
+#### 2. Contract Addresses & ABIs
+
+Update:
+`/fe/app/_contracts/`
+with the latest ABIs and deployed contract addresses from the backend deployment output.
+
+#### 3. Install dependencies & run locally
+
+```bash
+# Frontend
+cd fe
+pnpm install
+pnpm dev
+```
+
+---
+
+### ๐งช Testing & Coverage (Smart Contracts)
+
+All smart contracts were tested using Foundry with full branch, statement, and function coverage.
+
+Run Full Test Suite locally:
+
+```bash
+cd be
+forge test
+```
+
+Coverage Report:
+
+```bash
+cd be
+forge coverage
+```
+
+
+ View Coverage Report (100%)
+
+| File | Lines | Statements | Branches | Funcs |
+| ----------------------------- | ---------------- | ---------------- | ---------------- | ---------------- |
+| **script/FTokenScript.s.sol** | 100% (6/6) | 100% (5/5) | 100% (0/0) | 100% (1/1) |
+| **script/ForgeScript.s.sol** | 100% (6/6) | 100% (5/5) | 100% (0/0) | 100% (1/1) |
+| **src/FToken.sol** | 100% (16/16) | 100% (11/11) | 100% (1/1) | 100% (7/7) |
+| **src/Forge.sol** | 100% (67/67) | 100% (78/78) | 100% (18/18) | 100% (8/8) |
+| **Total** | **100% (95/95)** | **100% (99/99)** | **100% (19/19)** | **100% (17/17)** |
+
+
+
+---
+๐ฏ Project Summary
+
+Forge is an ERC1155 mint โ forge โ trade onchain game where players progressively transform base materials into higher-tier items.
+Contracts enforce forging rules, cooldowns, and token evolution, while the frontend provides a smooth UX built with:
+
+- Next.js 16
+- Foundry + Solidity
+- Wagmi + Viem
+- Alchemy WebSockets for live on-chain events
+
+---
+
+## Author
+
+Built solo by **Siegfried Bozza**: Full-stack development, smart contracts, and deployment.
+
+๐ผ [LinkedIn](https://www.linkedin.com/in/siegfriedbozza/)
+๐ [GitHub](https://github.com/SiegfriedBz)
diff --git a/assets/desktop-burn.04.gif b/assets/desktop-burn.04.gif
new file mode 100644
index 0000000..7d08f67
Binary files /dev/null and b/assets/desktop-burn.04.gif differ
diff --git a/assets/desktop-forge.03.gif b/assets/desktop-forge.03.gif
new file mode 100644
index 0000000..574818a
Binary files /dev/null and b/assets/desktop-forge.03.gif differ
diff --git a/assets/desktop-mint.01.gif b/assets/desktop-mint.01.gif
new file mode 100644
index 0000000..6da6acd
Binary files /dev/null and b/assets/desktop-mint.01.gif differ
diff --git a/assets/desktop-trade.02.gif b/assets/desktop-trade.02.gif
new file mode 100644
index 0000000..4b175bc
Binary files /dev/null and b/assets/desktop-trade.02.gif differ
diff --git a/assets/mobile-mint.gif b/assets/mobile-mint.gif
new file mode 100644
index 0000000..51f4667
Binary files /dev/null and b/assets/mobile-mint.gif differ
diff --git a/be/lib/openzeppelin-contracts/README.md b/be/lib/openzeppelin-contracts/README.md
new file mode 100644
index 0000000..6a01f56
--- /dev/null
+++ b/be/lib/openzeppelin-contracts/README.md
@@ -0,0 +1,122 @@
+#
+
+[](https://github.com/OpenZeppelin/openzeppelin-contracts/releases/latest)
+[](https://www.npmjs.org/package/@openzeppelin/contracts)
+[](https://codecov.io/gh/OpenZeppelin/openzeppelin-contracts)
+[](https://www.gitpoap.io/gh/OpenZeppelin/openzeppelin-contracts)
+[](https://docs.openzeppelin.com/contracts)
+[](https://forum.openzeppelin.com/)
+
+**A library for secure smart contract development.** Build on a solid foundation of community-vetted code.
+
+ * Implementations of standards like [ERC20](https://docs.openzeppelin.com/contracts/erc20) and [ERC721](https://docs.openzeppelin.com/contracts/erc721).
+ * Flexible [role-based permissioning](https://docs.openzeppelin.com/contracts/access-control) scheme.
+ * Reusable [Solidity components](https://docs.openzeppelin.com/contracts/utilities) to build custom contracts and complex decentralized systems.
+
+:mage: **Not sure how to get started?** Check out [Contracts Wizard](https://wizard.openzeppelin.com/) โ an interactive smart contract generator.
+
+> [!IMPORTANT]
+> OpenZeppelin Contracts uses semantic versioning to communicate backwards compatibility of its API and storage layout. For upgradeable contracts, the storage layout of different major versions should be assumed incompatible, for example, it is unsafe to upgrade from 4.9.3 to 5.0.0. Learn more at [Backwards Compatibility](https://docs.openzeppelin.com/contracts/backwards-compatibility).
+
+## Overview
+
+### Release tags
+
+We use NPM tags to clearly distinguish between audited and non-audited versions of our package:
+
+| Tag | Purpose | Description |
+| :--------- | :----------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **latest** | โ Audited releases | Stable, audited versions of the package. This is the **default** version installed when users run `npm install @openzeppelin/contracts`. |
+| **dev** | ๐งช Final but not audited | Versions that are finalized and feature-complete but have **not yet been audited**. This version is fully tested, can be used in production and is covered by the bug bounty. |
+| **next** | ๐ง Release candidates | Pre-release versions that are **not final**. Used for testing and validation before the version becomes a final `dev` or `latest` release. |
+
+### Installation
+
+#### Hardhat (npm)
+
+```
+$ npm install @openzeppelin/contracts
+```
+โ Installs the latest audited release (`latest`).
+
+```
+$ npm install @openzeppelin/contracts@dev
+```
+โ Installs the latest unaudited release (`dev`).
+
+#### Foundry (git)
+
+> [!WARNING]
+> When installing via git, it is a common error to use the `master` branch. This is a development branch that should be avoided in favor of tagged releases. The release process involves security measures that the `master` branch does not guarantee.
+
+> [!WARNING]
+> Foundry installs the latest version initially, but subsequent `forge update` commands will use the `master` branch.
+
+```
+$ forge install OpenZeppelin/openzeppelin-contracts
+```
+
+Add `@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/` in `remappings.txt`.
+
+### Usage
+
+Once installed, you can use the contracts in the library by importing them:
+
+```solidity
+pragma solidity ^0.8.20;
+
+import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol";
+
+contract MyCollectible is ERC721 {
+ constructor() ERC721("MyCollectible", "MCO") {
+ }
+}
+```
+
+_If you're new to smart contract development, head to [Developing Smart Contracts](https://docs.openzeppelin.com/learn/developing-smart-contracts) to learn about creating a new project and compiling your contracts._
+
+To keep your system secure, you should **always** use the installed code as-is, and neither copy-paste it from online sources nor modify it yourself. The library is designed so that only the contracts and functions you use are deployed, so you don't need to worry about it needlessly increasing gas costs.
+
+## Learn More
+
+The guides in the [documentation site](https://docs.openzeppelin.com/contracts) will teach about different concepts, and how to use the related contracts that OpenZeppelin Contracts provides:
+
+* [Access Control](https://docs.openzeppelin.com/contracts/access-control): decide who can perform each of the actions on your system.
+* [Tokens](https://docs.openzeppelin.com/contracts/tokens): create tradeable assets or collectibles for popular ERC standards like ERC-20, ERC-721, ERC-1155, and ERC-6909.
+* [Utilities](https://docs.openzeppelin.com/contracts/utilities): generic useful tools including non-overflowing math, signature verification, and trustless paying systems.
+
+The [full API](https://docs.openzeppelin.com/contracts/api/token/ERC20) is also thoroughly documented, and serves as a great reference when developing your smart contract application. You can also ask for help or follow Contracts' development in the [community forum](https://forum.openzeppelin.com).
+
+Finally, you may want to take a look at the [guides on our blog](https://blog.openzeppelin.com/), which cover several common use cases and good practices. The following articles provide great background reading, though please note that some of the referenced tools have changed, as the tooling in the ecosystem continues to rapidly evolve.
+
+* [The Hitchhikerโs Guide to Smart Contracts in Ethereum](https://blog.openzeppelin.com/the-hitchhikers-guide-to-smart-contracts-in-ethereum-848f08001f05) will help you get an overview of the various tools available for smart contract development, and help you set up your environment.
+* [A Gentle Introduction to Ethereum Programming, Part 1](https://blog.openzeppelin.com/a-gentle-introduction-to-ethereum-programming-part-1-783cc7796094) provides very useful information on an introductory level, including many basic concepts from the Ethereum platform.
+* For a more in-depth dive, you may read the guide [Designing the Architecture for Your Ethereum Application](https://blog.openzeppelin.com/designing-the-architecture-for-your-ethereum-application-9cec086f8317), which discusses how to better structure your application and its relationship to the real world.
+
+## Security
+
+This project is maintained by [OpenZeppelin](https://openzeppelin.com) with the goal of providing a secure and reliable library of smart contract components for the ecosystem. We address security through risk management in various areas such as engineering and open source best practices, scoping and API design, multi-layered review processes, and incident response preparedness.
+
+The [OpenZeppelin Contracts Security Center](https://contracts.openzeppelin.com/security) contains more details about the secure development process.
+
+The security policy is detailed in [`SECURITY.md`](./SECURITY.md) as well, and specifies how you can report security vulnerabilities, which versions will receive security patches, and how to stay informed about them. We run a [bug bounty program on Immunefi](https://immunefi.com/bounty/openzeppelin) to reward the responsible disclosure of vulnerabilities.
+
+The engineering guidelines we follow to promote project quality can be found in [`GUIDELINES.md`](./GUIDELINES.md).
+
+Past audits can be found in [`audits/`](./audits).
+
+Smart contracts are a nascent technology and carry a high level of technical risk and uncertainty. Although OpenZeppelin is well known for its security audits, using OpenZeppelin Contracts is not a substitute for a security audit.
+
+OpenZeppelin Contracts is made available under the MIT License, which disclaims all warranties in relation to the project and which limits the liability of those that contribute and maintain the project, including OpenZeppelin. As set out further in the Terms, you acknowledge that you are solely responsible for any use of OpenZeppelin Contracts and you assume all risks associated with any such use.
+
+## Contribute
+
+OpenZeppelin Contracts exists thanks to its contributors. There are many ways you can participate and help build high quality software. Check out the [contribution guide](CONTRIBUTING.md)!
+
+## License
+
+OpenZeppelin Contracts is released under the [MIT License](LICENSE).
+
+## Legal
+
+Your use of this Project is governed by the terms found at www.openzeppelin.com/tos (the "Terms").
diff --git a/be/lib/openzeppelin-contracts/audits/README.md b/be/lib/openzeppelin-contracts/audits/README.md
new file mode 100644
index 0000000..d199fd9
--- /dev/null
+++ b/be/lib/openzeppelin-contracts/audits/README.md
@@ -0,0 +1,22 @@
+# Audits
+
+| Date | Version | Commit | Auditor | Scope | Links |
+| ------------- | ------- | -------------------------------------------------------------------------------- | ------------ | ---------------------------------- | ----------------------------------------------------------- |
+| October 2025 | v5.5.0 | [`f5edfc0`](https://github.com/openzeppelin/openzeppelin-contracts/tree/f5edfc0) | OpenZeppelin | SafeERC20, ECDSA, SignatureChecker | [๐](./2025-10-v5.5.pdf) |
+| July 2025 | v5.4.0 | [`f6fea85`](https://github.com/openzeppelin/openzeppelin-contracts/tree/f6fea85) | OpenZeppelin | v5.4 Changes | [๐](./2025-07-v5.4.pdf) |
+| April 2025 | v5.3.0 | [`d4b2e98`](https://github.com/openzeppelin/openzeppelin-contracts/tree/d4b2e98) | OpenZeppelin | v5.3 Changes | [๐](./2025-04-v5.3.pdf) |
+| December 2024 | v5.2.0 | [`98d28f9`](https://github.com/openzeppelin/openzeppelin-contracts/tree/98d28f9) | OpenZeppelin | v5.2 Changes | [๐](./2024-12-v5.2.pdf) |
+| October 2024 | v5.1.0 | [`aba9ff6`](https://github.com/openzeppelin/openzeppelin-contracts/tree/aba9ff6) | OpenZeppelin | v5.1 Changes | [๐](./2024-10-v5.1.pdf) |
+| October 2023 | v5.0.0 | [`b5a3e69`](https://github.com/openzeppelin/openzeppelin-contracts/tree/b5a3e69) | OpenZeppelin | v5.0 Changes | [๐](./2023-10-v5.0.pdf) |
+| May 2023 | v4.9.0 | [`91df66c`](https://github.com/openzeppelin/openzeppelin-contracts/tree/91df66c) | OpenZeppelin | v4.9 Changes | [๐](./2023-05-v4.9.pdf) |
+| October 2022 | v4.8.0 | [`14f98db`](https://github.com/openzeppelin/openzeppelin-contracts/tree/14f98db) | OpenZeppelin | ERC4626, Checkpoints | [๐](./2022-10-ERC4626.pdf) [๐](./2022-10-Checkpoints.pdf) |
+| October 2018 | v2.0.0 | [`dac5bcc`](https://github.com/openzeppelin/openzeppelin-contracts/tree/dac5bcc) | LevelK | Everything | [๐](./2018-10.pdf) |
+| March 2017 | v1.0.4 | [`9c5975a`](https://github.com/openzeppelin/openzeppelin-contracts/tree/9c5975a) | New Alchemy | Everything | [๐](./2017-03.md) |
+
+# Formal Verification
+
+| Date | Version | Commit | Tool | Scope | Links |
+| ------------ | ------- | --------- | ------- | -------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------ |
+| May 2022 | v4.7.0 | `109778c` | Certora | Initializable, GovernorPreventLateQuorum, ERC1155Burnable, ERC1155Pausable, ERC1155Supply, ERC1155Holder, ERC1155Receiver | [๐](../certora/reports/2022-05.pdf) |
+| March 2022 | v4.4.0 | `4088540` | Certora | ERC20Votes, ERC20FlashMint, ERC20Wrapper, TimelockController, ERC721Votes, Votes, AccessControl, ERC1155 | [๐](../certora/reports/2022-03.pdf) |
+| October 2021 | v4.4.0 | `4088540` | Certora | Governor, GovernorCountingSimple, GovernorProposalThreshold, GovernorTimelockControl, GovernorVotes, GovernorVotesQuorumFraction | [๐](../certora/reports/2021-10.pdf) |
diff --git a/be/lib/openzeppelin-contracts/fv/README.md b/be/lib/openzeppelin-contracts/fv/README.md
new file mode 100644
index 0000000..023a49e
--- /dev/null
+++ b/be/lib/openzeppelin-contracts/fv/README.md
@@ -0,0 +1,60 @@
+# Running formal verification tool
+
+These instructions detail the process for running Formal Verification Tool on OpenZeppelin Contracts.
+
+Documentation for CVT and the specification language is available [here](https://certora.atlassian.net/wiki/spaces/CPD/overview).
+
+## Prerequisites
+
+Follow the [Certora installation guide](https://docs.certora.com/en/latest/docs/user-guide/getting-started/install.html) in order to get the Certora Prover Package and the `solc` executable folder in your path.
+
+> **Note**
+> An API Key is required for local testing. Although the prover will run on a GitHub Actions' CI environment on selected Pull Requests.
+
+## Running the verification
+
+The Formal Verification Tool proves specs for contracts, which are defined by the `./specs.json` file along with their pre-configured options.
+
+The verification script `./run.js` is used to submit verification jobs to the Certora Verification service.
+
+You can run it from the root of the repository with the following command:
+
+```bash
+node fv/run.js [[CONTRACT_NAME:]SPEC_NAME] [OPTIONS...]
+```
+
+Where:
+
+- `CONTRACT_NAME` matches the `contract` key in the `./spec.json` file and may be empty. It will run all matching contracts if not provided.
+- `SPEC_NAME` refers to a `spec` key from the `./specs.json` file. It will run every spec if not provided.
+- `OPTIONS` extend the [Certora Prover CLI options](https://docs.certora.com/en/latest/docs/prover/cli/options.html#certora-prover-cli-options) and will respect the preconfigured options in the `specs.json` file.
+
+> **Note**
+> A single spec may be configured to run for multiple contracts, whereas a single contract may run multiple specs.
+
+Example usage:
+
+```bash
+node fv/run.js AccessControl # Run the AccessControl spec against every contract implementing it
+```
+
+## Adapting to changes in the contracts
+
+Some of our rules require the code to be simplified in various ways. Our primary tool for performing these simplifications is to run verification on a contract that extends the original contracts and overrides some of the methods. These "harness" contracts can be found in the `fv/harnesses` directory.
+
+This pattern does require some modifications to the original code: some methods need to be made virtual or public, for example. These changes are handled by applying a patch
+to the code before verification by running:
+
+```bash
+make -C fv apply
+```
+
+Before running the `fv/run.js` script, it's required to apply the corresponding patches to the `contracts` directory, placing the output in the `fv/patched` directory. Then, the contracts are verified by running the verification for the `fv/patched` directory.
+
+If the original contracts change, it is possible to create a conflict with the patch. In this case, the verify scripts will report an error message and output rejected changes in the `patched` directory. After merging the changes, run `make record` in the `fv` directory; this will regenerate the patch file, which can then be checked into git.
+
+For more information about the `make` scripts available, run:
+
+```bash
+make -C fv help
+```
diff --git a/be/lib/openzeppelin-contracts/lib/erc4626-tests/README.md b/be/lib/openzeppelin-contracts/lib/erc4626-tests/README.md
new file mode 100644
index 0000000..651e443
--- /dev/null
+++ b/be/lib/openzeppelin-contracts/lib/erc4626-tests/README.md
@@ -0,0 +1,116 @@
+# ERC4626 Property Tests
+
+Foundry (dapptools-style) property-based tests for [ERC4626] standard conformance.
+
+[ERC4626]:
+
+You can read our post on "_[Generalized property tests for ERC4626 vaults][post]_."
+
+[post]:
+
+## Overview
+
+#### What is it?
+- Test suites for checking if the given ERC4626 implementation satisfies the **standard requirements**.
+- Dapptools-style **property-based tests** for fuzzing or symbolic execution testing.
+- Tests that are **independent** from implementation details, thus applicable for any ERC4626 vaults.
+
+#### What isnโt it?
+- It does NOT test implementation-specific details, e.g., how to generate and distribute yields, how to compute the share price, etc.
+
+#### Testing properties:
+
+- **Round-trip properties**: no one can make a free profit by depositing and immediately withdrawing back and forth.
+
+- **Functional correctness**: the `deposit()`, `mint()`, `withdraw()`, and `redeem()` functions update the balance and allowance properly.
+
+- The `preview{Deposit,Redeem}()` functions **MUST NOT over-estimate** the exact amount.[^1]
+
+[^1]: That is, the `deposit()` and `redeem()` functions โMUST return the same or more amounts as their preview function if called in the same transaction.โ
+
+- The `preview{Mint,Withdraw}()` functions **MUST NOT under-estimate** the exact amount.[^2]
+
+[^2]: That is, the `mint()` and `withdraw()` functions โMUST return the same or fewer amounts as their preview function if called in the same transaction.โ
+
+- The `convertTo{Shares,Assets}` functions โ**MUST NOT show any variations** depending on the caller.โ
+
+- The `asset()`, `totalAssets()`, and `max{Deposit,Mint,Withdraw,Redeem}()` functions โ**MUST NOT revert**.โ
+
+## Usage
+
+**Step 0**: Install [foundry] and add [forge-std] in your vault repo:
+```bash
+$ curl -L https://foundry.paradigm.xyz | bash
+
+$ cd /path/to/your-erc4626-vault
+$ forge install foundry-rs/forge-std
+```
+
+[foundry]:
+[forge-std]:
+
+**Step 1**: Add this [erc4626-tests] as a dependency to your vault:
+```bash
+$ cd /path/to/your-erc4626-vault
+$ forge install a16z/erc4626-tests
+```
+
+[erc4626-tests]:
+
+**Step 2**: Extend the abstract test contract [`ERC4626Test`](ERC4626.test.sol) with your own custom vault setup method, for example:
+
+```solidity
+// SPDX-License-Identifier: AGPL-3.0
+pragma solidity >=0.8.0 <0.9.0;
+
+import "erc4626-tests/ERC4626.test.sol";
+
+import { ERC20Mock } from "/path/to/mocks/ERC20Mock.sol";
+import { ERC4626Mock } from "/path/to/mocks/ERC4626Mock.sol";
+
+contract ERC4626StdTest is ERC4626Test {
+ function setUp() public override {
+ _underlying_ = address(new ERC20Mock("Mock ERC20", "MERC20", 18));
+ _vault_ = address(new ERC4626Mock(ERC20Mock(__underlying__), "Mock ERC4626", "MERC4626"));
+ _delta_ = 0;
+ _vaultMayBeEmpty = false;
+ _unlimitedAmount = false;
+ }
+}
+```
+
+Specifically, set the state variables as follows:
+- `_vault_`: the address of your ERC4626 vault.
+- `_underlying_`: the address of the underlying asset of your vault. Note that the default `setupVault()` and `setupYield()` methods of `ERC4626Test` assume that it implements `mint(address to, uint value)` and `burn(address from, uint value)`. You can override the setup methods with your own if such `mint()` and `burn()` are not implemented.
+- `_delta_`: the maximum approximation error size to be passed to [`assertApproxEqAbs()`]. It must be given as an absolute value (not a percentage) in the smallest unit (e.g., Wei or Satoshi). Note that all the tests are expected to pass with `__delta__ == 0` as long as your vault follows the [preferred rounding direction] as specified in the standard. If your vault doesn't follow the preferred rounding direction, you can set `__delta__` to a reasonable size of rounding errors where the adversarial profit of exploiting such rounding errors stays sufficiently small compared to the gas cost. (You can read our [post] for more about the adversarial profit.)
+- `_vaultMayBeEmpty`: when set to false, fuzz inputs that empties the vault are ignored.
+- `_unlimitedAmount`: when set to false, fuzz inputs are restricted to the currently available amount from the caller. Limiting the amount can speed up fuzzing, but may miss some edge cases.
+
+[`assertApproxEqAbs()`]:
+
+[preferred rounding direction]:
+
+**Step 3**: Run `forge test`
+
+```
+$ forge test
+```
+
+## Examples
+
+Below are examples of adding these property tests to existing ERC4626 vaults:
+- [OpenZeppelin ERC4626] [[diff](https://github.com/daejunpark/openzeppelin-contracts/pull/1/files)]
+- [Solmate ERC4626] [[diff](https://github.com/daejunpark/solmate/pull/1/files)]
+- [Revenue Distribution Token] [[diff](https://github.com/daejunpark/revenue-distribution-token/pull/1/files)]
+- [Yield Daddy ERC4626 wrappers] [[diff](https://github.com/daejunpark/yield-daddy/pull/1/files)][^bug]
+
+[OpenZeppelin ERC4626]:
+[Solmate ERC4626]:
+[Revenue Distribution Token]:
+[Yield Daddy ERC4626 wrappers]:
+
+[^bug]: Our property tests indeed revealed an [issue](https://github.com/timeless-fi/yield-daddy/issues/7) in their eToken testing mock contract. The tests passed after it is [fixed](https://github.com/daejunpark/yield-daddy/commit/721cf4bd766805fd409455434aa5fd1a9b2df25c).
+
+## Disclaimer
+
+_These smart contracts are being provided as is. No guarantee, representation or warranty is being made, express or implied, as to the safety or correctness of the user interface or the smart contracts. They have not been audited and as such there can be no assurance they will work as intended, and users may experience delays, failures, errors, omissions or loss of transmitted information. THE SMART CONTRACTS CONTAINED HEREIN ARE FURNISHED AS IS, WHERE IS, WITH ALL FAULTS AND WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING ANY WARRANTY OF MERCHANTABILITY, NON-INFRINGEMENT OR FITNESS FOR ANY PARTICULAR PURPOSE. Further, use of any of these smart contracts may be restricted or prohibited under applicable law, including securities laws, and it is therefore strongly advised for you to contact a reputable attorney in any jurisdiction where these smart contracts may be accessible for any questions or concerns with respect thereto. Further, no information provided in this repo should be construed as investment advice or legal advice for any particular facts or circumstances, and is not meant to replace competent counsel. a16z is not liable for any use of the foregoing, and users should proceed with caution and use at their own risk. See a16z.com/disclosures for more info._
diff --git a/be/lib/openzeppelin-contracts/lib/forge-std/README.md b/be/lib/openzeppelin-contracts/lib/forge-std/README.md
new file mode 100644
index 0000000..2674dec
--- /dev/null
+++ b/be/lib/openzeppelin-contracts/lib/forge-std/README.md
@@ -0,0 +1,266 @@
+# Forge Standard Library โข [](https://github.com/foundry-rs/forge-std/actions/workflows/ci.yml)
+
+Forge Standard Library is a collection of helpful contracts and libraries for use with [Forge and Foundry](https://github.com/foundry-rs/foundry). It leverages Forge's cheatcodes to make writing tests easier and faster, while improving the UX of cheatcodes.
+
+**Learn how to use Forge-Std with the [๐ Foundry Book (Forge-Std Guide)](https://book.getfoundry.sh/forge/forge-std.html).**
+
+## Install
+
+```bash
+forge install foundry-rs/forge-std
+```
+
+## Contracts
+### stdError
+
+This is a helper contract for errors and reverts. In Forge, this contract is particularly helpful for the `expectRevert` cheatcode, as it provides all compiler builtin errors.
+
+See the contract itself for all error codes.
+
+#### Example usage
+
+```solidity
+
+import "forge-std/Test.sol";
+
+contract TestContract is Test {
+ ErrorsTest test;
+
+ function setUp() public {
+ test = new ErrorsTest();
+ }
+
+ function testExpectArithmetic() public {
+ vm.expectRevert(stdError.arithmeticError);
+ test.arithmeticError(10);
+ }
+}
+
+contract ErrorsTest {
+ function arithmeticError(uint256 a) public {
+ a = a - 100;
+ }
+}
+```
+
+### stdStorage
+
+This is a rather large contract due to all of the overloading to make the UX decent. Primarily, it is a wrapper around the `record` and `accesses` cheatcodes. It can *always* find and write the storage slot(s) associated with a particular variable without knowing the storage layout. The one _major_ caveat to this is while a slot can be found for packed storage variables, we can't write to that variable safely. If a user tries to write to a packed slot, the execution throws an error, unless it is uninitialized (`bytes32(0)`).
+
+This works by recording all `SLOAD`s and `SSTORE`s during a function call. If there is a single slot read or written to, it immediately returns the slot. Otherwise, behind the scenes, we iterate through and check each one (assuming the user passed in a `depth` parameter). If the variable is a struct, you can pass in a `depth` parameter which is basically the field depth.
+
+I.e.:
+```solidity
+struct T {
+ // depth 0
+ uint256 a;
+ // depth 1
+ uint256 b;
+}
+```
+
+#### Example usage
+
+```solidity
+import "forge-std/Test.sol";
+
+contract TestContract is Test {
+ using stdStorage for StdStorage;
+
+ Storage test;
+
+ function setUp() public {
+ test = new Storage();
+ }
+
+ function testFindExists() public {
+ // Lets say we want to find the slot for the public
+ // variable `exists`. We just pass in the function selector
+ // to the `find` command
+ uint256 slot = stdstore.target(address(test)).sig("exists()").find();
+ assertEq(slot, 0);
+ }
+
+ function testWriteExists() public {
+ // Lets say we want to write to the slot for the public
+ // variable `exists`. We just pass in the function selector
+ // to the `checked_write` command
+ stdstore.target(address(test)).sig("exists()").checked_write(100);
+ assertEq(test.exists(), 100);
+ }
+
+ // It supports arbitrary storage layouts, like assembly based storage locations
+ function testFindHidden() public {
+ // `hidden` is a random hash of a bytes, iteration through slots would
+ // not find it. Our mechanism does
+ // Also, you can use the selector instead of a string
+ uint256 slot = stdstore.target(address(test)).sig(test.hidden.selector).find();
+ assertEq(slot, uint256(keccak256("my.random.var")));
+ }
+
+ // If targeting a mapping, you have to pass in the keys necessary to perform the find
+ // i.e.:
+ function testFindMapping() public {
+ uint256 slot = stdstore
+ .target(address(test))
+ .sig(test.map_addr.selector)
+ .with_key(address(this))
+ .find();
+ // in the `Storage` constructor, we wrote that this address' value was 1 in the map
+ // so when we load the slot, we expect it to be 1
+ assertEq(uint(vm.load(address(test), bytes32(slot))), 1);
+ }
+
+ // If the target is a struct, you can specify the field depth:
+ function testFindStruct() public {
+ // NOTE: see the depth parameter - 0 means 0th field, 1 means 1st field, etc.
+ uint256 slot_for_a_field = stdstore
+ .target(address(test))
+ .sig(test.basicStruct.selector)
+ .depth(0)
+ .find();
+
+ uint256 slot_for_b_field = stdstore
+ .target(address(test))
+ .sig(test.basicStruct.selector)
+ .depth(1)
+ .find();
+
+ assertEq(uint(vm.load(address(test), bytes32(slot_for_a_field))), 1);
+ assertEq(uint(vm.load(address(test), bytes32(slot_for_b_field))), 2);
+ }
+}
+
+// A complex storage contract
+contract Storage {
+ struct UnpackedStruct {
+ uint256 a;
+ uint256 b;
+ }
+
+ constructor() {
+ map_addr[msg.sender] = 1;
+ }
+
+ uint256 public exists = 1;
+ mapping(address => uint256) public map_addr;
+ // mapping(address => Packed) public map_packed;
+ mapping(address => UnpackedStruct) public map_struct;
+ mapping(address => mapping(address => uint256)) public deep_map;
+ mapping(address => mapping(address => UnpackedStruct)) public deep_map_struct;
+ UnpackedStruct public basicStruct = UnpackedStruct({
+ a: 1,
+ b: 2
+ });
+
+ function hidden() public view returns (bytes32 t) {
+ // an extremely hidden storage slot
+ bytes32 slot = keccak256("my.random.var");
+ assembly {
+ t := sload(slot)
+ }
+ }
+}
+```
+
+### stdCheats
+
+This is a wrapper over miscellaneous cheatcodes that need wrappers to be more dev friendly. Currently there are only functions related to `prank`. In general, users may expect ETH to be put into an address on `prank`, but this is not the case for safety reasons. Explicitly this `hoax` function should only be used for addresses that have expected balances as it will get overwritten. If an address already has ETH, you should just use `prank`. If you want to change that balance explicitly, just use `deal`. If you want to do both, `hoax` is also right for you.
+
+
+#### Example usage:
+```solidity
+
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.0;
+
+import "forge-std/Test.sol";
+
+// Inherit the stdCheats
+contract StdCheatsTest is Test {
+ Bar test;
+ function setUp() public {
+ test = new Bar();
+ }
+
+ function testHoax() public {
+ // we call `hoax`, which gives the target address
+ // eth and then calls `prank`
+ hoax(address(1337));
+ test.bar{value: 100}(address(1337));
+
+ // overloaded to allow you to specify how much eth to
+ // initialize the address with
+ hoax(address(1337), 1);
+ test.bar{value: 1}(address(1337));
+ }
+
+ function testStartHoax() public {
+ // we call `startHoax`, which gives the target address
+ // eth and then calls `startPrank`
+ //
+ // it is also overloaded so that you can specify an eth amount
+ startHoax(address(1337));
+ test.bar{value: 100}(address(1337));
+ test.bar{value: 100}(address(1337));
+ vm.stopPrank();
+ test.bar(address(this));
+ }
+}
+
+contract Bar {
+ function bar(address expectedSender) public payable {
+ require(msg.sender == expectedSender, "!prank");
+ }
+}
+```
+
+### Std Assertions
+
+Contains various assertions.
+
+### `console.log`
+
+Usage follows the same format as [Hardhat](https://hardhat.org/hardhat-network/reference/#console-log).
+It's recommended to use `console2.sol` as shown below, as this will show the decoded logs in Forge traces.
+
+```solidity
+// import it indirectly via Test.sol
+import "forge-std/Test.sol";
+// or directly import it
+import "forge-std/console2.sol";
+...
+console2.log(someValue);
+```
+
+If you need compatibility with Hardhat, you must use the standard `console.sol` instead.
+Due to a bug in `console.sol`, logs that use `uint256` or `int256` types will not be properly decoded in Forge traces.
+
+```solidity
+// import it indirectly via Test.sol
+import "forge-std/Test.sol";
+// or directly import it
+import "forge-std/console.sol";
+...
+console.log(someValue);
+```
+
+## Contributing
+
+See our [contributing guidelines](./CONTRIBUTING.md).
+
+## Getting Help
+
+First, see if the answer to your question can be found in [book](https://book.getfoundry.sh).
+
+If the answer is not there:
+
+- Join the [support Telegram](https://t.me/foundry_support) to get help, or
+- Open a [discussion](https://github.com/foundry-rs/foundry/discussions/new/choose) with your question, or
+- Open an issue with [the bug](https://github.com/foundry-rs/foundry/issues/new/choose)
+
+If you want to contribute, or follow along with contributor discussion, you can use our [main telegram](https://t.me/foundry_rs) to chat with us about the development of Foundry!
+
+## License
+
+Forge Standard Library is offered under either [MIT](LICENSE-MIT) or [Apache 2.0](LICENSE-APACHE) license.
diff --git a/be/lib/openzeppelin-contracts/lib/halmos-cheatcodes/README.md b/be/lib/openzeppelin-contracts/lib/halmos-cheatcodes/README.md
new file mode 100644
index 0000000..209c2cf
--- /dev/null
+++ b/be/lib/openzeppelin-contracts/lib/halmos-cheatcodes/README.md
@@ -0,0 +1,97 @@
+# Halmos Cheat Codes
+
+Halmos cheatcodes are abstract functions designed to facilitate writing symbolic tests, such as the creation of new symbolic values at runtime. While these cheatcodes are currently exclusive to [Halmos][halmos], they are not limited to it and could potentially be supported by other symbolic testing tools in the future.
+
+Please refer to [the list of currently available cheatcodes][list]. More cheatcodes will be added in the future.
+
+Join the [Halmos Telegram Group][chat] for any inquiries or further discussions.
+
+[halmos]:
+[list]:
+[chat]:
+
+## Installation
+
+To install using Foundry:
+```
+forge install a16z/halmos-cheatcodes
+```
+Alternatively, you can directly add it as a submodule:
+```
+git submodule add https://github.com/a16z/halmos-cheatcodes
+```
+
+## Example usage
+
+Below is an example of a symbolic test that checks for potential unauthorized access to others' tokens. The approach involves setting up an initial symbolic state of the token contract, executing an arbitrary function call to the token contract, and checking if there is an execution path that increases the caller's balance and/or decreases the balance of others. This example illustrates how to utilize cheatcodes to set up initial symbolic states and execute arbitrary function calls.
+
+```solidity
+// import Halmos cheatcodes
+import {SymTest} from "halmos-cheatcodes/SymTest.sol";
+
+import {Test} from "forge-std/Test.sol";
+
+import {Token} from "/path/to/Token.sol";
+
+contract TokenTest is SymTest, Test {
+ Token token;
+
+ function setUp() public {
+ token = new Token();
+
+ // set the balances of three arbitrary accounts to arbitrary symbolic values
+ for (uint256 i = 0; i < 3; i++) {
+ address receiver = svm.createAddress('receiver'); // create a new symbolic address
+ uint256 amount = svm.createUint256('amount'); // create a new symbolic uint256 value
+ token.transfer(receiver, amount);
+ }
+ }
+
+ function checkBalanceUpdate() public {
+ // consider two arbitrary distinct accounts
+ address caller = svm.createAddress('caller'); // create a symbolic address
+ address others = svm.createAddress('others'); // create another symbolic address
+ vm.assume(others != caller); // assume the two addresses are different
+
+ // record their current balances
+ uint256 oldBalanceCaller = token.balanceOf(caller);
+ uint256 oldBalanceOthers = token.balanceOf(others);
+
+ // execute an arbitrary function call to the token from the caller
+ vm.prank(caller);
+ uint256 dataSize = 100; // the max calldata size for the public functions in the token
+ bytes memory data = svm.createBytes(dataSize, 'data'); // create a symbolic calldata
+ address(token).call(data);
+
+ // ensure that the caller cannot spend others' tokens
+ assert(token.balanceOf(caller) <= oldBalanceCaller); // cannot increase their own balance
+ assert(token.balanceOf(others) >= oldBalanceOthers); // cannot decrease others' balance
+ }
+}
+```
+
+When running the above test against the following buggy token contract, Halmos will provide a counterexample that may be overlooked during manual reviews.
+
+```solidity
+/// @notice This is a buggy token contract. DO NOT use it in production.
+contract Token {
+ mapping(address => uint) public balanceOf;
+
+ constructor() public {
+ balanceOf[msg.sender] = 1e27;
+ }
+
+ function transfer(address to, uint amount) public {
+ _transfer(msg.sender, to, amount);
+ }
+
+ function _transfer(address from, address to, uint amount) public {
+ balanceOf[from] -= amount;
+ balanceOf[to] += amount;
+ }
+}
+```
+
+## Disclaimer
+
+_These smart contracts and code are being provided as is. No guarantee, representation or warranty is being made, express or implied, as to the safety or correctness of the user interface or the smart contracts and code. They have not been audited and as such there can be no assurance they will work as intended, and users may experience delays, failures, errors, omissions or loss of transmitted information. THE SMART CONTRACTS AND CODE CONTAINED HEREIN ARE FURNISHED AS IS, WHERE IS, WITH ALL FAULTS AND WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING ANY WARRANTY OF MERCHANTABILITY, NON-INFRINGEMENT OR FITNESS FOR ANY PARTICULAR PURPOSE. Further, use of any of these smart contracts and code may be restricted or prohibited under applicable law, including securities laws, and it is therefore strongly advised for you to contact a reputable attorney in any jurisdiction where these smart contracts and code may be accessible for any questions or concerns with respect thereto. Further, no information provided in this repo should be construed as investment advice or legal advice for any particular facts or circumstances, and is not meant to replace competent counsel. a16z is not liable for any use of the foregoing, and users should proceed with caution and use at their own risk. See a16z.com/disclosures for more info._
diff --git a/be/lib/openzeppelin-contracts/scripts/upgradeable/README.md b/be/lib/openzeppelin-contracts/scripts/upgradeable/README.md
new file mode 100644
index 0000000..2309f9e
--- /dev/null
+++ b/be/lib/openzeppelin-contracts/scripts/upgradeable/README.md
@@ -0,0 +1,21 @@
+The upgradeable variant of OpenZeppelin Contracts is automatically generated from the original Solidity code. We call this process "transpilation" and it is implemented by our [Upgradeability Transpiler](https://github.com/OpenZeppelin/openzeppelin-transpiler/).
+
+When the `master` branch or `release-v*` branches are updated, the code is transpiled and pushed to [OpenZeppelin/openzeppelin-contracts-upgradeable](https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable) by the `upgradeable.yml` workflow.
+
+## `transpile.sh`
+
+Applies patches and invokes the transpiler with the command line flags we need for our requirements (for example, excluding certain files).
+
+## `transpile-onto.sh`
+
+```
+bash scripts/upgradeable/transpile-onto.sh []
+```
+
+Transpiles the contents of the current git branch and commits the result as a new commit on branch ``. If branch `` doesn't exist, it will copy the commit history of `[]` (this is used in GitHub Actions, but is usually not necessary locally).
+
+## `patch-apply.sh` & `patch-save.sh`
+
+Some of the upgradeable contract variants require ad-hoc changes that are not implemented by the transpiler. These changes are implemented by patches stored in `upgradeable.patch` in this directory. `patch-apply.sh` applies these patches.
+
+If the patches fail to apply due to changes in the repo, the conflicts have to be resolved manually. Once fixed, `patch-save.sh` will take the changes staged in Git and update `upgradeable.patch` to match.
diff --git a/fe/app/_components/footer.tsx b/fe/app/_components/footer.tsx
index b15ac8f..1ef79d4 100644
--- a/fe/app/_components/footer.tsx
+++ b/fe/app/_components/footer.tsx
@@ -7,13 +7,15 @@ const ADMIN_LINK = process.env.ADMIN_LINK ?? "https://github.com/SiegfriedBz";
export const Footer: FC = () => {
return (
-