Web3 Blockchain Entwicklung Grundlagen: Smart Contracts, DApps & DeFi
Dieser Beitrag ist eine umfassende Einführung in die Web3 Blockchain Entwicklung Grundlagen – inklusive Smart Contracts, DApps und DeFi mit praktischen Beispielen.
In a Nutshell
Web3 ist die nächste Generation des Internets, die auf Blockchain-Technologie basiert und dezentrale Anwendungen (DApps) ermöglicht, die ohne zentrale Instanzen auskommen.
Kompakte Fachbeschreibung
Web3 ist ein dezentrales Internet-Protokoll, das auf Blockchain-Technologie aufbaut und Benutzern die Kontrolle über ihre Daten und digitale Identitäten gibt.
Kernkomponenten:
Blockchain Grundlagen
- Distributed Ledger: Dezentrale Datenhaltung
- Consensus Mechanisms: Proof of Work, Proof of Stake
- Cryptography: Hash-Funktionen, Digitale Signaturen
- Smart Contracts: Selbstausführende Verträge
- Gas Fees: Transaktionskosten
Ethereum Ecosystem
- EVM: Ethereum Virtual Machine
- Solidity: Smart Contract Programmiersprache
- Web3.js: JavaScript Bibliothek für Web3
- Hardhat: Entwicklungsumgebung
- OpenZeppelin: Sichere Smart Contract Bibliotheken
Decentralized Finance (DeFi)
- DEX: Decentralized Exchanges
- Lending: Dezentrale Kreditplattformen
- Yield Farming: Liquiditätsbereitstellung
- Staking: Token-Validierung
- Governance: Dezentrale Entscheidungsfindung
Prüfungsrelevante Stichpunkte
- Web3: Dezentrales Internet basierend auf Blockchain
- Blockchain: Dezentrale Datenbank mit kryptographischer Sicherheit
- Smart Contracts: Selbstausführende Verträge auf der Blockchain
- DApps: Dezentrale Anwendungen ohne zentrale Instanz
- DeFi: Dezentrale Finanzdienstleistungen
- Ethereum: Leading Smart Contract Plattform
- Solidity: Programmiersprache für Smart Contracts
- Gas: Transaktionskosten auf der Blockchain
- IHK-relevant: Moderne Blockchain-Entwicklung und -Architektur
Kernkomponenten
- Blockchain Technology: Distributed Ledger, Konsensmechanismen
- Smart Contracts: Selbstausführende Verträge mit Business Logic
- DApps: Dezentrale Frontend-Anwendungen
- DeFi Protocols: Finanzdienstleistungen auf der Blockchain
- Wallet Integration: MetaMask, WalletConnect
- Web3 Libraries: Web3.js, Ethers.js
- Development Tools: Hardhat, Truffle, Remix
- Security: Audits, Best Practices, Vulnerability Scanning
Praxisbeispiele
1. Smart Contract mit Solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";
/**
* @title DeFiToken
* @dev ERC20 Token mit erweiterten Funktionen für DeFi-Anwendungen
* @author Web3 Developer
*/
contract DeFiToken is ERC20, ERC20Burnable, ReentrancyGuard, Ownable {
using SafeMath for uint256;
// Events
event TokensMinted(address indexed to, uint256 amount);
event TokensBurned(address indexed from, uint256 amount);
event LiquidityAdded(address indexed provider, uint256 tokenAmount, uint256 ethAmount);
event LiquidityRemoved(address indexed provider, uint256 tokenAmount, uint256 ethAmount);
event RewardClaimed(address indexed claimant, uint256 rewardAmount);
// State variables
uint256 public constant MAX_SUPPLY = 1000000000 * 10**18; // 1 Billion tokens
uint256 public constant INITIAL_SUPPLY = 100000000 * 10**18; // 100 Million tokens
uint256 public constant REWARD_RATE = 1 * 10**16; // 0.01 tokens per block
uint256 public totalLiquidity;
uint256 public totalRewardsDistributed;
uint256 public lastRewardBlock;
uint256 public rewardPerTokenStored;
mapping(address => uint256) public userRewardPerTokenPaid;
mapping(address => uint256) public rewards;
mapping(address => uint256) public liquidityProvided;
mapping(address => uint256) public depositTimestamp;
// Arrays für Staking-Pools
struct Pool {
uint256 totalStaked;
uint256 rewardRate;
uint256 lockPeriod;
uint256 apr;
bool active;
}
mapping(uint256 => Pool) public pools;
mapping(address => mapping(uint256 => uint256)) public userStakes;
mapping(address => mapping(uint256 => uint256)) public userStakeTimestamp;
uint256 public poolCount;
// Governance
struct Proposal {
uint256 id;
address proposer;
string description;
uint256 voteCount;
uint256 quorum;
uint256 deadline;
bool executed;
mapping(address => bool) hasVoted;
}
mapping(uint256 => Proposal) public proposals;
uint256 public proposalCount;
mapping(address => uint256) public votingPower;
// Modifiers
modifier validAddress(address _addr) {
require(_addr != address(0), "Invalid address");
_;
}
modifier sufficientBalance(address _account, uint256 _amount) {
require(balanceOf(_account) >= _amount, "Insufficient balance");
_;
}
modifier sufficientLiquidity(uint256 _amount) {
require(address(this).balance >= _amount, "Insufficient ETH liquidity");
_;
}
modifier onlyWhenPaused() {
require(!paused(), "Contract is paused");
_;
}
// Constructor
constructor(
string memory _name,
string memory _symbol,
uint256 _initialMint
) ERC20(_name, _symbol) {
require(_initialMint <= INITIAL_SUPPLY, "Initial mint exceeds limit");
_mint(msg.sender, _initialMint);
lastRewardBlock = block.number;
// Erstelle initialen Staking-Pool
_createPool(100, 30 days, 10); // 100% APR, 30 Tage Lock
}
/**
* @dev Mint neue Tokens (nur Owner)
*/
function mint(address _to, uint256 _amount)
external
onlyOwner
validAddress(_to)
returns (bool)
{
require(totalSupply() + _amount <= MAX_SUPPLY, "Exceeds max supply");
_mint(_to, _amount);
emit TokensMinted(_to, _amount);
return true;
}
/**
* @dev Füge Liquidität zum Pool hinzu
*/
function addLiquidity(uint256 _tokenAmount)
external
payable
nonReentrant
sufficientBalance(msg.sender, _tokenAmount)
returns (uint256 liquidityTokens)
{
require(_tokenAmount > 0 && msg.value > 0, "Invalid amounts");
// Berechne Liquidität-Tokens
uint256 ethReserve = address(this).balance - msg.value;
uint256 tokenReserve = totalSupply() - _tokenAmount;
if (ethReserve == 0 || tokenReserve == 0) {
liquidityTokens = _tokenAmount;
} else {
liquidityTokens = min(
(msg.value * tokenReserve) / ethReserve,
_tokenAmount
);
}
require(liquidityTokens > 0, "Insufficient liquidity minted");
// Transferiere Tokens und ETH
_transfer(msg.sender, address(this), _tokenAmount);
// Update Benutzer-Liquidität
liquidityProvided[msg.sender] += liquidityTokens;
depositTimestamp[msg.sender] = block.timestamp;
// Update totale Liquidität
totalLiquidity += liquidityTokens;
// Update Rewards
_updateReward(msg.sender);
emit LiquidityAdded(msg.sender, _tokenAmount, msg.value);
return liquidityTokens;
}
/**
* @dev Entferne Liquidität aus dem Pool
*/
function removeLiquidity(uint256 _liquidityAmount)
external
nonReentrant
returns (uint256 ethAmount, uint256 tokenAmount)
{
require(_liquidityAmount > 0, "Invalid amount");
require(liquidityProvided[msg.sender] >= _liquidityAmount, "Insufficient liquidity");
// Berechne Anteile
uint256 totalLiquidityTokens = totalLiquidity;
uint256 ethReserve = address(this).balance;
uint256 tokenReserve = balanceOf(address(this));
ethAmount = (ethReserve * _liquidityAmount) / totalLiquidityTokens;
tokenAmount = (tokenReserve * _liquidityAmount) / totalLiquidityTokens;
require(ethAmount > 0 && tokenAmount > 0, "Insufficient withdraw amount");
// Update Benutzer-Liquidität
liquidityProvided[msg.sender] -= _liquidityAmount;
totalLiquidity -= _liquidityAmount;
// Update Rewards
_updateReward(msg.sender);
_claimRewards(msg.sender);
// Transferiere ETH und Tokens
payable(msg.sender).transfer(ethAmount);
_transfer(address(this), msg.sender, tokenAmount);
emit LiquidityRemoved(msg.sender, tokenAmount, ethAmount);
return (ethAmount, tokenAmount);
}
/**
* @dev Erstelle neuen Staking-Pool
*/
function createPool(uint256 _apr, uint256 _lockPeriod) external onlyOwner {
_createPool(_apr, _lockPeriod, 0);
}
function _createPool(uint256 _apr, uint256 _lockPeriod, uint256 _rewardRate) internal {
pools[poolCount] = Pool({
totalStaked: 0,
rewardRate: _rewardRate > 0 ? _rewardRate : REWARD_RATE,
lockPeriod: _lockPeriod,
apr: _apr,
active: true
});
poolCount++;
}
/**
* @dev Stake Tokens in Pool
*/
function stake(uint256 _poolId, uint256 _amount)
external
nonReentrant
sufficientBalance(msg.sender, _amount)
returns (bool)
{
require(_poolId < poolCount, "Invalid pool");
require(pools[_poolId].active, "Pool not active");
require(_amount > 0, "Invalid amount");
// Update Rewards vor dem Stake
_updatePoolRewards(_poolId);
_updateUserPoolRewards(_poolId, msg.sender);
// Transferiere Tokens zum Contract
_transfer(msg.sender, address(this), _amount);
// Update Staking
userStakes[msg.sender][_poolId] += _amount;
userStakeTimestamp[msg.sender][_poolId] = block.timestamp;
pools[_poolId].totalStaked += _amount;
// Update Voting Power
votingPower[msg.sender] += _amount;
return true;
}
/**
* @dev Unstake Tokens aus Pool
*/
function unstake(uint256 _poolId, uint256 _amount)
external
nonReentrant
returns (bool)
{
require(_poolId < poolCount, "Invalid pool");
require(userStakes[msg.sender][_poolId] >= _amount, "Insufficient stake");
Pool storage pool = pools[_poolId];
// Check Lock Period
uint256 stakeTime = userStakeTimestamp[msg.sender][_poolId];
require(
block.timestamp >= stakeTime + pool.lockPeriod,
"Tokens still locked"
);
// Update Rewards vor dem Unstake
_updatePoolRewards(_poolId);
_updateUserPoolRewards(_poolId, msg.sender);
// Update Staking
userStakes[msg.sender][_poolId] -= _amount;
pool.totalStaked -= _amount;
// Update Voting Power
votingPower[msg.sender] -= _amount;
// Transferiere Tokens zurück
_transfer(address(this), msg.sender, _amount);
return true;
}
/**
* @dev Claim Rewards aus Pool
*/
function claimRewards(uint256 _poolId) external nonReentrant returns (uint256) {
require(_poolId < poolCount, "Invalid pool");
require(userStakes[msg.sender][_poolId] > 0, "No stake in pool");
// Update Rewards
_updatePoolRewards(_poolId);
_updateUserPoolRewards(_poolId, msg.sender);
uint256 reward = rewards[msg.sender];
require(reward > 0, "No rewards to claim");
// Reset rewards
rewards[msg.sender] = 0;
// Mint neue Tokens als Reward
_mint(msg.sender, reward);
emit RewardClaimed(msg.sender, reward);
return reward;
}
/**
* @dev Erstelle Governance Proposal
*/
function createProposal(string memory _description, uint256 _quorum)
external
returns (uint256)
{
require(votingPower[msg.sender] >= 1000 * 10**18, "Insufficient voting power");
require(bytes(_description).length > 0, "Empty description");
Proposal storage proposal = proposals[proposalCount];
proposal.id = proposalCount;
proposal.proposer = msg.sender;
proposal.description = _description;
proposal.voteCount = 0;
proposal.quorum = _quorum;
proposal.deadline = block.timestamp + 7 days;
proposal.executed = false;
proposalCount++;
return proposalCount - 1;
}
/**
* @dev Vote für Proposal
*/
function vote(uint256 _proposalId) external {
require(_proposalId < proposalCount, "Invalid proposal");
require(block.timestamp <= proposals[_proposalId].deadline, "Voting ended");
require(!proposals[_proposalId].hasVoted[msg.sender], "Already voted");
require(votingPower[msg.sender] > 0, "No voting power");
proposals[_proposalId].hasVoted[msg.sender] = true;
proposals[_proposalId].voteCount += votingPower[msg.sender];
}
/**
* @dev Execute Proposal
*/
function executeProposal(uint256 _proposalId) external onlyOwner {
require(_proposalId < proposalCount, "Invalid proposal");
require(block.timestamp > proposals[_proposalId].deadline, "Voting not ended");
require(!proposals[_proposalId].executed, "Already executed");
require(
proposals[_proposalId].voteCount >= proposals[_proposalId].quorum,
"Quorum not reached"
);
proposals[_proposalId].executed = true;
}
/**
* @dev Update Reward Funktionen
*/
function _updateReward(address _account) internal {
if (_account == address(0)) return;
rewardPerTokenStored = rewardPerToken();
lastRewardBlock = block.number;
rewards[_account] = earned(_account);
userRewardPerTokenPaid[_account] = rewardPerTokenStored;
}
function _updatePoolRewards(uint256 _poolId) internal {
// Implementiere Pool-spezifische Reward Logic
// Dies ist eine vereinfachte Version
}
function _updateUserPoolRewards(uint256 _poolId, address _account) internal {
// Implementiere User-spezifische Pool Rewards
}
/**
* @dev Helper Funktionen
*/
function rewardPerToken() public view returns (uint256) {
if (totalLiquidity == 0) {
return rewardPerTokenStored;
}
return rewardPerTokenStored.add(
((block.number.sub(lastRewardBlock)).mul(REWARD_RATE)).mul(1e18).div(totalLiquidity)
);
}
function earned(address _account) public view returns (uint256) {
return liquidityProvided[_account]
.mul(rewardPerToken().sub(userRewardPerTokenPaid[_account]))
.div(1e18)
.add(rewards[_account]);
}
function getPoolInfo(uint256 _poolId)
external
view
returns (
uint256 totalStaked,
uint256 rewardRate,
uint256 lockPeriod,
uint256 apr,
bool active
)
{
require(_poolId < poolCount, "Invalid pool");
Pool storage pool = pools[_poolId];
return (pool.totalStaked, pool.rewardRate, pool.lockPeriod, pool.apr, pool.active);
}
function getUserStake(uint256 _poolId, address _user)
external
view
returns (uint256 amount, uint256 timestamp)
{
require(_poolId < poolCount, "Invalid pool");
return (userStakes[_user][_poolId], userStakeTimestamp[_user][_poolId]);
}
function getProposalInfo(uint256 _proposalId)
external
view
returns (
address proposer,
string memory description,
uint256 voteCount,
uint256 quorum,
uint256 deadline,
bool executed,
bool hasVoted
)
{
require(_proposalId < proposalCount, "Invalid proposal");
Proposal storage proposal = proposals[_proposalId];
return (
proposal.proposer,
proposal.description,
proposal.voteCount,
proposal.quorum,
proposal.deadline,
proposal.executed,
proposal.hasVoted[msg.sender]
);
}
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Emergency Funktionen
*/
function emergencyPause() external onlyOwner {
_pause();
}
function emergencyUnpause() external onlyOwner {
_unpause();
}
function emergencyWithdraw() external onlyOwner {
payable(owner()).transfer(address(this).balance);
}
/**
* @dev Fallback für ETH Transfers
*/
receive() external payable {
// Akzeptiere ETH für Liquidität
}
fallback() external payable {
// Akzeptiere ETH für Liquidität
}
}
2. DApp Frontend mit React und Web3.js
// src/components/Web3Provider.jsx
import React, { createContext, useContext, useEffect, useState } from 'react';
import Web3 from 'web3';
import { Contract } from 'web3-eth-contract';
import DeFiTokenABI from '../contracts/DeFiToken.json';
const Web3Context = createContext();
export const useWeb3 = () => {
const context = useContext(Web3Context);
if (!context) {
throw new Error('useWeb3 must be used within a Web3Provider');
}
return context;
};
const Web3Provider = ({ children }) => {
const [web3, setWeb3] = useState(null);
const [account, setAccount] = useState(null);
const [contract, setContract] = useState(null);
const [networkId, setNetworkId] = useState(null);
const [balance, setBalance] = useState('0');
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const CONTRACT_ADDRESS = process.env.REACT_APP_CONTRACT_ADDRESS;
const SUPPORTED_NETWORKS = {
1: 'Ethereum Mainnet',
3: 'Ropsten Testnet',
4: 'Rinkeby Testnet',
5: 'Goerli Testnet',
42: 'Kovan Testnet',
137: 'Polygon Mainnet',
80001: 'Polygon Mumbai'
};
// Initialize Web3
useEffect(() => {
const initWeb3 = async () => {
try {
// Check if MetaMask is installed
if (typeof window.ethereum !== 'undefined') {
const web3Instance = new Web3(window.ethereum);
setWeb3(web3Instance);
// Request account access
const accounts = await window.ethereum.request({
method: 'eth_requestAccounts'
});
if (accounts.length > 0) {
setAccount(accounts[0]);
await setupContract(web3Instance);
await getNetworkInfo(web3Instance);
await updateBalance(web3Instance, accounts[0]);
}
// Setup event listeners
setupEventListeners(web3Instance);
} else {
setError('MetaMask is not installed. Please install MetaMask to use this DApp.');
}
} catch (error) {
console.error('Web3 initialization error:', error);
setError('Failed to initialize Web3. Please check your wallet connection.');
} finally {
setLoading(false);
}
};
initWeb3();
}, []);
const setupEventListeners = (web3Instance) => {
// Account change
window.ethereum.on('accountsChanged', (accounts) => {
if (accounts.length === 0) {
setAccount(null);
setBalance('0');
} else {
setAccount(accounts[0]);
updateBalance(web3Instance, accounts[0]);
}
});
// Network change
window.ethereum.on('chainChanged', () => {
window.location.reload();
});
// Connect/Disconnect
window.ethereum.on('connect', (connectInfo) => {
console.log('Connected to blockchain:', connectInfo);
});
window.ethereum.on('disconnect', (error) => {
console.error('Disconnected from blockchain:', error);
setAccount(null);
setBalance('0');
});
};
const setupContract = async (web3Instance) => {
try {
const contractInstance = new web3Instance.eth.Contract(
DeFiTokenABI.abi,
CONTRACT_ADDRESS
);
setContract(contractInstance);
} catch (error) {
console.error('Contract setup error:', error);
setError('Failed to setup smart contract.');
}
};
const getNetworkInfo = async (web3Instance) => {
try {
const networkId = await web3Instance.eth.net.getId();
setNetworkId(networkId);
if (!SUPPORTED_NETWORKS[networkId]) {
setError(`Unsupported network. Please switch to a supported network.`);
}
} catch (error) {
console.error('Network info error:', error);
}
};
const updateBalance = async (web3Instance, accountAddress) => {
try {
const balanceWei = await web3Instance.eth.getBalance(accountAddress);
const balanceEth = web3Instance.utils.fromWei(balanceWei, 'ether');
setBalance(balanceEth);
} catch (error) {
console.error('Balance update error:', error);
}
};
const connectWallet = async () => {
try {
if (typeof window.ethereum !== 'undefined') {
const accounts = await window.ethereum.request({
method: 'eth_requestAccounts'
});
if (accounts.length > 0) {
setAccount(accounts[0]);
await updateBalance(web3, accounts[0]);
}
}
} catch (error) {
console.error('Wallet connection error:', error);
setError('Failed to connect wallet.');
}
};
const disconnectWallet = () => {
setAccount(null);
setBalance('0');
};
const switchNetwork = async (networkId) => {
try {
await window.ethereum.request({
method: 'wallet_switchEthereumChain',
params: [{ chainId: `0x${networkId.toString(16)}` }]
});
} catch (error) {
console.error('Network switch error:', error);
setError('Failed to switch network.');
}
};
const value = {
web3,
account,
contract,
networkId,
balance,
loading,
error,
supportedNetworks: SUPPORTED_NETWORKS,
connectWallet,
disconnectWallet,
switchNetwork,
refreshBalance: () => updateBalance(web3, account)
};
return (
<Web3Context.Provider value={value}>
{children}
</Web3Context.Provider>
);
};
export default Web3Provider;
// src/components/TokenDashboard.jsx
import React, { useState, useEffect } from 'react';
import { useWeb3 } from './Web3Provider';
import { Card, CardHeader, CardContent, CardActions } from './UI/Card';
import Button from './UI/Button';
import Input from './UI/Input';
import Alert from './UI/Alert';
import LoadingSpinner from './UI/LoadingSpinner';
const TokenDashboard = () => {
const { web3, account, contract, balance, refreshBalance } = useWeb3();
const [tokenBalance, setTokenBalance] = useState('0');
const [totalSupply, setTotalSupply] = useState('0');
const [stakingData, setStakingData] = useState([]);
const [liquidityData, setLiquidityData] = useState(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const [success, setSuccess] = useState(null);
// Form states
const [stakeAmount, setStakeAmount] = useState('');
const [liquidityTokenAmount, setLiquidityTokenAmount] = useState('');
const [liquidityEthAmount, setLiquidityEthAmount] = useState('');
// Load token data
useEffect(() => {
if (contract && account) {
loadTokenData();
}
}, [contract, account]);
const loadTokenData = async () => {
try {
setLoading(true);
setError(null);
const [
tokenBalanceWei,
totalSupplyWei,
poolCount,
userLiquidity,
userRewards
] = await Promise.all([
contract.methods.balanceOf(account).call(),
contract.methods.totalSupply().call(),
contract.methods.poolCount().call(),
contract.methods.liquidityProvided(account).call(),
contract.methods.earned(account).call()
]);
setTokenBalance(web3.utils.fromWei(tokenBalanceWei, 'ether'));
setTotalSupply(web3.utils.fromWei(totalSupplyWei, 'ether'));
setLiquidityData({
provided: web3.utils.fromWei(userLiquidity, 'ether'),
rewards: web3.utils.fromWei(userRewards, 'ether')
});
// Load staking data
const pools = [];
for (let i = 0; i < poolCount; i++) {
const [poolInfo, userStake] = await Promise.all([
contract.methods.getPoolInfo(i).call(),
contract.methods.getUserStake(i, account).call()
]);
pools.push({
id: i,
...poolInfo,
userStake: {
amount: web3.utils.fromWei(userStake.amount, 'ether'),
timestamp: userStake.timestamp
}
});
}
setStakingData(pools);
} catch (error) {
console.error('Token data load error:', error);
setError('Failed to load token data.');
} finally {
setLoading(false);
}
};
const handleStake = async (poolId, amount) => {
try {
setLoading(true);
setError(null);
const amountWei = web3.utils.toWei(amount, 'ether');
const tx = await contract.methods.stake(poolId, amountWei).send({
from: account,
gas: '300000'
});
setSuccess(`Successfully staked ${amount} tokens! Transaction: ${tx.transactionHash}`);
setStakeAmount('');
await loadTokenData();
await refreshBalance();
} catch (error) {
console.error('Stake error:', error);
setError('Failed to stake tokens.');
} finally {
setLoading(false);
}
};
const handleUnstake = async (poolId, amount) => {
try {
setLoading(true);
setError(null);
const amountWei = web3.utils.toWei(amount, 'ether');
const tx = await contract.methods.unstake(poolId, amountWei).send({
from: account,
gas: '300000'
});
setSuccess(`Successfully unstaked ${amount} tokens! Transaction: ${tx.transactionHash}`);
await loadTokenData();
await refreshBalance();
} catch (error) {
console.error('Unstake error:', error);
setError('Failed to unstake tokens.');
} finally {
setLoading(false);
}
};
const handleClaimRewards = async (poolId) => {
try {
setLoading(true);
setError(null);
const tx = await contract.methods.claimRewards(poolId).send({
from: account,
gas: '200000'
});
const rewards = await contract.methods.claimRewards(poolId).call({ from: account });
setSuccess(`Successfully claimed ${web3.utils.fromWei(rewards, 'ether')} tokens!`);
await loadTokenData();
} catch (error) {
console.error('Claim rewards error:', error);
setError('Failed to claim rewards.');
} finally {
setLoading(false);
}
};
const handleAddLiquidity = async () => {
try {
setLoading(true);
setError(null);
const tokenAmountWei = web3.utils.toWei(liquidityTokenAmount, 'ether');
const ethAmountWei = web3.utils.toWei(liquidityEthAmount, 'ether');
// Approve token transfer
await contract.methods.approve(CONTRACT_ADDRESS, tokenAmountWei).send({
from: account,
gas: '100000'
});
// Add liquidity
const tx = await contract.methods.addLiquidity(tokenAmountWei).send({
from: account,
value: ethAmountWei,
gas: '300000'
});
setSuccess(`Successfully added liquidity! Transaction: ${tx.transactionHash}`);
setLiquidityTokenAmount('');
setLiquidityEthAmount('');
await loadTokenData();
await refreshBalance();
} catch (error) {
console.error('Add liquidity error:', error);
setError('Failed to add liquidity.');
} finally {
setLoading(false);
}
};
const handleRemoveLiquidity = async (amount) => {
try {
setLoading(true);
setError(null);
const amountWei = web3.utils.toWei(amount, 'ether');
const tx = await contract.methods.removeLiquidity(amountWei).send({
from: account,
gas: '300000'
});
setSuccess(`Successfully removed liquidity! Transaction: ${tx.transactionHash}`);
await loadTokenData();
await refreshBalance();
} catch (error) {
console.error('Remove liquidity error:', error);
setError('Failed to remove liquidity.');
} finally {
setLoading(false);
}
};
if (loading && !tokenBalance) {
return <LoadingSpinner />;
}
return (
<div className="token-dashboard">
<div className="dashboard-header">
<h1>DeFi Token Dashboard</h1>
<div className="account-info">
<p><strong>Account:</strong> {account}</p>
<p><strong>ETH Balance:</strong> {balance} ETH</p>
<p><strong>Token Balance:</strong> {tokenBalance} DEFI</p>
</div>
</div>
{error && <Alert type="error" message={error} />}
{success && <Alert type="success" message={success} />}
{/* Token Info */}
<Card className="token-info-card">
<CardHeader>
<h2>Token Information</h2>
</CardHeader>
<CardContent>
<div className="info-grid">
<div className="info-item">
<label>Total Supply</label>
<span>{totalSupply} DEFI</span>
</div>
<div className="info-item">
<label>Your Balance</label>
<span>{tokenBalance} DEFI</span>
</div>
<div className="info-item">
<label>Liquidity Provided</label>
<span>{liquidityData?.provided || '0'} DEFI</span>
</div>
<div className="info-item">
<label>Pending Rewards</label>
<span>{liquidityData?.rewards || '0'} DEFI</span>
</div>
</div>
</CardContent>
</Card>
{/* Staking Pools */}
<Card className="staking-card">
<CardHeader>
<h2>Staking Pools</h2>
</CardHeader>
<CardContent>
{stakingData.map((pool) => (
<div key={pool.id} className="staking-pool">
<div className="pool-header">
<h3>Pool #{pool.id + 1}</h3>
<span className={`pool-status ${pool.active ? 'active' : 'inactive'}`}>
{pool.active ? 'Active' : 'Inactive'}
</span>
</div>
<div className="pool-info">
<div className="pool-stat">
<label>APR</label>
<span>{pool.apr}%</span>
</div>
<div className="pool-stat">
<label>Lock Period</label>
<span>{pool.lockPeriod / 86400} days</span>
</div>
<div className="pool-stat">
<label>Total Staked</label>
<span>{web3.utils.fromWei(pool.totalStaked, 'ether')} DEFI</span>
</div>
<div className="pool-stat">
<label>Your Stake</label>
<span>{pool.userStake.amount} DEFI</span>
</div>
</div>
<div className="pool-actions">
{pool.active && (
<>
<div className="stake-form">
<Input
type="number"
placeholder="Amount to stake"
value={stakeAmount}
onChange={(e) => setStakeAmount(e.target.value)}
min="0"
step="0.01"
/>
<Button
onClick={() => handleStake(pool.id, stakeAmount)}
disabled={!stakeAmount || parseFloat(stakeAmount) <= 0}
>
Stake
</Button>
</div>
{pool.userStake.amount > '0' && (
<>
<Button
variant="secondary"
onClick={() => handleUnstake(pool.id, pool.userStake.amount)}
>
Unstake All
</Button>
<Button
variant="outline"
onClick={() => handleClaimRewards(pool.id)}
>
Claim Rewards
</Button>
</>
)}
</>
)}
</div>
</div>
))}
</CardContent>
</Card>
{/* Liquidity Management */}
<Card className="liquidity-card">
<CardHeader>
<h2>Liquidity Management</h2>
</CardHeader>
<CardContent>
<div className="liquidity-form">
<h3>Add Liquidity</h3>
<div className="form-row">
<Input
type="number"
placeholder="Token amount"
value={liquidityTokenAmount}
onChange={(e) => setLiquidityTokenAmount(e.target.value)}
min="0"
step="0.01"
/>
<Input
type="number"
placeholder="ETH amount"
value={liquidityEthAmount}
onChange={(e) => setLiquidityEthAmount(e.target.value)}
min="0"
step="0.01"
/>
</div>
<Button
onClick={handleAddLiquidity}
disabled={!liquidityTokenAmount || !liquidityEthAmount || loading}
>
Add Liquidity
</Button>
</div>
{liquidityData?.provided > '0' && (
<div className="remove-liquidity">
<h3>Remove Liquidity</h3>
<div className="form-row">
<Input
type="number"
placeholder="Amount to remove"
min="0"
max={liquidityData.provided}
step="0.01"
/>
<Button
variant="danger"
onClick={() => handleRemoveLiquidity(liquidityData.provided)}
>
Remove All
</Button>
</div>
</div>
)}
</CardContent>
</Card>
</div>
);
};
export default TokenDashboard;
// src/components/GovernancePanel.jsx
import React, { useState, useEffect } from 'react';
import { useWeb3 } from './Web3Provider';
import { Card, CardHeader, CardContent, CardActions } from './UI/Card';
import Button from './UI/Button';
import Input from './UI/Input';
import Alert from './UI/Alert';
const GovernancePanel = () => {
const { web3, account, contract } = useWeb3();
const [proposals, setProposals] = useState([]);
const [votingPower, setVotingPower] = useState('0');
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const [success, setSuccess] = useState(null);
// Form states
const [proposalDescription, setProposalDescription] = useState('');
const [proposalQuorum, setProposalQuorum] = useState('');
useEffect(() => {
if (contract && account) {
loadGovernanceData();
}
}, [contract, account]);
const loadGovernanceData = async () => {
try {
setLoading(true);
setError(null);
const [proposalCount, userVotingPower] = await Promise.all([
contract.methods.proposalCount().call(),
contract.methods.votingPower(account).call()
]);
setVotingPower(web3.utils.fromWei(userVotingPower, 'ether'));
// Load proposals
const proposalList = [];
for (let i = 0; i < proposalCount; i++) {
const proposalInfo = await contract.methods.getProposalInfo(i).call();
proposalList.push({
id: i,
proposer: proposalInfo[0],
description: proposalInfo[1],
voteCount: web3.utils.fromWei(proposalInfo[2], 'ether'),
quorum: web3.utils.fromWei(proposalInfo[3], 'ether'),
deadline: new Date(proposalInfo[4] * 1000),
executed: proposalInfo[5],
hasVoted: proposalInfo[6]
});
}
setProposals(proposalList.reverse()); // Newest first
} catch (error) {
console.error('Governance data load error:', error);
setError('Failed to load governance data.');
} finally {
setLoading(false);
}
};
const handleCreateProposal = async () => {
try {
setLoading(true);
setError(null);
const quorumWei = web3.utils.toWei(proposalQuorum, 'ether');
const tx = await contract.methods.createProposal(
proposalDescription,
quorumWei
).send({
from: account,
gas: '200000'
});
setSuccess(`Proposal created successfully! Transaction: ${tx.transactionHash}`);
setProposalDescription('');
setProposalQuorum('');
await loadGovernanceData();
} catch (error) {
console.error('Create proposal error:', error);
setError('Failed to create proposal.');
} finally {
setLoading(false);
}
};
const handleVote = async (proposalId) => {
try {
setLoading(true);
setError(null);
const tx = await contract.methods.vote(proposalId).send({
from: account,
gas: '100000'
});
setSuccess(`Vote cast successfully! Transaction: ${tx.transactionHash}`);
await loadGovernanceData();
} catch (error) {
console.error('Vote error:', error);
setError('Failed to cast vote.');
} finally {
setLoading(false);
}
};
const handleExecuteProposal = async (proposalId) => {
try {
setLoading(true);
setError(null);
const tx = await contract.methods.executeProposal(proposalId).send({
from: account,
gas: '100000'
});
setSuccess(`Proposal executed successfully! Transaction: ${tx.transactionHash}`);
await loadGovernanceData();
} catch (error) {
console.error('Execute proposal error:', error);
setError('Failed to execute proposal.');
} finally {
setLoading(false);
}
};
const canVote = (proposal) => {
return !proposal.hasVoted &&
votingPower > '0' &&
new Date() < proposal.deadline &&
!proposal.executed;
};
const canExecute = (proposal) => {
return !proposal.executed &&
new Date() > proposal.deadline &&
proposal.voteCount >= proposal.quorum;
};
return (
<div className="governance-panel">
<div className="governance-header">
<h1>Governance</h1>
<div className="voting-info">
<p><strong>Your Voting Power:</strong> {votingPower} DEFI</p>
</div>
</div>
{error && <Alert type="error" message={error} />}
{success && <Alert type="success" message={success} />}
{/* Create Proposal */}
<Card className="create-proposal-card">
<CardHeader>
<h2>Create Proposal</h2>
</CardHeader>
<CardContent>
<div className="proposal-form">
<div className="form-group">
<label>Proposal Description</label>
<textarea
value={proposalDescription}
onChange={(e) => setProposalDescription(e.target.value)}
placeholder="Describe your proposal..."
rows={4}
/>
</div>
<div className="form-group">
<label>Quorum (tokens required)</label>
<Input
type="number"
value={proposalQuorum}
onChange={(e) => setProposalQuorum(e.target.value)}
placeholder="1000000"
min="0"
step="0.01"
/>
</div>
</div>
</CardContent>
<CardActions>
<Button
onClick={handleCreateProposal}
disabled={!proposalDescription || !proposalQuorum || votingPower < '1000'}
>
Create Proposal
</Button>
</CardActions>
</Card>
{/* Proposals List */}
<Card className="proposals-card">
<CardHeader>
<h2>Proposals</h2>
</CardHeader>
<CardContent>
{proposals.length === 0 ? (
<p>No proposals yet.</p>
) : (
<div className="proposals-list">
{proposals.map((proposal) => (
<div key={proposal.id} className="proposal-item">
<div className="proposal-header">
<h3>Proposal #{proposal.id + 1}</h3>
<div className="proposal-status">
{proposal.executed ? (
<span className="status-executed">Executed</span>
) : new Date() > proposal.deadline ? (
<span className="status-expired">Expired</span>
) : (
<span className="status-active">Active</span>
)}
</div>
</div>
<div className="proposal-content">
<p className="proposal-description">{proposal.description}</p>
<div className="proposal-meta">
<div className="meta-item">
<label>Proposer:</label>
<span>{proposal.proposer}</span>
</div>
<div className="meta-item">
<label>Deadline:</label>
<span>{proposal.deadline.toLocaleDateString()}</span>
</div>
<div className="meta-item">
<label>Vote Count:</label>
<span>{proposal.voteCount} / {proposal.quorum}</span>
</div>
</div>
<div className="vote-progress">
<div className="progress-bar">
<div
className="progress-fill"
style={{
width: `${Math.min((parseFloat(proposal.voteCount) / parseFloat(proposal.quorum)) * 100, 100)}%`
}}
/>
</div>
<span className="progress-text">
{Math.round((parseFloat(proposal.voteCount) / parseFloat(proposal.quorum)) * 100)}%
</span>
</div>
</div>
<div className="proposal-actions">
{canVote(proposal) && (
<Button onClick={() => handleVote(proposal.id)}>
Vote
</Button>
)}
{canExecute(proposal) && (
<Button variant="success" onClick={() => handleExecuteProposal(proposal.id)}>
Execute
</Button>
)}
{proposal.hasVoted && (
<span className="voted-indicator">✓ Voted</span>
)}
</div>
</div>
))}
</div>
)}
</CardContent>
</Card>
</div>
);
};
export default GovernancePanel;
// src/App.jsx
import React from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import Web3Provider from './components/Web3Provider';
import TokenDashboard from './components/TokenDashboard';
import GovernancePanel from './components/GovernancePanel';
import Navbar from './components/Navbar';
import './App.css';
function App() {
return (
<Web3Provider>
<Router>
<div className="App">
<Navbar />
<main className="main-content">
<Routes>
<Route path="/" element={<TokenDashboard />} />
<Route path="/governance" element={<GovernancePanel />} />
</Routes>
</main>
</div>
</Router>
</Web3Provider>
);
}
export default App;
3. DeFi Protocol mit Python und Web3.py
# defi_protocol.py
import json
import time
from web3 import Web3
from web3.contract import Contract
from web3.middleware import geth_poa_middleware
from eth_account import Account
from eth_utils import to_checksum_address
from decimal import Decimal
import logging
# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class DeFiProtocol:
"""
DeFi Protocol implementation for automated trading and liquidity management
"""
def __init__(self, provider_url, private_key=None):
"""
Initialize DeFi Protocol
Args:
provider_url: Web3 provider URL
private_key: Private key for transactions (optional)
"""
self.w3 = Web3(Web3.HTTPProvider(provider_url))
# Inject POA middleware for testnets
if self.w3.eth.chain_id in [3, 4, 5, 42, 80001]:
self.w3.middleware_onion.inject(geth_poa_middleware, layer=0)
self.account = None
if private_key:
self.account = Account.from_key(private_key)
self.w3.eth.default_account = self.account.address
# Contract addresses and ABIs
self.contracts = {}
self.load_contracts()
# Gas settings
self.gas_price = self.w3.eth.gas_price
self.gas_limit = 300000
def load_contracts(self):
"""Load contract ABIs and addresses"""
# Example contract ABIs (would normally load from files)
erc20_abi = [
{
"constant": True,
"inputs": [{"name": "_owner", "type": "address"}],
"name": "balanceOf",
"outputs": [{"name": "balance", "type": "uint256"}],
"type": "function"
},
{
"constant": False,
"inputs": [
{"name": "_to", "type": "address"},
{"name": "_value", "type": "uint256"}
],
"name": "transfer",
"outputs": [{"name": "", "type": "bool"}],
"type": "function"
},
{
"constant": False,
"inputs": [
{"name": "_spender", "type": "address"},
{"name": "_value", "type": "uint256"}
],
"name": "approve",
"outputs": [{"name": "", "type": "bool"}],
"type": "function"
}
]
uniswap_router_abi = [
{
"constant": False,
"inputs": [
{"name": "amountOutMin", "type": "uint256"},
{"name": "path", "type": "address[]"},
{"name": "to", "type": "address"},
{"name": "deadline", "type": "uint256"}
],
"name": "swapExactETHForTokens",
"outputs": [{"name": "amounts", "type": "uint256[]"}],
"type": "function"
},
{
"constant": False,
"inputs": [
{"name": "amountIn", "type": "uint256"},
{"name": "amountOutMin", "type": "uint256"},
{"name": "path", "type": "address[]"},
{"name": "to", "type": "address"},
{"name": "deadline", "type": "uint256"}
],
"name": "swapExactTokensForTokens",
"outputs": [{"name": "amounts", "type": "uint256[]"}],
"type": "function"
},
{
"constant": True,
"inputs": [
{"name": "amountIn", "type": "uint256"},
{"name": "reserveIn", "type": "uint256"},
{"name": "reserveOut", "type": "uint256"}
],
"name": "getAmountOut",
"outputs": [{"name": "amountOut", "type": "uint256"}],
"type": "function"
}
]
# Contract addresses (example for Ethereum Mainnet)
self.contract_addresses = {
'WETH': '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
'USDC': '0xA0b86a33E6441E7C1A785D1A97b7327c2c0c0c0c',
'DAI': '0x6B175474E89094C44Da98b954EedeAC495271d0F',
'UNISWAP_ROUTER': '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D',
'UNISWAP_FACTORY': '0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f'
}
# Initialize contracts
for name, address in self.contract_addresses.items():
if name in ['WETH', 'USDC', 'DAI']:
self.contracts[name] = self.w3.eth.contract(
address=address,
abi=erc20_abi
)
elif name == 'UNISWAP_ROUTER':
self.contracts[name] = self.w3.eth.contract(
address=address,
abi=uniswap_router_abi
)
def get_balance(self, token_symbol, address=None):
"""
Get token balance for address
Args:
token_symbol: Token symbol (e.g., 'ETH', 'USDC', 'DAI')
address: Address to check (default: current account)
Returns:
Token balance as Decimal
"""
if address is None:
if not self.account:
raise ValueError("No account specified")
address = self.account.address
if token_symbol == 'ETH':
balance_wei = self.w3.eth.get_balance(address)
return Decimal(balance_wei) / Decimal(10**18)
if token_symbol not in self.contracts:
raise ValueError(f"Unknown token: {token_symbol}")
contract = self.contracts[token_symbol]
balance_wei = contract.functions.balanceOf(address).call()
decimals = self.get_token_decimals(token_symbol)
return Decimal(balance_wei) / Decimal(10**decimals)
def get_token_decimals(self, token_symbol):
"""Get token decimals"""
decimals_map = {
'WETH': 18,
'USDC': 6,
'DAI': 18
}
return decimals_map.get(token_symbol, 18)
def approve_token(self, token_symbol, spender_address, amount):
"""
Approve token spending
Args:
token_symbol: Token symbol to approve
spender_address: Address to approve for
amount: Amount to approve (in human-readable format)
Returns:
Transaction hash
"""
if not self.account:
raise ValueError("No account configured")
if token_symbol not in self.contracts:
raise ValueError(f"Unknown token: {token_symbol}")
contract = self.contracts[token_symbol]
decimals = self.get_token_decimals(token_symbol)
amount_wei = int(Decimal(amount) * Decimal(10**decimals))
# Build transaction
transaction = contract.functions.approve(
spender_address,
amount_wei
).build_transaction({
'from': self.account.address,
'gas': self.gas_limit,
'gasPrice': self.gas_price,
'nonce': self.w3.eth.get_transaction_count(self.account.address)
})
# Sign and send transaction
signed_txn = self.w3.eth.account.sign_transaction(transaction, self.account.key)
tx_hash = self.w3.eth.send_raw_transaction(signed_txn.rawTransaction)
# Wait for confirmation
receipt = self.w3.eth.wait_for_transaction_receipt(tx_hash)
if receipt.status == 1:
logger.info(f"Token approved: {tx_hash.hex()}")
return tx_hash.hex()
else:
raise Exception("Transaction failed")
def swap_eth_for_tokens(self, eth_amount, token_symbol, slippage_percent=1):
"""
Swap ETH for tokens on Uniswap
Args:
eth_amount: Amount of ETH to swap
token_symbol: Target token symbol
slippage_percent: Maximum slippage percentage
Returns:
Transaction hash
"""
if not self.account:
raise ValueError("No account configured")
if token_symbol not in self.contract_addresses:
raise ValueError(f"Unknown token: {token_symbol}")
router = self.contracts['UNISWAP_ROUTER']
token_address = self.contract_addresses[token_symbol]
# Calculate minimum amount out with slippage
amount_out = self.get_swap_amount_out(eth_amount, 'ETH', token_symbol)
min_amount_out = int(amount_out * (1 - slippage_percent / 100))
# Build transaction
eth_amount_wei = int(Decimal(eth_amount) * Decimal(10**18))
deadline = int(time.time()) + 300 # 5 minutes
transaction = router.functions.swapExactETHForTokens(
min_amount_out,
[self.contract_addresses['WETH'], token_address],
self.account.address,
deadline
).build_transaction({
'from': self.account.address,
'value': eth_amount_wei,
'gas': self.gas_limit,
'gasPrice': self.gas_price,
'nonce': self.w3.eth.get_transaction_count(self.account.address)
})
# Sign and send transaction
signed_txn = self.w3.eth.account.sign_transaction(transaction, self.account.key)
tx_hash = self.w3.eth.send_raw_transaction(signed_txn.rawTransaction)
# Wait for confirmation
receipt = self.w3.eth.wait_for_transaction_receipt(tx_hash)
if receipt.status == 1:
logger.info(f"ETH swapped for {token_symbol}: {tx_hash.hex()}")
return tx_hash.hex()
else:
raise Exception("Transaction failed")
def swap_tokens_for_eth(self, token_symbol, token_amount, slippage_percent=1):
"""
Swap tokens for ETH on Uniswap
Args:
token_symbol: Token symbol to swap
token_amount: Amount of tokens to swap
slippage_percent: Maximum slippage percentage
Returns:
Transaction hash
"""
if not self.account:
raise ValueError("No account configured")
if token_symbol not in self.contract_addresses:
raise ValueError(f"Unknown token: {token_symbol}")
router = self.contracts['UNISWAP_ROUTER']
token_address = self.contract_addresses[token_symbol]
# Approve token spending
self.approve_token(token_symbol, self.contract_addresses['UNISWAP_ROUTER'], token_amount)
# Calculate minimum amount out with slippage
amount_out = self.get_swap_amount_out(token_amount, token_symbol, 'ETH')
min_amount_out = int(amount_out * (1 - slippage_percent / 100))
# Build transaction
decimals = self.get_token_decimals(token_symbol)
token_amount_wei = int(Decimal(token_amount) * Decimal(10**decimals))
deadline = int(time.time()) + 300 # 5 minutes
transaction = router.functions.swapExactTokensForTokens(
token_amount_wei,
min_amount_out,
[token_address, self.contract_addresses['WETH']],
self.account.address,
deadline
).build_transaction({
'from': self.account.address,
'gas': self.gas_limit,
'gasPrice': self.gas_price,
'nonce': self.w3.eth.get_transaction_count(self.account.address)
})
# Sign and send transaction
signed_txn = self.w3.eth.account.sign_transaction(transaction, self.account.key)
tx_hash = self.w3.eth.send_raw_transaction(signed_txn.rawTransaction)
# Wait for confirmation
receipt = self.w3.eth.wait_for_transaction_receipt(tx_hash)
if receipt.status == 1:
logger.info(f"{token_symbol} swapped for ETH: {tx_hash.hex()}")
return tx_hash.hex()
else:
raise Exception("Transaction failed")
def get_swap_amount_out(self, amount_in, token_in, token_out):
"""
Calculate amount out for swap (simplified)
Args:
amount_in: Amount to swap
token_in: Input token symbol
token_out: Output token symbol
Returns:
Expected amount out
"""
# This is a simplified calculation
# In production, you would query the actual pool reserves
# Example exchange rates (would be fetched from DEX)
exchange_rates = {
('ETH', 'USDC'): 2000, # 1 ETH = 2000 USDC
('ETH', 'DAI'): 2000, # 1 ETH = 2000 DAI
('USDC', 'ETH'): 0.0005, # 1 USDC = 0.0005 ETH
('DAI', 'ETH'): 0.0005, # 1 DAI = 0.0005 ETH
}
rate = exchange_rates.get((token_in, token_out))
if rate is None:
raise ValueError(f"No exchange rate for {token_in} -> {token_out}")
return Decimal(amount_in) * Decimal(rate)
def add_liquidity(self, token_symbol, token_amount, eth_amount):
"""
Add liquidity to Uniswap pool
Args:
token_symbol: Token symbol to add
token_amount: Amount of tokens to add
eth_amount: Amount of ETH to add
Returns:
Transaction hash
"""
if not self.account:
raise ValueError("No account configured")
# This would implement actual Uniswap liquidity addition
# For now, it's a placeholder
logger.info(f"Adding liquidity: {token_amount} {token_symbol} + {eth_amount} ETH")
# In production, you would:
# 1. Approve token spending
# 2. Call Uniswap router's addLiquidityETH function
# 3. Handle transaction and receipt
return "0xplaceholder"
def remove_liquidity(self, token_symbol, liquidity_amount):
"""
Remove liquidity from Uniswap pool
Args:
token_symbol: Token symbol of the pool
liquidity_amount: Amount of liquidity tokens to remove
Returns:
Transaction hash
"""
if not self.account:
raise ValueError("No account configured")
# This would implement actual Uniswap liquidity removal
logger.info(f"Removing liquidity: {liquidity_amount} from {token_symbol} pool")
# In production, you would:
# 1. Call Uniswap router's removeLiquidityETH function
# 2. Handle transaction and receipt
return "0xplaceholder"
def get_portfolio_value(self, address=None):
"""
Calculate total portfolio value in USD
Args:
address: Address to calculate for (default: current account)
Returns:
Portfolio value in USD
"""
if address is None:
if not self.account:
raise ValueError("No account specified")
address = self.account.address
# Get balances
eth_balance = self.get_balance('ETH', address)
usdc_balance = self.get_balance('USDC', address)
dai_balance = self.get_balance('DAI', address)
# Calculate USD value (simplified)
# In production, you would fetch real prices from oracles
eth_price_usd = 2000 # Example price
dai_price_usd = 1.0 # DAI is pegged to USD
portfolio_value = (
eth_balance * eth_price_usd +
usdc_balance +
dai_balance * dai_price_usd
)
return {
'total_value_usd': portfolio_value,
'breakdown': {
'ETH': {'amount': eth_balance, 'value_usd': eth_balance * eth_price_usd},
'USDC': {'amount': usdc_balance, 'value_usd': usdc_balance},
'DAI': {'amount': dai_balance, 'value_usd': dai_balance * dai_price_usd}
}
}
def monitor_gas_prices(self):
"""
Monitor current gas prices
Returns:
Current gas price in Gwei
"""
gas_price_wei = self.w3.eth.gas_price
gas_price_gwei = gas_price_wei / 10**9
return {
'gas_price_wei': gas_price_wei,
'gas_price_gwei': gas_price_gwei,
'estimated_eth_cost': gas_price_wei * self.gas_limit / 10**18
}
def execute_arbitrage(self, token_symbol, min_profit_percent=1):
"""
Execute arbitrage opportunity (simplified)
Args:
token_symbol: Token to arbitrage
min_profit_percent: Minimum profit percentage required
Returns:
Transaction hash if arbitrage executed
"""
# This is a simplified arbitrage implementation
# In production, you would:
# 1. Monitor prices across multiple DEXs
# 2. Calculate profit opportunities
# 3. Execute trades when profitable
logger.info(f"Checking arbitrage opportunities for {token_symbol}")
# Example: Check price difference between two DEXs
# This is placeholder logic
price_dex1 = self.get_swap_amount_out(1, 'ETH', token_symbol)
price_dex2 = self.get_swap_amount_out(1, 'ETH', token_symbol) * 1.02 # 2% difference
profit_percent = ((price_dex2 - price_dex1) / price_dex1) * 100
if profit_percent >= min_profit_percent:
logger.info(f"Arbitrage opportunity found: {profit_percent:.2f}% profit")
# Execute arbitrage trades
return "0xarbitrage_placeholder"
return None
# Usage example
def main():
"""Example usage of DeFi Protocol"""
# Initialize protocol
provider_url = "https://mainnet.infura.io/v3/YOUR_PROJECT_ID"
private_key = "YOUR_PRIVATE_KEY" # Be careful with private keys!
protocol = DeFiProtocol(provider_url, private_key)
# Get portfolio value
portfolio = protocol.get_portfolio_value()
print(f"Portfolio Value: ${portfolio['total_value_usd']:.2f}")
# Check gas prices
gas_info = protocol.monitor_gas_prices()
print(f"Gas Price: {gas_info['gas_price_gwei']:.2f} Gwei")
# Swap ETH for USDC
try:
tx_hash = protocol.swap_eth_for_tokens(0.1, 'USDC', slippage_percent=1)
print(f"Swap transaction: {tx_hash}")
except Exception as e:
print(f"Swap failed: {e}")
# Check for arbitrage opportunities
arbitrage_tx = protocol.execute_arbitrage('USDC', min_profit_percent=1)
if arbitrage_tx:
print(f"Arbitrage executed: {arbitrage_tx}")
if __name__ == "__main__":
main()
Web3 Architektur
DeFi Ecosystem
graph TD
A[User] --> B[Wallet]
B --> C[DApp Frontend]
C --> D[Web3.js/Ethers.js]
D --> E[Smart Contracts]
E --> F[DeFi Protocols]
F --> G[DEX]
F --> H[Lending]
F --> I[Yield Farming]
F --> J[Liquidity Pools]
E --> K[Blockchain]
K --> L[Ethereum]
K --> M[Polygon]
K --> N[BSC]
O[Oracles] --> E
P[Chainlink] --> O
Q[Band Protocol] --> O
R[Governance] --> E
S[DAO] --> R
T[Token Holders] --> R
Smart Contract Security
Common Vulnerabilities
| Vulnerability | Beschreibung | Schutzmaßnahme |
|---|---|---|
| Reentrancy | Recursive calls before state update | ReentrancyGuard, Checks-Effects-Interactions |
| Integer Overflow | Arithmetic overflow/underflow | SafeMath, Solidity 0.8+ |
| Access Control | Unauthorized function calls | Modifiers, Role-based access |
| Front-Running | Transaction order manipulation | Commit-reveal schemes |
| Oracle Manipulation | Price feed manipulation | Decentralized oracles |
DeFi Protocols Vergleich
Leading DeFi Categories
| Kategorie | Protokolle | Funktion | TVL (Billion $) |
|---|---|---|---|
| DEX | Uniswap, SushiSwap | Token Swaps | 25+ |
| Lending | Aave, Compound | Kredite | 20+ |
| Yield | Yearn, Harvest | Yield Optimization | 10+ |
| Derivatives | Synthetix, Perpetual | Derivatives | 5+ |
| Oracle | Chainlink, Band | Price Feeds | 15+ |
Vorteile und Nachteile
Vorteile von Web3/DeFi
- Dezentralisierung: Keine zentrale Instanz erforderlich
- Transparenz: Alle Transaktionen sind öffentlich sichtbar
- Permissionless: Jeder kann teilnehmen ohne Genehmigung
- Programmierbarkeit: Smart Contracts ermöglichen komplexe Logik
- Composability: Protokolle können kombiniert werden
Nachteile
- Skalierbarkeit: Begrenzte Transaktionsdurchsatz
- Gas Fees: Hohe Transaktionskosten bei Netzwerklast
- User Experience: Komplexe Wallet-Integration
- Security Risks: Smart Contract Vulnerabilities
- Regulatory Uncertainty: Ungewisse regulatorische Lage
Häufige Prüfungsfragen
-
Was ist der Unterschied zwischen Web2 und Web3? Web2 ist zentralisiert mit Servern, Web3 ist dezentralisiert mit Blockchain und Smart Contracts.
-
Erklären Sie Smart Contracts! Smart Contracts sind selbstausführende Verträge auf der Blockchain, die Business Logic ohne Zwischenhändler ausführen.
-
Wann verwendet man DeFi Protokolle? DeFi Protokolle werden für dezentrale Finanzdienstleistungen wie Trading, Lending und Yield Farming verwendet.
-
Was sind die Hauptvorteile von Blockchain? Dezentralisierung, Transparenz, Unveränderlichkeit und Sicherheit durch Kryptographie.