📁 Estructura del projecte
docs/ ├── index.md ├── 01-introduccio.md ├── 02-sintaxi-basica.md ├── 03-funcions-modificadors.md ├── 04-herencia-interficies.md ├── 05-events-error-handling.md ├── 06-entorns-desenvolupament.md ├── 07-desplegament-testnet.md ├── 08-bones-practiques-seguretat.md ├── exercicis/ │ ├── ex01-votacio.md │ ├── ex02-marketplace-nft.md │ ├── ex03-crowdfunding.md │ └── col-leccio-exercicis.md ├── avaluacio/ │ ├── rubrica.md │ └── bones-practiques-finals.md └── recursos.md mkdocs.yml
📁 Estructura del projecte
docs/ ├── index.md ├── 01-introduccio.md ├── 02-sintaxi-basica.md ├── 03-funcions-modificadors.md ├── 04-herencia-interficies.md ├── 05-events-error-handling.md ├── 06-entorns-desenvolupament.md ├── 07-desplegament-testnet.md ├── 08-bones-practiques-seguretat.md ├── exercicis/ │ ├── ex01-votacio.md │ ├── ex02-marketplace-nft.md │ ├── ex03-crowdfunding.md │ └── col-leccio-exercicis.md ├── avaluacio/ │ ├── rubrica.md │ └── bones-practiques-finals.md └── recursos.md mkdocs.yml 📄 mkdocs.yml
site_name: "UD3: Desenvolupament de Smart Contracts" site_description: "Unitat Didàctica 3 – Curs de Blockchain. Disseny, implementació, desplegament i auditoria de smart contracts amb Solidity." site_author: "Curs de Blockchain" docs_dir: docs theme: name: material language: ca palette: - scheme: default primary: deep purple accent: indigo toggle: icon: material/brightness-7 name: Canvia a mode fosc - scheme: slate primary: deep purple accent: indigo toggle: icon: material/brightness-4 name: Canvia a mode clar features: - navigation.tabs - navigation.sections - navigation.expand - navigation.top - toc.integrate - search.suggest - search.highlight - content.code.copy - content.code.annotate markdown_extensions: - admonition - pymdownx.details - pymdownx.superfences - pymdownx.highlight: anchor_linenums: true - pymdownx.inlinehilite - pymdownx.tabbed: alternate_style: true - tables - attr_list - md_in_html nav: - Inici: index.md - Fonaments: - 1. Introducció als Smart Contracts: 01-introduccio.md - 2. Sintaxi Bàsica de Solidity: 02-sintaxi-basica.md - Programació Avançada: - 3. Funcions i Modificadors: 03-funcions-modificadors.md - 4. Herència i Interfícies: 04-herencia-interficies.md - 5. Events i Error Handling: 05-events-error-handling.md - Entorns i Eines: - 6. Entorns de Desenvolupament: 06-entorns-desenvolupament.md - 7. Desplegament en Testnet: 07-desplegament-testnet.md - Seguretat: - 8. Bones Pràctiques i Seguretat: 08-bones-practiques-seguretat.md - Exercicis: - Exercici 1 – Sistema de Votació: exercicis/ex01-votacio.md - Exercici 2 – Marketplace NFT: exercicis/ex02-marketplace-nft.md - Exercici 3 – Crowdfunding: exercicis/ex03-crowdfunding.md - Col·lecció d'Exercicis Proposats: exercicis/col-leccio-exercicis.md - Avaluació: - Rúbrica d'Avaluació: avaluacio/rubrica.md - Bones Pràctiques Finals: avaluacio/bones-practiques-finals.md - Recursos Addicionals: recursos.md 📄 docs/index.md
Unitat Didàctica 3: Desenvolupament de Smart Contracts Benvinguts a la tercera unitat didàctica del curs de blockchain.¶
Al llarg d'aquestes 24 hores de formació, aprendrem a dissenyar, implementar, desplegar i auditar smart contracts professionals utilitzant el llenguatge Solidity. Des dels fonaments teòrics fins als exercicis pràctics avançats, aquesta unitat cobreix tot el cicle de vida d'un contracte intel·ligent.
Resum de la Unitat¶
| 🎯 Resultat d'Aprenentatge | Desenvolupa smart contracts segurs i funcionals en entorns reals |
| ⏱️ Durada | 24 hores de contingut teòric, pràctic i exercicis guiats |
| 🛠️ Tecnologies | Solidity, Hardhat, Remix IDE, Sepolia Testnet, OpenZeppelin |
Índex de Continguts¶
Aquesta unitat s'estructura en blocs progressius, des dels conceptes bàsics fins als exercicis avançats. Cada bloc construeix sobre l'anterior per garantir una comprensió sòlida i aplicable. 1. Fonaments - Introducció als Smart Contracts - Sintaxi Bàsica de Solidity 2. Programació Avançada - Funcions i Modificadors - Herència i Interfícies - Events i Error Handling 3. Entorns i Eines - Remix IDE - Hardhat - Configuració de projecte professional 4. Desplegament - Sepolia Testnet - Verificació a Etherscan - Interacció amb contractes 5. Seguretat i Pràctica - Bones Pràctiques - Vulnerabilitats Comunes - Exercicis Guiats
📄 docs/01-introduccio.md
1. Introducció als Smart Contracts¶
Un smart contract és un programa auto-executable que s'executa en una blockchain quan es compleixen condicions predefinides. A diferència dels contractes tradicionals, que depenen d'intermediaris per fer-los complir, els smart contracts operen de manera autònoma i transparent sobre una xarxa distribuïda. Ethereum va ser la primera plataforma en popularitzar aquest concepte, i avui dia és l'estàndard de facto per al desenvolupament de contractes intel·ligents.
Propietats Fonamentals¶
| Propietat | Descripció |
|---|---|
| 🌐 Descentralitzats | S'executen simultàniament en tots els nodes de la xarxa. Cap entitat central pot aturar-los o modificar-los unilateralment. |
| 🔒 Immutables | Un cop desplegats a la blockchain, el codi no es pot modificar. Això garanteix que les regles del contracte es mantenen intactes. |
| 👁️ Transparents | El codi font és visible i verificable per qualsevol persona. La traçabilitat de les transaccions és pública i auditable. |
| ✅ Deterministes | Amb les mateixes entrades, sempre produeixen el mateix resultat, independentment del node que executi el contracte. |
El Llenguatge Solidity¶
Solidity és el llenguatge de programació més utilitzat per desenvolupar smart contracts a Ethereum i altres blockchains compatibles amb EVM (Ethereum Virtual Machine). Té una sintaxi similar a JavaScript i és estàticament tipat, cosa que ajuda a detectar errors en temps de compilació. El codi Solidity es compila a bytecode que l'EVM pot executar de forma determinista en qualsevol node de la xarxa.
===
"Característiques Principals" - Llenguatge d'alt nivell, orientat a objectes - Sintaxi similar a JavaScript - Estàticament tipat - Compilat a bytecode per a l'EVM
- Ethereum (xarxa principal)
- Polygon, Arbitrum, Optimism
- BNB Chain, Avalanche
- Qualsevol xarxa EVM-compatible
📄 docs/02-sintaxi-basica.md
2. Sintaxi Bàsica de Solidity ## 2.1 Estructura d'un Contracte Tot contracte Solidity segueix una estructura estandarditzada. Els elements obligatoris inclouen l'identificador de llicència SPDX, la directiva pragma que indica la versió del compilador, i la paraula clau contract que defineix el contracte. ```solidity // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; contract PrimerContract { // Variables d'estat (emmagatzemades a la blockchain) string public nom; uint256 public valor; // Constructor: s'executa UNA vegada en el desplegament constructor(string memory _nom, uint256 _valor) { nom = _nom; valor = _valor; } // Funció que modifica l'estat function actualitzarValor(uint256 _nouValor) public { valor = _nouValor; } // Funció que llegeix l'estat (view) function obtenirValor() public view returns (uint256) { return valor; } }¶
Elements Clau
SPDX-License-Identifier Identificador de llicència obligatori des de Solidity 0.6.8. Indica la llicència del codi (MIT, GPL, etc.). pragma solidity Especifica la versió del compilador. El símbol ^ indica compatibilitat amb versions menors. Variables d'estat S'emmagatzemen permanentment a la blockchain. Cada escriptura consumeix gas i és costosa. Constructor Funció especial que s'executa una sola vegada durant el desplegament. Inicialitza les variables d'estat. 2.2 Tipus de Dades
Solidity disposa d'un sistema de tipus ric que inclou tipus valor (copiats quan s'assignen) i tipus referència (passats per referència). Conèixer la diferència és essencial per evitar comportaments inesperats i optimitzar el consum de gas.
solidity bool public esValid = true; int256 public enterNegatiu = -100; uint256 public enterPositiu = 100; address public propietari = 0x71C7...; address payable public compte; bytes32 public hash; enum Estat { Pendent, Procesant, Completat }
solidity string public missatge = "Hola Blockchain"; uint256[] public numeros; // Array dinàmic uint256[5] public cincNumeros; // Array fix mapping(address => uint256) public saldos; struct Persona { string nom; uint256 edat; address wallet; }
--- ## 📄 docs/03-funcions-modificadors.md markdown # 3. Funcions i Modificadors Les funcions són el nucli de qualsevol smart contract. Solidity ofereix un sistema sofisticat de visibilitat, modificadors d'estat i modificadors personalitzats que permeten controlar amb precisió com i qui pot interactuar amb el contracte. ## 3.1 Visibilitat de Funcions | Visibilitat | Accessible des de | Notes | |---|---|---| | `public` | Dins i fora del contracte | Qualsevol caller | | `external` | Només des de fora | Més eficient per arrays grans | | `internal` | Aquest contracte i derivats | Com `protected` en OOP | | `private` | Exclusiu d'aquest contracte | Màxima restricció | ## 3.2 Modificadors d'Estat Els modificadors d'estat indiquen com una funció interacciona amb les variables de la blockchain. Una correcta declaració estalvia gas i millora la llegibilitat del codi.solidity contract ModificadorsEstat { uint256 public valor = 100; mapping(address => uint256) public saldos; // view: pot llegir estat però NO modificar-lo function obtenirValor() public view returns (uint256) { return valor; } // pure: no llegeix NI modifica estat function calcular(uint256 a, uint256 b) public pure returns (uint256) { return a + b; } // payable: pot rebre Ether function dipositar() public payable { require(msg.value > 0, "Ha d'enviar Ether"); saldos[msg.sender] += msg.value; } } view Llegeix variables d'estat però no les modifica No consumeix gas si es crida externament pure No accedeix a l'estat. Només opera amb paràmetres locals Ideal per càlculs matemàtics payable Permet que la funció rebi Ether en la transacció Essencial per contractes financers
3.3 Modificadors Personalitzats
Els modificadors personalitzats permeten reutilitzar lògica de validació de forma elegant. El símbol _; indica on s'executa el cos de la funció modificada.
contract ModificadorsPersonalitzats { address public propietari; bool public actiu = true; modifier nomesPropietari() { require(msg.sender == propietari, "No es el propietari"); ; // Executa la funció } modifier contracteActiu() { require(actiu, "Contracte no actiu"); ; } constructor() { propietari = msg.sender; } function desactivar() public nomesPropietari { actiu = false; } function incrementar() public contracteActiu { // Lògica protegida } } --- ##
📄 docs/04-herencia-interficies.md markdown # 4. Herència i Interfícies L'herència és un dels pilars de la programació orientada a objectes en Solidity. Permet reutilitzar codi, estendre funcionalitats i establir jerarquies de contractes. Combinada amb les interfícies, és la base dels estàndards com ERC20 i ERC721 que governen l'ecosistema blockchain. ## 4.1 Herència Simple i Múltiplesolidity // Contracte base contract Animal { string public nom; uint256 public edat; constructor(string memory _nom, uint256 _edat) { nom = _nom; edat = _edat; } function ferSo() public virtual returns (string memory) { return "..."; } } // Herència simple: Gos hereta d'Animal contract Gos is Animal { constructor(string memory _nom, uint256 _edat) Animal(_nom, _edat) {} // override sobreescriu la funció virtual del pare function ferSo() public pure override returns (string memory) { return "Bord!"; } }
4.2 Interfícies i Estàndard ERC20
Les interfícies defineixen un contracte de funcions sense implementació. Qualsevol contracte que implementi una interfície ha de proporcionar totes les funcions declarades. L'estàndard IERC20 és la interfície més important de l'ecosistema Ethereum:
- name() — Nom del token
- symbol() — Símbol del token
- decimals() — Nombre de decimals
- totalSupply() — Subministrament total
- balanceOf(address) — Saldo d'una adreça
- transfer(to, amount) — Transferir tokens
- approve(spender, amount) — Autoritzar despesa
- transferFrom(from, to, amount) — Transferir en nom d'altri
- Transfer(from, to, value) — Emès en cada transferència
- Approval(owner, spender, value) — Emès en autoritzar
Bon consell
Utilitza sempre les implementacions auditades d'OpenZeppelin per als estàndards ERC20, ERC721 i ERC1155. Evita reimplementar-los des de zero per reduir el risc de vulnerabilitats.
--- ## 📄 docs/05-events-error-handling.md markdown # 5. Events i Error Handling Els events i el tractament d'errors són elements fonamentals per construir smart contracts robustos i interoperables amb aplicacions descentralitzades (DApps). Un bon disseny d'events permet que les DApps reaccionin als canvis d'estat de la blockchain en temps real. ## 5.1 Events Els events registren informació a la blockchain en un log especial que és molt més barat que emmagatzemar dades a les variables d'estat. Les DApps poden subscriure's a aquests events per detectar canvis i actualitzar la interfície d'usuari automàticament.solidity contract EventsExample { event Transferencia( address indexed from, address indexed to, uint256 amount, uint256 timestamp ); event PropietariCanviat( address indexed anticPropietari, address indexed nouPropietari ); function transferir(address to, uint256 amount) public { require(saldos[msg.sender] >= amount, "Saldo insuficient"); saldos[msg.sender] -= amount; saldos[to] += amount; emit Transferencia(msg.sender, to, amount, block.timestamp); } }
Bones Pràctiques amb Events
Paràmetres indexed: Permeten filtrar events per valor. Màxim 3 paràmetres indexats per event. Ideals per adreces i identificadors únics. Timestamps: Incloure block.timestamp als events proporciona traçabilitat temporal de les operacions. Cobertura d'events: Emetre events per a totes les operacions importants: creació, transferències, canvis de propietat, actualitzacions d'estat. 5.2 Error Handling
Solidity ofereix tres mecanismes principals per gestionar errors, cadascun amb un ús específic i implicacions de gas diferents:
require Validar inputs i condicions d'entrada Reemborsa gas restant revert Cancel·lar explícitament amb errors personalitzats Reemborsa gas restant assert Verificar invariants interns (mai haurien de fallar) NO reemborsa gas
Recomanació des de Solidity 0.8.4
Utilitza Custom Errors (error NomError(params)) en lloc de strings en require. Són més eficients en gas, tipats i verificables en compilació.
--- ## 📄 docs/06-entorns-desenvolupament.md markdown # 6. Entorns de Desenvolupament === "Remix IDE" IDE basat en web, ideal per a prototipatge ràpid i aprenentatge. No requereix instal·lació. - Accés a [remix.ethereum.org](https://remix.ethereum.org) - Compilador integrat - Desplegament a JavaScript VM - Depurador de transaccions === "Hardhat" Entorn professional per a projectes reals. Ofereix testing avançat, scripts de desplegament i integració amb Etherscan. - Tests amb Mocha/Chai - Xarxa local integrada - Plugins extensibles - Verificació automàtica ## 6.1 Configuració de Projecte Hardhatbash mkdir projecte-blockchain && cd projecte-blockchain npm init -y npm install --save-dev hardhat npx hardhat init npm install --save-dev @nomicfoundation/hardhat-toolbox npm install @openzeppelin/contracts
6.2 Estructura del Projecte
projecte-blockchain/ ├── contracts/ │ └── Token.sol ├── scripts/ │ └── deploy.js ├── test/ │ └── Token.test.js ├── hardhat.config.js └── package.json 6.3 hardhat.config.js
require("@nomicfoundation/hardhat-toolbox"); require('dotenv').config(); module.exports = { solidity: "0.8.20", networks: { hardhat: { chainId: 31337 }, sepolia: { url: process.env.SEPOLIA_RPC_URL, accounts: process.env.PRIVATE_KEY ? [process.env.PRIVATE_KEY] : [], chainId: 11155111 } }, etherscan: { apiKey: process.env.ETHERSCAN_API_KEY } }; 6.4 Comandes Útils
npx hardhat compile Compila tots els contractes i genera artefactes ABI npx hardhat test Executa la suite de tests amb cobertura de codi npx hardhat node Inicia una xarxa local d'Ethereum per a desenvolupament npx hardhat run scripts/deploy.js --network sepolia Desplega a Sepolia testnet usant les credencials del .env --- ## 📄 docs/07-desplegament-testnet.md markdown # 7. Desplegament en Testnet Abans de desplegar a la mainnet d'Ethereum, és imprescindible provar el contracte en una **testnet**. La testnet **Sepolia** és l'entorn de proves recomanat per Ethereum Foundation, ja que replica el comportament de la xarxa principal sense cost real. ## 7.1 Preparatius per a Sepolia 1. **Obtenir ETH de prova** al faucet de Sepolia 2. **Configurar MetaMask** amb Sepolia (Chain ID: `11155111`) 3. **Crear fitxer `.env`** amb claus privades i RPC URL 4. **Executar script de desplegament** amb Hardhat !!! warning "Seguretat" Les claus privades **mai** han d'estar al codi font. Utilitza sempre fitxers `.env` i afegeix-los al `.gitignore`. ## 7.2 Variables d'Entornbash SEPOLIA_RPC_URL="https://sepolia.infura.io/v3/YOUR_INFURA_KEY" PRIVATE_KEY="your_private_key_here" ETHERSCAN_API_KEY="your_etherscan_api_key"
7.3 Script de Desplegament amb Verificació
const hre = require("hardhat"); async function main() { const [deployer] = await hre.ethers.getSigners(); console.log("Desplegant amb el compte:", deployer.address); const Token = await hre.ethers.getContractFactory("TokenERC20"); const token = await Token.deploy(1000000); await token.waitForDeployment(); const address = await token.getAddress(); console.log("Token desplegat a:", address); // Verificar a Etherscan await hre.run("verify:verify", { address: address, constructorArguments: [1000000], }); console.log("Explorer: https://sepolia.etherscan.io/address/" + address); } main().then(() => process.exit(0)).catch((error) => { console.error(error); process.exit(1); });
Faucets recomanats
- sepoliafaucet.com
- Alchemy Faucet
- Infura Faucet
Necessitaràs ETH de prova per pagar les comissions de gas. --- ## 📄 docs/08-bones-practiques-seguretat.md markdown # 8. Bones Pràctiques i Seguretat La seguretat en smart contracts és crítica. A diferència del software tradicional, un contracte desplegat a la blockchain és **immutable**: no es pot parchejar un bug post-desplegament. Els errors de seguretat han costat centenars de milions de dòlars a l'ecosistema. Seguir les millors pràctiques des del principi és una necessitat, no una opció. ## 8.1 Principis Fonamentals ### Principi del Mínim Privilegi Cada funció ha de tenir únicament els permisos estrictament necessaris. Evita funcions `public` quan podrien ser `external` o `internal`. ### Checks-Effects-Interactions (CEI) Primer valida les condicions (Checks), després actualitza l'estat intern (Effects), i finalment realitza crides externes (Interactions). **Prevé atacs de reentrancy.** ### Fail-Safe i Circuit Breakers Implementa mecanismes de pausa d'emergència (`Pausable` d'OpenZeppelin) per poder aturar el contracte si es detecta una anomalia. ### Auditoria Contínua Tests exhaustius, revisió de codi per parells, eines d'anàlisi estàtica (Slither, Mythril) i auditoria externa abans de mainnet. ## 8.2 Reentrancy Attack: Vulnerable vs Segur === "❌ Codi Vulnerable"solidity function withdraw() public { uint256 balance = balances[msg.sender]; require(balance > 0); // Crida externa ABANS d'actualitzar estat (bool success, ) = msg.sender.call{value: balance}(""); require(success); balances[msg.sender] = 0; // Massa tard! } === "✅ Codi Segur (CEI Pattern)"solidity function withdraw() public { uint256 balance = balances[msg.sender]; require(balance > 0); // Actualitzar estat PRIMER balances[msg.sender] = 0; // Crida externa DESPRÉS (bool success, ) = msg.sender.call{value: balance}(""); require(success); } ``` ## 8.3 Checklist de Seguretat Pre-Desplegament | Àrea | Requisits | |---|---| | 🧪 Tests | Cobertura >95% · Tests de seguretat específics · Tests de casos límit | | 🔒 Seguretat | Auditoria externa · OpenZeppelin per estàndards · Circuit breaker implementat | | ⚡ Optimització | Optimització de gas · Tipus de dades adequats · Minimitzar emmagatzematge | | 📄 Documentació | NatSpec comments · README complet · Variables d'entorn documentades |
📄 docs/exercicis/ex01-votacio.md
Exercici Guiat 1: Sistema de Votació Descentralitzat !!! abstract "Objectiu" Construir un sistema de votació complet integrant tots els conceptes apresos: estructures de dades, modificadors personalitzats, events, errors personalitzats i control d'accés. ## Funcionalitats - Registrar candidats (propietari) - Iniciar/finalitzar votació amb termini - Un vot per adreça (haVotat mapping) - Comptatge automàtic i determinació del guanyador ## Conceptes Aplicats - Structs (Candidat) i mappings - Modificadors (nomesPropietari, votacioActiva) - Custom errors (JaHaVotat, CandidatInvalid) - Events indexats per traçabilitat ## Flux del Sistema¶
Afegir candidats → Iniciar votació → Emetre vots → Finalitzar i determinar guanyador
Estructura del Contracte ```solidity // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; contract SistemaVotacio { struct Candidat { uint256 id; string nom; uint256 vots; bool actiu; } address public propietari; uint256 public totalCandidats; uint256 public totalVots; bool public votacioIniciada; bool public votacioFinalitzada; uint256 public dataFi; mapping(uint256 => Candidat) public candidats; mapping(address => bool) public haVotat; event VotEmes(address indexed votant, uint256 indexed candidatId); event VotacioFinalitzada(uint256 guanyadorId, string guanyadorNom); error NoPropietari(); error JaHaVotat(); error CandidatInvalid(); modifier nomesPropietari() { if (msg.sender != propietari) revert NoPropietari(); _; } }¶
Note
El flux del sistema garanteix la integritat del procés: el propietari controla l'inici i el final, mentre que els participants voten de forma autònoma. Cada vot es registra immutablement a la blockchain.
--- ## 📄 docs/exercicis/ex02-marketplace-nft.md markdown # Exercici Guiat 2: Marketplace NFT Simple !!! abstract "Objectiu" Implementar un marketplace bàsic per comprar i vendre NFTs combinant l'estàndard ERC721 d'OpenZeppelin amb una lògica de mercat secundari que inclou comissions automàtiques. ## Funcionalitats del Marketplace - Mint de NFTs amb URI de metadades - Listar NFTs a la venda amb preu - Compra directa amb ETH - Cancel·lació de listings actius - Comissió configurable (2.5% per defecte) ## Estructura de Dadessolidity struct Listing { uint256 tokenId; address seller; uint256 price; bool active; } mapping(uint256 => Listing) public listings; mapping(uint256 => uint256) public tokenToListing;
Flux de Compravenda
// Listar NFT function listNFT(uint256 tokenId, uint256 price) public { if (price == 0) revert PriceZero(); if (ownerOf(tokenId) != msg.sender) revert NotOwner(); approve(address(this), tokenId); listings[nextListingId++] = Listing(tokenId, msg.sender, price, true); } // Comprar NFT function buyNFT(uint256 listingId) public payable { Listing storage listing = listings[listingId]; if (!listing.active) revert ListingInactive(); uint256 commission = (listing.price * commissionPercent) / 1000; uint256 sellerAmount = listing.price - commission; listing.active = false; _safeTransferFrom(listing.seller, msg.sender, listing.tokenId); payable(listing.seller).transfer(sellerAmount); if (commission > 0) payable(owner()).transfer(commission); emit NFTSold(listingId, listing.tokenId, msg.sender); } --- ## 📄 docs/exercicis/ex03-crowdfunding.md markdown # Exercici Guiat 3: Sistema de Crowdfunding !!! abstract "Objectiu" Crear una plataforma de crowdfunding descentralitzada on els fons **només s'alliberen si s'assoleix la meta**. En cas contrari, els donants poden recuperar automàticament els seus fons, sense dependre de cap intermediari. ## Cicle de Vida d'una Campanya | Fase | Descripció | |---|---| | **Crear Campanya** | El creador defineix títol, descripció, meta en ETH i durada en dies. El contracte calcula el termini automàticament. | | **Donar** | Qualsevol adreça pot donar ETH mentre la campanya és activa. El contracte registra cada donació amb timestamp. | | **Reclamar Fons** | Si s'assoleix la meta, el creador pot reclamar tots els fons un cop finalitzat el termini. | | **Reemborsament** | Si no s'assoleix la meta, els donants poden reclamar individualment el seu ETH de tornada. | ## Lògica de Reclamació i Reemborsamentsolidity function claimFunds(uint256 campaignId) public { Campaign storage campaign = campaigns[campaignId]; require(msg.sender == campaign.creator, "Not creator"); require(campaign.completed, "Goal not reached"); require(!campaign.claimed, "Already claimed"); require(block.timestamp >= campaign.deadline, "Not ended"); campaign.claimed = true; (bool success, ) = payable(campaign.creator).call{value: campaign.raised}(""); require(success, "Transfer failed"); emit FundsClaimed(campaignId, campaign.creator); } function refund(uint256 campaignId) public { Campaign storage campaign = campaigns[campaignId]; require(block.timestamp > campaign.deadline, "Not ended"); require(!campaign.completed, "Goal reached - no refund"); // Lògica de reemborsament per donant individual } --- ## 📄 docs/exercicis/col-leccio-exercicis.md ```markdown # 10. Col·lecció d'Exercicis Proposats La col·lecció d'exercicis proposats cobreix tot l'espectre de complexitat, des de contractes bàsics fins a protocols DeFi avançats. Cada exercici està dissenyat per reforçar competències específiques i acumular punts per a l'avaluació final de la unitat. ## Exercicis per Nivell === "🟢 Nivell Bàsic" | Exercici | Punts | |---|---| | E1: Wallet Multi-Signature | 15 pts | | E2: Token amb Staking | 20 pts | | E3: Subhasta Cega | 25 pts | === "🟡 Nivell Intermedi" | Exercici | Punts | |---|---| | E4: DAO Simple | 30 pts | | E5: Lending Protocol | 35 pts | | E6: NFT amb Royalties | 35 pts | === "🔴 Nivell Avançat" | Exercici | Punts | |---|---| | E7: DEX tipus Uniswap | 50 pts | | E8: Bridge Cross-Chain | 50 pts | | E9: Insurance Protocol | 45 pts | === "🔒 Seguretat" | Exercici | Punts | |---|---| | E10: Auditoria de Codi | 30 pts | | E11: Reentrancy Guard | 25 pts | ## Projectes Integradors ### E12: Crowdfunding + NFTs (60 pts) Plataforma de crowdfunding que distribueix NFTs com a recompenses. Inclou frontend bàsic amb Web3.js, tests exhaustius, desplegament a Sepolia i documentació completa. ### E13: Supply Chain amb NFTs (55 pts) Sistema de traçabilitat de productes amb NFTs. Múltiples actors (fabricant, transportista, venedor), actualitzacions d'estat i verificació d'autenticitat en cadena. ### E14: Prediction Market (50 pts) Mercat de prediccions descentralitzat. Creació d'esdeveniments, apostes per resultats, oracle per a la resolució i distribució automàtica de premis.
📄 docs/avaluacio/rubrica.md
Rúbrica d'Avaluació L'avaluació dels exercicis es basa en cinc criteris principals que reflecteixen les competències reals d'un desenvolupador de smart contracts professional. La funcionalitat i la seguretat tenen el pes més elevat, ja que són les dimensions més crítiques en un entorn blockchain on els errors són irreversibles. ## Taula de Criteris | Criteri | Excel·lent (9-10) | Notable (7-8) | Aprovat (5-6) | Suspès (<5) | |---|---|---|---|---| | Funcionalitat | Totes les funcions implementades i funcionant | Majoria de funcions correctes | Funcions bàsiques funcionant | Funcions incompletes o errònies | | Seguretat | Sense vulnerabilitats, bones pràctiques | Petits problemes de seguretat | Vulnerabilitats menors | Vulnerabilitats crítiques | | Codi Net | Ben estructurat, comentat, optimitzat | Clar amb algunes millores possibles | Funcional però millorable | Desorganitzat o difícil de llegir | | Tests | Cobertura >95%, tests exhaustius | Cobertura 80-95% | Cobertura 60-80% | Cobertura <60% o sense tests | | Documentació | Completa, clara, amb exemples | Documentació adequada | Documentació bàsica | Insuficient o absent | ## Criteris Numèrics | Indicador | Valor | |---|---| | Cobertura de Tests per Excel·lent | 95% | | Funcionalitat Bàsica requerida | 100% | | Cobertura mínima per Notable | 80% |¶
📄 docs/avaluacio/bones-practiques-finals.md
Bones Pràctiques Finals: El Camí cap al Mainnet Desplegar un smart contract a la mainnet d'Ethereum és un acte irrevocable. Un cop el contracte és actiu i gestiona fons reals, qualsevol vulnerabilitat pot ser explotada immediatament. El checklist final que segueix representa el mínim imprescindible que qualsevol developer professional ha de completar abans de premer el botó de desplegament definitiu. ## Checklist Pre-Mainnet ### 1. Pla de Resposta a Incidents Definir un protocol clar d'actuació en cas de detectar una vulnerabilitat: canals de comunicació, mecanismes de pausa i pla de migració. ### 2. Monitorització Post-Desplegament Configurar alertes sobre transaccions inusuals, events inesperats i canvis d'estat anòmals amb eines com Tenderly o OpenZeppelin Defender. ### 3. Mecanismes d'Emergència Implementar funcions de pausa (Pausable) i, si escau, funcions d'actualització amb patrons com Proxy Transparent o UUPS. ### 4. Verificació a Block Explorer Verificar el codi font a Etherscan o equivalent perquè els usuaris puguin auditar independentment el contracte. ### 5. Auditoria Externa Per a projectes amb fons reals significatius, contractar una auditoria professional d'empreses com Trail of Bits, Consensys Diligence o Certik. --- > "La seguretat en blockchain no és una característica, és un requisit fonamental. Cada línia de codi que escrius pot tenir conseqüències financeres reals i permanents per als teus usuaris." --- Aquesta unitat didàctica proporciona les bases sòlides per desenvolupar smart contracts professionals, segurs i eficients en Solidity. La pràctica constant, l'estudi de casos reals i la revisió contínua de vulnerabilitats conegudes són essencials per dominar aquest camp en constant evolució. Bona sort en els exercicis!¶
📄 docs/recursos.md
Recursos Addicionals i Eines L'ecosistema d'eines per al desenvolupament de smart contracts és ric i en constant evolució. Dedicar temps a explorar-los és essencial per mantenir-se al dia en un sector que avança a gran velocitat. ## Entorns de Desenvolupament - Remix IDE — IDE web per a prototipatge ràpid - Hardhat — Entorn professional complet - Foundry — Alternativa en Rust, molt ràpida ## Testnets i Faucets - Sepolia Faucet - Alchemy Faucet - Infura Faucet per Sepolia ## Biblioteques - OpenZeppelin — Estàndards auditats - Chainlink — Oracles descentralitzats ## Eines de Seguretat - Slither — Anàlisi estàtica de codi - Mythril — Security analysis - Echidna — Fuzzing automatitzat ## Documentació Oficial - Solidity Docs — Referència completa del llenguatge amb exemples i guies de migració entre versions. - Ethereum.org Developers — Tutorials, patrons de disseny i documentació de l'EVM per a tots els nivells.¶
Aquí tens tot el contingut llest per copiar. Algunes notes pràctiques per posar-ho en marxa:
Instal·lar MkDocs Material pip install mkdocs-material # Previsualitzar en local mkdocs serve # Generar el lloc estàtic mkdocs build¶
He fet servir les extensions de Material que ja tens al mkdocs.yml:
=== "Tab" per als continguts amb pestanyes (tipus valor/referència, Remix/Hardhat, etc.) !!! note/tip/warning/info per als callouts (equivalents als aside del deck) Taules per als comparatius de visibilitat, error handling i rúbrica Blocs de codi amb solidity, bash, javascript per al syntax highlighting