Skip to main content 홈 크리에이터 bobmatnyc mcp-skillset web3-blockchain-development
web3-blockchain-development Production-grade Web3 development with Solidity smart contracts, ethers.js/web3.js integration, DApp architecture, security patterns, and AI-enhanced blockchain development (ChatWeb3, Aider + Gemini 2024)
설치로 이동 Skills Marketplace 커뮤니티가 만든 AI 스킬을 발견하고 탐색하세요.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/bobmatnyc/mcp-skillset --skill web3-blockchain-development명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
Zip 다운로드 다운로드 중... name Web3 & Blockchain Development skill_id web3-blockchain version 1.0.0 description Production-grade Web3 development with Solidity smart contracts, ethers.js/web3.js integration, DApp architecture, security patterns, and AI-enhanced blockchain development (ChatWeb3, Aider + Gemini 2024) category Blockchain & Web3 tags ["web3","blockchain","solidity","ethereum","smart-contracts","dapp","ethers","hardhat","security","defi"] author mcp-skillset license MIT created 2025-11-25T00:00:00.000Z last_updated 2025-11-25T00:00:00.000Z toolchain ["Solidity 0.8+","Hardhat","ethers.js v6","OpenZeppelin Contracts"] frameworks ["Ethereum","Hardhat","Foundry","OpenZeppelin"] related_skills ["security-testing","test-driven-development","fastapi-web-development","cloudflare-edge-ai"]
Web3 & Blockchain Development
Overview
Master Web3 development with Solidity smart contracts, DApp architecture, and modern tooling (Hardhat, ethers.js v6). Learn security-first patterns, gas optimization, and AI-enhanced development with ChatWeb3 and Aider + Gemini for Solidity (2024).
When to Use This Skill
Building decentralized applications (DApps) on Ethereum
Writing secure smart contracts for DeFi, NFTs, or DAOs
Creating token contracts (ERC-20, ERC-721, ERC-1155)
Integrating blockchain functionality into web applications
Auditing smart contracts for security vulnerabilities
Optimizing gas costs for efficient contract execution
Deploying contracts to mainnet or Layer 2 networks
Core Principles
1. Solidity Security Patterns
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/security/Pausable.sol";
// ✅ GOOD: Security-first contract
contract SecureWallet is ReentrancyGuard, Ownable, Pausable {
mapping(address => uint256) public balances;
event Deposit(address indexed user, uint256 amount);
event Withdrawal(address indexed user, uint256 amount);
// ✅ Use receive() for accepting Ether
receive() external payable {
balances[msg.sender] += msg.value;
emit Deposit(msg.sender, msg.value);
}
// ✅ Checks-Effects-Interactions pattern (prevents reentrancy)
function withdraw(uint256 amount) external nonReentrant whenNotPaused {
// Checks
require(amount > 0, "Amount must be greater than 0");
require(balances[msg.sender] >= amount, "Insufficient balance");
// Effects (update state BEFORE external call)
balances[msg.sender] -= amount;
// Interactions (external call last)
(bool success, ) = msg.sender.call{value: amount}("");
require(success, "Transfer failed");
emit Withdrawal(msg.sender, amount);
}
// ✅ Emergency stop mechanism
function pause() external onlyOwner {
_pause();
}
function unpause() external onlyOwner {
_unpause();
}
}
// ❌ BAD: Vulnerable to reentrancy attack
contract VulnerableWallet {
mapping(address => uint256) public balances;
function withdraw(uint256 amount) external {
require(balances[msg.sender] >= amount);
// ❌ WRONG: External call before state update
(bool success, ) = msg.sender.call{value: amount}("");
require(success);
// Attacker can re-enter withdraw() before this line executes!
balances[msg.sender] -= amount;
}
}
Common Vulnerabilities (SWC Registry) :
Reentrancy (SWC-107) - Use ReentrancyGuard
Integer Overflow/Underflow (SWC-101) - Solidity 0.8+ has built-in checks
Unchecked Call Return Values (SWC-104) - Always check success
Unprotected Ether Withdrawal (SWC-105) - Use access control
Delegatecall to Untrusted Callee (SWC-112) - Avoid or whitelist
Timestamp Dependence (SWC-116) - Don't rely on block.timestamp for randomness
2. ERC Token Standards // ERC-20 Token (Fungible Token)
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract MyToken is ERC20, Ownable {
constructor() ERC20("MyToken", "MTK") {
_mint(msg.sender, 1000000 * 10 ** decimals());
}
// Optional: Mint new tokens
function mint(address to, uint256 amount) external onlyOwner {
_mint(to, amount);
}
}
// ERC-721 NFT (Non-Fungible Token)
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
contract MyNFT is ERC721, ERC721URIStorage, Ownable {
uint256 private _tokenIdCounter;
constructor() ERC721("MyNFT", "MNFT") {}
function safeMint(address to, string memory uri) external onlyOwner {
uint256 tokenId = _tokenIdCounter++;
_safeMint(to, tokenId);
_setTokenURI(tokenId, uri);
}
// Override required by Solidity
function tokenURI(uint256 tokenId)
public
view
override(ERC721, ERC721URIStorage)
returns (string memory)
{
return super.tokenURI(tokenId);
}
function supportsInterface(bytes4 interfaceId)
public
view
override(ERC721, ERC721URIStorage)
returns (bool)
{
return super.supportsInterface(interfaceId);
}
}
// ERC-1155 (Multi-Token Standard)
import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";
contract GameItems is ERC1155, Ownable {
uint256 public constant GOLD = 0;
uint256 public constant SILVER = 1;
uint256 public constant SWORD = 2;
constructor() ERC1155("https://game.example/api/item/{id}.json") {
_mint(msg.sender, GOLD, 10**18, "");
_mint(msg.sender, SILVER, 10**27, "");
_mint(msg.sender, SWORD, 1, "");
}
function mint(address account, uint256 id, uint256 amount)
external
onlyOwner
{
_mint(account, id, amount, "");
}
}
3. Gas Optimization Techniques // ❌ BAD: Expensive storage operations
contract Expensive {
uint256[] public numbers;
function addNumbers(uint256[] memory nums) external {
for (uint256 i = 0; i < nums.length; i++) {
numbers.push(nums[i]); // SSTORE every iteration (expensive!)
}
}
}
// ✅ GOOD: Batch operations and minimize SSTORE
contract Optimized {
uint256[] public numbers;
function addNumbers(uint256[] memory nums) external {
uint256 length = nums.length; // Cache array length
for (uint256 i; i < length; ) { // Skip initialization (i = 0)
numbers.push(nums[i]);
unchecked { ++i; } // Skip overflow check (safe here)
}
}
}
// ✅ Use uint256 (native word size) instead of smaller types
uint256 a; // Cheaper than uint8, uint16, etc.
// ✅ Pack storage variables
struct User {
address wallet; // 20 bytes
uint96 balance; // 12 bytes (fits in same slot)
uint32 lastUpdate; // 4 bytes (fits in same slot)
bool isActive; // 1 byte (fits in same slot)
} // Total: 1 storage slot (32 bytes) instead of 4 slots!
// ✅ Use events instead of storage for historical data
event Transfer(address indexed from, address indexed to, uint256 amount);
// ✅ Use immutable and constant
address public immutable OWNER; // Set in constructor, cheaper than storage
uint256 public constant MAX_SUPPLY = 1000000; // Compile-time constant
// ✅ Short-circuit evaluations
require(msg.sender == owner || balances[msg.sender] > 0); // Cheap check first
// ✅ Use calldata for read-only function parameters
function process(uint256[] calldata data) external {
// calldata is cheaper than memory for external functions
}
SLOAD (read storage): 2,100 gas
SSTORE (write storage): 20,000 gas (first time), 5,000 gas (subsequent)
CALL (external call): 2,600 gas
Memory operations: 3 gas per 32 bytes
4. DApp Frontend Integration (ethers.js v6) import { ethers } from 'ethers' ;
const provider = new ethers.BrowserProvider (window .ethereum );
await provider.send ("eth_requestAccounts" , []);
const signer = await provider.getSigner ();
const contractAddress = "0x..." ;
const abi = [
"function balanceOf(address owner) view returns (uint256)" ,
"function transfer(address to, uint256 amount) returns (bool)" ,
"event Transfer(address indexed from, address indexed to, uint256 amount)"
];
const contract = new ethers.Contract (contractAddress, abi, signer);
const balance = await contract.balanceOf (signer.address );
console .log (`Balance: ${ethers.formatEther(balance)} ETH` );
const tx = await contract.transfer (
"0xRecipientAddress" ,
ethers.parseEther ("1.0" )
);
const receipt = await tx.wait ();
console .log (`Transaction confirmed in block ${receipt.blockNumber} ` );
contract.on ("Transfer" , (from , to, amount, event ) => {
console .log (`Transfer: ${from } -> ${to} : ${ethers.formatEther(amount)} ETH` );
});
import { MyToken __factory } from './typechain-types' ;
const typedContract = MyToken __factory.connect (contractAddress, signer);
5. Testing with Hardhat
import { expect } from "chai" ;
import { ethers } from "hardhat" ;
import { MyToken } from "../typechain-types" ;
describe ("MyToken" , function ( ) {
let token : MyToken ;
let owner : any ;
let addr1 : any ;
beforeEach (async function ( ) {
[owner, addr1] = await ethers.getSigners ();
const TokenFactory = await ethers.getContractFactory ("MyToken" );
token = await TokenFactory .deploy ();
await token.waitForDeployment ();
});
it ("Should assign total supply to owner" , async function ( ) {
const ownerBalance = await token.balanceOf (owner.address );
expect (await token.totalSupply ()).to .equal (ownerBalance);
});
it ("Should transfer tokens between accounts" , async function ( ) {
const amount = ethers.parseEther ("50" );
await token.transfer (addr1.address , amount);
expect (await token.balanceOf (addr1.address )).to .equal (amount);
});
it ("Should fail if sender doesn't have enough tokens" , async function ( ) {
const amount = ethers.parseEther ("1000000" );
await expect (
token.connect (addr1).transfer (owner.address , amount)
).to .be .revertedWith ("ERC20: transfer amount exceeds balance" );
});
it ("Should emit Transfer event" , async function ( ) {
const amount = ethers.parseEther ("50" );
await expect (token.transfer (addr1.address , amount))
.to .emit (token, "Transfer" )
.withArgs (owner.address , addr1.address , amount);
});
});
Best Practices
Project Structure (Hardhat) blockchain-project/
├── contracts/
│ ├── MyToken.sol
│ ├── MyNFT.sol
│ └── interfaces/
│ └── IMyToken.sol
├── test/
│ ├── MyToken.test.ts
│ └── MyNFT.test.ts
├── scripts/
│ ├── deploy.ts
│ └── verify.ts
├── hardhat.config.ts
├── .env
├── .gitignore
└── package.json
Deployment Script
import { ethers } from "hardhat" ;
async function main ( ) {
const [deployer] = await ethers.getSigners ();
console .log ("Deploying contracts with:" , deployer.address );
const balance = await ethers.provider .getBalance (deployer.address );
console .log ("Account balance:" , ethers.formatEther (balance));
const TokenFactory = await ethers.getContractFactory ("MyToken" );
const token = await TokenFactory .deploy ();
await token.waitForDeployment ();
console .log ("Token deployed to:" , await token.getAddress ());
if (process.env .ETHERSCAN_API_KEY ) {
console .log ("Waiting for block confirmations..." );
await token.deploymentTransaction ()?.wait (6 );
console .log ("Verifying contract on Etherscan..." );
await run ("verify:verify" , {
address : await token.getAddress (),
constructorArguments : [],
});
}
}
main ().catch ((error ) => {
console .error (error);
process.exitCode = 1 ;
});
Hardhat Configuration
import { HardhatUserConfig } from "hardhat/config" ;
import "@nomicfoundation/hardhat-toolbox" ;
import "dotenv/config" ;
const config : HardhatUserConfig = {
solidity : {
version : "0.8.20" ,
settings : {
optimizer : {
enabled : true ,
runs : 200 ,
},
},
},
networks : {
hardhat : {
chainId : 31337 ,
},
sepolia : {
url : process.env .SEPOLIA_RPC_URL || "" ,
accounts : process.env .PRIVATE_KEY ? [process.env .PRIVATE_KEY ] : [],
},
mainnet : {
url : process.env .MAINNET_RPC_URL || "" ,
accounts : process.env .PRIVATE_KEY ? [process.env .PRIVATE_KEY ] : [],
},
},
etherscan : {
apiKey : process.env .ETHERSCAN_API_KEY ,
},
gasReporter : {
enabled : process.env .REPORT_GAS === "true" ,
currency : "USD" ,
coinmarketcap : process.env .COINMARKETCAP_API_KEY ,
},
};
export default config;
Common Patterns
Upgradeable Contracts (Proxy Pattern) // Using OpenZeppelin Upgradeable
import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
contract MyTokenV1 is Initializable, ERC20Upgradeable {
function initialize() public initializer {
__ERC20_init("MyToken", "MTK");
_mint(msg.sender, 1000000 * 10 ** decimals());
}
// No constructor! Use initialize() instead
}
// Deploy with hardhat-upgrades plugin
import { ethers, upgrades } from "hardhat";
const TokenV1 = await ethers.getContractFactory("MyTokenV1");
const proxy = await upgrades.deployProxy(TokenV1, [], { initializer: 'initialize' });
Oracle Integration (Chainlink) import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
contract PriceConsumer {
AggregatorV3Interface internal priceFeed;
constructor() {
// ETH/USD on Sepolia
priceFeed = AggregatorV3Interface(
0x694AA1769357215DE4FAC081bf1f309aDC325306
);
}
function getLatestPrice() public view returns (int) {
(, int price, , , ) = priceFeed.latestRoundData();
return price;
}
}
Security Auditing Tools
pip3 install slither-analyzer
slither ./contracts
pip3 install mythril
myth analyze contracts/MyToken.sol
docker run -v $(pwd ):/code trailofbits/echidna /code/contracts/MyToken.sol
forge install
forge test --match-test invariant
AI-Enhanced Web3 Development (2024) ChatWeb3 (conversational Solidity assistant):
- Natural language to Solidity code generation
- Security pattern recommendations
- Gas optimization suggestions
Aider + Google Gemini for Solidity:
- Context-aware code completion
- Vulnerability detection during development
- Refactoring assistance
Usage: "Write a secure ERC-20 token with vesting schedule"
→ Generates OpenZeppelin-based contract with best practices
Anti-Patterns
❌ DON'T: Use tx.origin for authentication // BAD: Vulnerable to phishing attacks
function withdraw() external {
require(tx.origin == owner); // ❌ NEVER!
// ...
}
// GOOD: Use msg.sender
function withdraw() external {
require(msg.sender == owner); // ✅
// ...
}
❌ DON'T: Use block.timestamp for randomness // BAD: Miners can manipulate
uint256 random = uint256(keccak256(abi.encodePacked(block.timestamp)));
// GOOD: Use Chainlink VRF for secure randomness
❌ DON'T: Ignore return values // BAD: Unchecked external call
address(target).call(data);
// GOOD: Check success
(bool success, ) = address(target).call(data);
require(success, "Call failed");
Related Skills
security-testing : Audit smart contracts for vulnerabilities
test-driven-development : Write tests before contract implementation
fastapi-web-development : Build Web3 backend APIs
cloudflare-edge-ai : Deploy Web3 frontends at the edge
Additional Resources
Example Questions
"Write a secure ERC-20 token contract with minting"
"How do I prevent reentrancy attacks?"
"Show me how to optimize gas costs in this contract"
"Integrate Chainlink price feed into my DeFi contract"
"Write tests for this NFT contract with Hardhat"
"Deploy this contract to Sepolia testnet"
"Audit this contract for security vulnerabilities"