Skip to content

Commit 463fee1

Browse files
committed
✨ Complete Base Learn Solutions - All 13 Exercises
Battle-tested smart contracts for earning all Base Learn NFTs! Features: - 13 working smart contract solutions - Verified on Base Sepolia testnet - Clean, documented code - Easy deployment scripts - Comprehensive README Successfully earns: - 13 Soulbound NFTs - Guild.xyz roles (Newcomer → Supreme) - 13 TalentProtocol points Ready to deploy and earn your NFTs! 🚀
0 parents  commit 463fee1

22 files changed

Lines changed: 10245 additions & 0 deletions

File tree

.env.example

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Private key for deploying contracts (DO NOT COMMIT REAL KEYS!)
2+
PRIVATE_KEY=your_private_key_here
3+
4+
# RPC URLs
5+
BASE_SEPOLIA_RPC=https://sepolia.base.org
6+
SEPOLIA_RPC=https://rpc.sepolia.org
7+
8+
# API Keys for contract verification
9+
BASESCAN_API_KEY=your_basescan_api_key
10+
ETHERSCAN_API_KEY=your_etherscan_api_key
11+
12+
# Gas reporting (optional)
13+
REPORT_GAS=false
14+
COINMARKETCAP_API_KEY=your_coinmarketcap_api_key
15+
16+
# Base Learn Platform credentials (if needed)
17+
BASE_LEARN_WALLET=your_wallet_address

.gitignore

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Dependencies
2+
node_modules/
3+
.pnp
4+
.pnp.js
5+
6+
# Testing
7+
coverage/
8+
coverage.json
9+
10+
# Production
11+
build/
12+
dist/
13+
14+
# Hardhat
15+
artifacts/
16+
cache/
17+
typechain-types/
18+
19+
# Environment variables
20+
.env
21+
.env.local
22+
.env.development.local
23+
.env.test.local
24+
.env.production.local
25+
26+
# IDE
27+
.vscode/
28+
.idea/
29+
*.swp
30+
*.swo
31+
*~
32+
.DS_Store
33+
34+
# Logs
35+
npm-debug.log*
36+
yarn-debug.log*
37+
yarn-error.log*
38+
39+
# Deployments (keep structure but not addresses)
40+
deployments/*/*
41+
!deployments/*/
42+
43+
# Misc
44+
.openzeppelin/
45+
.defender/
46+
*.log
47+
temp/
48+
tmp/

README.md

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
# Base Learn Solutions 🎓
2+
3+
Complete, working smart contract solutions for all 13 Base Learn exercises. Earn your NFTs and unlock Guild.xyz roles! 🏆
4+
5+
## 🚀 Overview
6+
7+
This repository contains battle-tested smart contracts that successfully pass all Base Learn validations. Each contract has been deployed and verified to mint the corresponding NFT on Base Sepolia testnet.
8+
9+
### What you'll earn:
10+
-**13 Soulbound NFTs** - Proof of your smart contract mastery
11+
- 🏅 **Guild.xyz Roles** - Newcomer, Acolyte, Consul, Prefect, Supreme
12+
- 💎 **13 TalentProtocol Points** - Build your on-chain reputation
13+
14+
## 📋 Prerequisites
15+
16+
- Node.js v18+ and npm
17+
- MetaMask or Coinbase Wallet
18+
- Base Sepolia ETH (get from [faucet](https://www.coinbase.com/faucets/base-ethereum-goerli-faucet))
19+
- Basic understanding of Solidity and smart contracts
20+
21+
## 🛠 Installation
22+
23+
```bash
24+
# Clone the repository
25+
git clone https://github.com/YOUR_USERNAME/base-learn-solutions.git
26+
cd base-learn-solutions
27+
28+
# Install dependencies
29+
npm install
30+
31+
# Set up environment variables
32+
cp .env.example .env
33+
# Edit .env and add your private key (NEVER commit this!)
34+
```
35+
36+
## 📁 Contract Solutions
37+
38+
Each exercise is in its own directory with the exact contract name Base Learn expects:
39+
40+
| Exercise | Contract | Description |
41+
|----------|----------|-------------|
42+
| 01 | `BasicMath.sol` | Overflow-safe arithmetic operations |
43+
| 02 | `ControlStructures.sol` | FizzBuzz and time-based logic |
44+
| 03 | `EmployeeStorage.sol` | Optimized storage patterns |
45+
| 04 | `FavoriteRecords.sol` | Array manipulation |
46+
| 05 | `FavoriteRecords.sol` | Mapping operations |
47+
| 06 | `InheritanceContracts.sol` | Contract inheritance patterns |
48+
| 07 | `GarageManager.sol` | Struct management |
49+
| 08 | `ErrorTriageExercise.sol` | Error handling and debugging |
50+
| 09 | `AddressBookFactory.sol` | Factory pattern with `new` keyword |
51+
| 10 | `ImportsExercise.sol` | Library imports and usage |
52+
| 11 | `HaikuNFT.sol` | ERC-721 NFT implementation |
53+
| 12 | `UnburnableToken.sol` | Minimal token implementation |
54+
| 13 | `WeightedVoting.sol` | ERC-20 governance token |
55+
56+
## 🚀 Deployment Guide
57+
58+
### Deploy All Contracts
59+
60+
```bash
61+
# Compile all contracts
62+
npx hardhat compile
63+
64+
# Deploy to Base Sepolia
65+
npx hardhat run scripts/deploy-all.ts --network baseSepolia
66+
```
67+
68+
### Deploy Individual Contracts
69+
70+
```bash
71+
# Deploy specific exercise (replace XX with exercise number)
72+
npx hardhat run scripts/deploy-XX.ts --network baseSepolia
73+
```
74+
75+
## ✅ Submission Process
76+
77+
1. **Deploy your contracts** to Base Sepolia testnet
78+
2. **Copy the deployed contract address** from the terminal
79+
3. **Visit [Base Learn](https://docs.base.org/base-learn/docs/welcome)**
80+
4. **Navigate to the exercise** you want to submit
81+
5. **Paste your contract address** and click submit
82+
6. **Mint your NFT** after successful validation
83+
84+
## 🔑 Important Notes
85+
86+
### Security
87+
- **NEVER** commit your `.env` file or private keys
88+
- Use a dedicated wallet for testnet deployments
89+
- Keep your private keys secure
90+
91+
### Validation Tips
92+
- Base Learn expects **exact** function signatures
93+
- Don't modify function names or parameters
94+
- Some exercises require specific Solidity versions
95+
- If validation fails, check gas estimation errors
96+
97+
### Common Issues
98+
- **"Unable to estimate network fee"** - Contract validation failed
99+
- **"Transaction underpriced"** - Wait for pending transactions to clear
100+
- **Validation failures** - Ensure exact function signatures match
101+
102+
## 📚 Resources
103+
104+
- [Base Learn Platform](https://docs.base.org/base-learn/docs/welcome)
105+
- [Base Documentation](https://docs.base.org/)
106+
- [Base Sepolia Faucet](https://www.coinbase.com/faucets/base-ethereum-goerli-faucet)
107+
- [Base Sepolia Explorer](https://sepolia.basescan.org)
108+
- [Guild.xyz Base Learn](https://guild.xyz/base-learn)
109+
110+
## 🤝 Contributing
111+
112+
Found an issue or have an improvement? Contributions are welcome!
113+
114+
1. Fork the repository
115+
2. Create your feature branch (`git checkout -b feature/improvement`)
116+
3. Commit your changes (`git commit -m 'Add improvement'`)
117+
4. Push to the branch (`git push origin feature/improvement`)
118+
5. Open a Pull Request
119+
120+
## 📜 License
121+
122+
MIT License - feel free to use these solutions to complete Base Learn!
123+
124+
## 🙏 Acknowledgments
125+
126+
- Base Learn team for creating this educational platform
127+
- OpenZeppelin for secure contract libraries
128+
- The Base ecosystem community
129+
130+
---
131+
132+
**⚡ Ready to become a Base Learn graduate?** Deploy these contracts and earn your NFTs!
133+
134+
Remember: Learning by doing is the best way to master smart contracts. Use these solutions to understand the patterns, then try building your own variations! 🚀
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.17;
3+
4+
contract BasicMath {
5+
function adder(uint256 _a, uint256 _b) external pure returns (uint256 sum, bool error) {
6+
unchecked {
7+
sum = _a + _b;
8+
if (sum < _a || sum < _b) {
9+
return (0, true);
10+
}
11+
return (sum, false);
12+
}
13+
}
14+
15+
function subtractor(uint256 _a, uint256 _b) external pure returns (uint256 difference, bool error) {
16+
if (_b > _a) {
17+
return (0, true);
18+
}
19+
return (_a - _b, false);
20+
}
21+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.17;
3+
4+
contract ControlStructures {
5+
error AfterHours(uint256 time);
6+
7+
function fizzBuzz(uint256 _number) public pure returns (string memory response) {
8+
if (_number % 3 == 0 && _number % 5 == 0) {
9+
return "FizzBuzz";
10+
} else if (_number % 3 == 0) {
11+
return "Fizz";
12+
} else if (_number % 5 == 0) {
13+
return "Buzz";
14+
} else {
15+
return "Splat";
16+
}
17+
}
18+
19+
function doNotDisturb(uint256 _time) public pure returns (string memory result) {
20+
assert(_time < 2400);
21+
22+
if (_time > 2200 || _time < 800) {
23+
revert AfterHours(_time);
24+
} else if (_time >= 1200 && _time <= 1299) {
25+
revert("At lunch!");
26+
} else if (_time >= 800 && _time <= 1199) {
27+
return "Morning!";
28+
} else if (_time >= 1300 && _time <= 1799) {
29+
return "Afternoon!";
30+
} else if (_time >= 1800 && _time <= 2200) {
31+
return "Evening!";
32+
}
33+
}
34+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.17;
3+
4+
contract EmployeeStorage {
5+
uint16 private shares;
6+
uint32 private salary;
7+
uint256 public idNumber;
8+
string public name;
9+
10+
constructor(uint16 _shares, string memory _name, uint32 _salary, uint _idNumber) {
11+
shares = _shares;
12+
name = _name;
13+
salary = _salary;
14+
idNumber = _idNumber;
15+
}
16+
17+
function viewShares() public view returns (uint16) {
18+
return shares;
19+
}
20+
21+
function viewSalary() public view returns (uint32) {
22+
return salary;
23+
}
24+
25+
error TooManyShares(uint16 _shares);
26+
27+
function grantShares(uint16 _newShares) public {
28+
if (_newShares > 5000) {
29+
revert("Too many shares");
30+
} else if (shares + _newShares > 5000) {
31+
revert TooManyShares(shares + _newShares);
32+
}
33+
shares += _newShares;
34+
}
35+
36+
function checkForPacking(uint _slot) public view returns (uint r) {
37+
assembly {
38+
r := sload (_slot)
39+
}
40+
}
41+
42+
function debugResetShares() public {
43+
shares = 1000;
44+
}
45+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.17;
3+
4+
contract FavoriteRecords {
5+
mapping(string => bool) private approvedRecords;
6+
string[] private approvedRecordsIndex;
7+
8+
mapping(address => mapping(string => bool)) public userFavorites;
9+
mapping(address => string[]) private userFavoritesIndex;
10+
11+
error NotApproved(string albumName);
12+
13+
constructor() {
14+
approvedRecordsIndex = [
15+
"Thriller",
16+
"Back in Black",
17+
"The Bodyguard",
18+
"The Dark Side of the Moon",
19+
"Their Greatest Hits (1971-1975)",
20+
"Hotel California",
21+
"Come On Over",
22+
"Rumours",
23+
"Saturday Night Fever"
24+
];
25+
26+
for (uint i = 0; i < approvedRecordsIndex.length; i++) {
27+
approvedRecords[approvedRecordsIndex[i]] = true;
28+
}
29+
}
30+
31+
function getApprovedRecords() public view returns (string[] memory) {
32+
return approvedRecordsIndex;
33+
}
34+
35+
function addRecord(string memory _albumName) public {
36+
if (!approvedRecords[_albumName]) {
37+
revert NotApproved({albumName: _albumName});
38+
}
39+
40+
if (!userFavorites[msg.sender][_albumName]) {
41+
userFavorites[msg.sender][_albumName] = true;
42+
userFavoritesIndex[msg.sender].push(_albumName);
43+
}
44+
}
45+
46+
function getUserFavorites(address _address) public view returns (string[] memory) {
47+
return userFavoritesIndex[_address];
48+
}
49+
50+
function resetUserFavorites() public {
51+
for (uint i = 0; i < userFavoritesIndex[msg.sender].length; i++) {
52+
string memory albumName = userFavoritesIndex[msg.sender][i];
53+
userFavorites[msg.sender][albumName] = false;
54+
}
55+
delete userFavoritesIndex[msg.sender];
56+
}
57+
}

0 commit comments

Comments
 (0)