# W04: Create Your DAO -- On-Chain Presentation Voting

## Workshop Overview
- **Duration**: 30-45 minutes
- **Difficulty**: Intermediate (builds on W01)
- **Network**: Sepolia Testnet
- **Tools**: MetaMask, Remix IDE (remix.ethereum.org)

## Prerequisites
- [ ] MetaMask installed with Sepolia ETH
- [ ] Completed W01 (Deploy Your First Smart Contract)

---

## Part 1: Understanding the Contract (5 min)

> **Discovery Question:** What stops someone from voting twice in a normal election? How would you enforce this without a human poll worker?

### Read the Contract
1. Open `contracts/PresentationVoting.sol` and read through it
2. Identify the key components:
   - **State variables**: `owner`, `presentationCount`, `presentations` mapping
   - **Access control**: `onlyOwner` modifier on `addPresentation()`
   - **Vote tracking**: Nested mapping `hasVoted[address][presentationId]`
   - **Events**: `PresentationAdded`, `VoteCast`

### Key Concepts
- **Struct**: Groups related data (title, presenter, voteCount, exists) into one type
- **Nested mapping**: `mapping(address => mapping(uint256 => bool))` tracks per-address, per-presentation voting status
- **require()**: Reverts the transaction if the condition is false -- this is how the contract prevents double voting

### Checkpoint: Reflect
- What surprised you in this section?
- What question do you still have?

---

## Part 2: Deploy the Contract (5 min)

> **Discovery Question:** Predict: What will MetaMask show when you deploy? Will there be constructor arguments?

1. Open Remix IDE (remix.ethereum.org)
2. Create new file: `PresentationVoting.sol`
3. Paste the contract code from `contracts/PresentationVoting.sol`
4. Select compiler `0.8.20`, compile
5. Switch to "Deploy & Run" tab
6. Set environment: **"Injected Provider - MetaMask"**
7. Ensure **Sepolia** network is selected in MetaMask
8. Click **Deploy** (no constructor arguments needed!)
9. Confirm in MetaMask
10. Copy the deployed contract address -- **share with the class**

### Checkpoint: Reflect
- Was your prediction about MetaMask correct?
- Why does the contract have no constructor arguments? (Hint: it reads `msg.sender` automatically)

---

## Part 3: Add Presentations (5 min -- instructor)

The instructor (contract owner) calls `addPresentation()` for each student presentation:

```
addPresentation("Bitcoin Mining Economics", "Alice")
addPresentation("DeFi Lending Protocols", "Bob")
addPresentation("NFT Marketplaces", "Carol")
```

### Verify
- Students call `getPresentationCount()` to confirm the number
- Students call `getPresentation(0)` to see the first entry
- Check events on Sepolia Etherscan

> **Discovery Question:** Why can only the owner add presentations? What would happen if anyone could?

### Checkpoint: Reflect
- What surprised you in this section?
- What question do you still have?

---

## Part 4: Cast Your Votes (10 min)

1. In Remix, expand the deployed contract
2. Find the `vote()` function
3. Enter the `presentationId` you want to vote for (e.g., `0`)
4. Click **transact**, confirm in MetaMask
5. Wait for confirmation
6. **Try voting for the same presentation again -- observe the revert!**

### What to Observe
- MetaMask pops up for `vote()` (state change = costs gas)
- MetaMask does NOT pop up for `getPresentation()` (view = free)
- The revert message says "You have already voted for this presentation"

> **Discovery Question:** What happens in the EVM when `require()` fails? Does the voter still pay gas?

### Checkpoint: Reflect
- What surprised you in this section?
- Try calling `hasUserVoted(0, YOUR_ADDRESS)` -- what does it return?

---

## Part 5: Read Results (5 min)

1. Call `getPresentation(0)`, `getPresentation(1)`, etc.
2. Record vote counts for each presentation
3. Compare with class expectations

### Verify on Etherscan
1. Go to [sepolia.etherscan.io](https://sepolia.etherscan.io)
2. Paste the contract address
3. Click "Events" tab
4. Find every `VoteCast` event -- each shows the voter and presentation ID

> **Discovery Question:** Can the owner change the results after voting? Look at the contract code -- is there any function that modifies `voteCount` directly?

### Checkpoint: Reflect
- What surprised you in this section?
- What question do you still have?

---

## Part 6: Bonus Challenge (optional, 10 min)

### Deploy the Extended Contract
1. Create a new file in Remix: `PresentationVoting_Extended.sol`
2. Paste the code from `contracts/PresentationVoting_Extended.sol`
3. Compile and deploy to Sepolia
4. Add presentations (as owner)

### Test the Rating System
1. Call `ratePresentation(0, 4)` to give 4 stars
2. Call `ratePresentation(0, 5)` from a different account (or ask a classmate)
3. Call `getAverageRating(0)` -- should return `450` (meaning 4.50 average)
4. Try rating with `0` or `6` -- observe the revert

### Compare Approaches
- **Voting** (base contract): Binary approval -- did you like it or not?
- **Rating** (extended): Spectrum feedback -- how much did you like it?
- **Discussion**: Which gives better signal? When would you use each?

### Close Voting
1. As owner, call `closeVoting()`
2. Try to vote after closing -- observe the revert
3. Read results still work (view functions are unaffected)

---

## Reflection Questions

1. What are the advantages of on-chain voting vs Google Forms?
2. What is the Sybil attack, and how do real DAOs address it?
3. How would you add a voting deadline to this contract?
4. Why is transparency both a strength and limitation of on-chain voting?
5. How does this contract compare to real DAO governance (Uniswap, Compound)?

---

## Important Note

> The companion notebook (`W04_Create_Your_DAO.ipynb`) demonstrates **token-weighted voting** (1 token = 1 vote), while this workshop uses **1-address-1-vote** for simplicity. Real DAOs often combine both approaches.

---

## Deliverables

Submit the following to complete this workshop:

1. **Contract Address:** Your deployed PresentationVoting contract address on Sepolia
   - Format: `0x` followed by 40 hexadecimal characters
2. **Screenshot:** Etherscan page showing VoteCast events
3. **Reflection:** One paragraph: What did on-chain voting teach you about trustless coordination?

---

## Troubleshooting

| Problem | Solution |
|---------|----------|
| "Execution reverted" | You already voted, or presentation ID doesn't exist |
| "Only the owner can call this function" | You are not the deployer -- only the instructor can add presentations |
| Transaction stuck | Try increasing gas limit in MetaMask |
| Wrong network | Ensure MetaMask shows Sepolia, not mainnet |
| Need Sepolia ETH | Use faucets at cloud.google.com/application/web3/faucet, sepoliafaucet.com, or infura.io/faucet |
| Compilation errors | Check compiler version is 0.8.20, check for missing semicolons |

---

## Congratulations!

You just built and used a DAO voting system on Ethereum. The same primitives -- proposals, voting, access control, transparency -- power organizations governing billions of dollars in DeFi.

**Next:** Explore the W04 companion notebook for token-weighted governance.
