blockchain-expert by personamanagmentlayer/pcl
npx skills add https://github.com/personamanagmentlayer/pcl --skill blockchain-expert为区块链开发、智能合约、Web3 应用程序、DeFi 协议和加密货币系统提供专家指导。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
contract SimpleToken is ERC20, Ownable, ReentrancyGuard {
uint256 public constant MAX_SUPPLY = 1000000 * 10**18;
mapping(address => bool) public minters;
event MinterAdded(address indexed minter);
event MinterRemoved(address indexed minter);
modifier onlyMinter() {
require(minters[msg.sender], "Not a minter");
_;
}
constructor() ERC20("SimpleToken", "SMPL") {
minters[msg.sender] = true;
}
function mint(address to, uint256 amount) external onlyMinter {
require(totalSupply() + amount <= MAX_SUPPLY, "Max supply exceeded");
_mint(to, amount);
}
function burn(uint256 amount) external {
_burn(msg.sender, amount);
}
function addMinter(address minter) external onlyOwner {
minters[minter] = true;
emit MinterAdded(minter);
}
function removeMinter(address minter) external onlyOwner {
minters[minter] = false;
emit MinterRemoved(minter);
}
}
// Staking Contract
contract StakingPool is ReentrancyGuard {
IERC20 public stakingToken;
IERC20 public rewardToken;
uint256 public rewardRate = 100; // Reward tokens per second
uint256 public lastUpdateTime;
uint256 public rewardPerTokenStored;
mapping(address => uint256) public userRewardPerTokenPaid;
mapping(address => uint256) public rewards;
mapping(address => uint256) public balances;
uint256 private _totalSupply;
constructor(address _stakingToken, address _rewardToken) {
stakingToken = IERC20(_stakingToken);
rewardToken = IERC20(_rewardToken);
}
function rewardPerToken() public view returns (uint256) {
if (_totalSupply == 0) {
return rewardPerTokenStored;
}
return rewardPerTokenStored +
(((block.timestamp - lastUpdateTime) * rewardRate * 1e18) / _totalSupply);
}
function earned(address account) public view returns (uint256) {
return ((balances[account] *
(rewardPerToken() - userRewardPerTokenPaid[account])) / 1e18) +
rewards[account];
}
modifier updateReward(address account) {
rewardPerTokenStored = rewardPerToken();
lastUpdateTime = block.timestamp;
if (account != address(0)) {
rewards[account] = earned(account);
userRewardPerTokenPaid[account] = rewardPerTokenStored;
}
_;
}
function stake(uint256 amount) external nonReentrant updateReward(msg.sender) {
require(amount > 0, "Cannot stake 0");
_totalSupply += amount;
balances[msg.sender] += amount;
stakingToken.transferFrom(msg.sender, address(this), amount);
}
function withdraw(uint256 amount) external nonReentrant updateReward(msg.sender) {
require(amount > 0, "Cannot withdraw 0");
_totalSupply -= amount;
balances[msg.sender] -= amount;
stakingToken.transfer(msg.sender, amount);
}
function getReward() external nonReentrant updateReward(msg.sender) {
uint256 reward = rewards[msg.sender];
if (reward > 0) {
rewards[msg.sender] = 0;
rewardToken.transfer(msg.sender, reward);
}
}
}
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
// Simple Automated Market Maker (like Uniswap)
contract SimpleAMM is ReentrancyGuard {
IERC20 public token0;
IERC20 public token1;
uint256 public reserve0;
uint256 public reserve1;
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
event Swap(address indexed user, address tokenIn, uint256 amountIn, uint256 amountOut);
event AddLiquidity(address indexed user, uint256 amount0, uint256 amount1);
event RemoveLiquidity(address indexed user, uint256 amount0, uint256 amount1);
constructor(address _token0, address _token1) {
token0 = IERC20(_token0);
token1 = IERC20(_token1);
}
function addLiquidity(uint256 amount0, uint256 amount1)
external
nonReentrant
returns (uint256 shares)
{
token0.transferFrom(msg.sender, address(this), amount0);
token1.transferFrom(msg.sender, address(this), amount1);
if (totalSupply == 0) {
shares = sqrt(amount0 * amount1);
} else {
shares = min(
(amount0 * totalSupply) / reserve0,
(amount1 * totalSupply) / reserve1
);
}
require(shares > 0, "Shares = 0");
_mint(msg.sender, shares);
_update(
token0.balanceOf(address(this)),
token1.balanceOf(address(this))
);
emit AddLiquidity(msg.sender, amount0, amount1);
}
function removeLiquidity(uint256 shares)
external
nonReentrant
returns (uint256 amount0, uint256 amount1)
{
uint256 balance0 = token0.balanceOf(address(this));
uint256 balance1 = token1.balanceOf(address(this));
amount0 = (shares * balance0) / totalSupply;
amount1 = (shares * balance1) / totalSupply;
require(amount0 > 0 && amount1 > 0, "Amount = 0");
_burn(msg.sender, shares);
_update(balance0 - amount0, balance1 - amount1);
token0.transfer(msg.sender, amount0);
token1.transfer(msg.sender, amount1);
emit RemoveLiquidity(msg.sender, amount0, amount1);
}
function swap(address tokenIn, uint256 amountIn)
external
nonReentrant
returns (uint256 amountOut)
{
require(tokenIn == address(token0) || tokenIn == address(token1), "Invalid token");
bool isToken0 = tokenIn == address(token0);
(IERC20 tokenIn_, IERC20 tokenOut, uint256 reserveIn, uint256 reserveOut) =
isToken0
? (token0, token1, reserve0, reserve1)
: (token1, token0, reserve1, reserve0);
tokenIn_.transferFrom(msg.sender, address(this), amountIn);
// 0.3% fee
uint256 amountInWithFee = (amountIn * 997) / 1000;
// x * y = k formula
amountOut = (reserveOut * amountInWithFee) / (reserveIn + amountInWithFee);
tokenOut.transfer(msg.sender, amountOut);
_update(
token0.balanceOf(address(this)),
token1.balanceOf(address(this))
);
emit Swap(msg.sender, tokenIn, amountIn, amountOut);
}
function _mint(address to, uint256 amount) private {
balanceOf[to] += amount;
totalSupply += amount;
}
function _burn(address from, uint256 amount) private {
balanceOf[from] -= amount;
totalSupply -= amount;
}
function _update(uint256 _reserve0, uint256 _reserve1) private {
reserve0 = _reserve0;
reserve1 = _reserve1;
}
function sqrt(uint256 y) private pure returns (uint256 z) {
if (y > 3) {
z = y;
uint256 x = y / 2 + 1;
while (x < z) {
z = x;
x = (y / x + x) / 2;
}
} else if (y != 0) {
z = 1;
}
}
function min(uint256 x, uint256 y) private pure returns (uint256) {
return x <= y ? x : y;
}
}
import { ethers } from 'ethers';
import { Contract, Provider, Signer } from 'ethers';
class Web3Client {
private provider: Provider;
private signer?: Signer;
constructor(rpcUrl: string) {
this.provider = new ethers.JsonRpcProvider(rpcUrl);
}
async connectWallet(): Promise<string> {
// Connect to MetaMask
if (typeof window.ethereum !== 'undefined') {
const provider = new ethers.BrowserProvider(window.ethereum);
await provider.send("eth_requestAccounts", []);
this.signer = await provider.getSigner();
return await this.signer.getAddress();
}
throw new Error('No wallet found');
}
async getBalance(address: string): Promise<string> {
const balance = await this.provider.getBalance(address);
return ethers.formatEther(balance);
}
async sendTransaction(to: string, amount: string): Promise<string> {
if (!this.signer) throw new Error('Wallet not connected');
const tx = await this.signer.sendTransaction({
to,
value: ethers.parseEther(amount)
});
const receipt = await tx.wait();
return receipt?.hash || '';
}
getContract(address: string, abi: any[]): Contract {
return new ethers.Contract(
address,
abi,
this.signer || this.provider
);
}
async callContract(
contractAddress: string,
abi: any[],
method: string,
args: any[]
): Promise<any> {
const contract = this.getContract(contractAddress, abi);
return await contract[method](...args);
}
async estimateGas(
contractAddress: string,
abi: any[],
method: string,
args: any[]
): Promise<bigint> {
const contract = this.getContract(contractAddress, abi);
return await contract[method].estimateGas(...args);
}
}
uint256 而非更小的类型calldata❌ 无重入保护 ❌ 未检查的外部调用 ❌ 使用 tx.origin 进行授权 ❌ 浮动的 pragma 版本 ❌ 无访问控制 ❌ 在链上存储敏感数据 ❌ 未考虑 Gas 限制
每周安装量
102
代码仓库
GitHub 星标数
11
首次出现
2026年1月24日
安全审计
安装于
opencode73
codex71
gemini-cli66
cursor61
github-copilot61
claude-code58
Expert guidance for blockchain development, smart contracts, Web3 applications, DeFi protocols, and cryptocurrency systems.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
contract SimpleToken is ERC20, Ownable, ReentrancyGuard {
uint256 public constant MAX_SUPPLY = 1000000 * 10**18;
mapping(address => bool) public minters;
event MinterAdded(address indexed minter);
event MinterRemoved(address indexed minter);
modifier onlyMinter() {
require(minters[msg.sender], "Not a minter");
_;
}
constructor() ERC20("SimpleToken", "SMPL") {
minters[msg.sender] = true;
}
function mint(address to, uint256 amount) external onlyMinter {
require(totalSupply() + amount <= MAX_SUPPLY, "Max supply exceeded");
_mint(to, amount);
}
function burn(uint256 amount) external {
_burn(msg.sender, amount);
}
function addMinter(address minter) external onlyOwner {
minters[minter] = true;
emit MinterAdded(minter);
}
function removeMinter(address minter) external onlyOwner {
minters[minter] = false;
emit MinterRemoved(minter);
}
}
// Staking Contract
contract StakingPool is ReentrancyGuard {
IERC20 public stakingToken;
IERC20 public rewardToken;
uint256 public rewardRate = 100; // Reward tokens per second
uint256 public lastUpdateTime;
uint256 public rewardPerTokenStored;
mapping(address => uint256) public userRewardPerTokenPaid;
mapping(address => uint256) public rewards;
mapping(address => uint256) public balances;
uint256 private _totalSupply;
constructor(address _stakingToken, address _rewardToken) {
stakingToken = IERC20(_stakingToken);
rewardToken = IERC20(_rewardToken);
}
function rewardPerToken() public view returns (uint256) {
if (_totalSupply == 0) {
return rewardPerTokenStored;
}
return rewardPerTokenStored +
(((block.timestamp - lastUpdateTime) * rewardRate * 1e18) / _totalSupply);
}
function earned(address account) public view returns (uint256) {
return ((balances[account] *
(rewardPerToken() - userRewardPerTokenPaid[account])) / 1e18) +
rewards[account];
}
modifier updateReward(address account) {
rewardPerTokenStored = rewardPerToken();
lastUpdateTime = block.timestamp;
if (account != address(0)) {
rewards[account] = earned(account);
userRewardPerTokenPaid[account] = rewardPerTokenStored;
}
_;
}
function stake(uint256 amount) external nonReentrant updateReward(msg.sender) {
require(amount > 0, "Cannot stake 0");
_totalSupply += amount;
balances[msg.sender] += amount;
stakingToken.transferFrom(msg.sender, address(this), amount);
}
function withdraw(uint256 amount) external nonReentrant updateReward(msg.sender) {
require(amount > 0, "Cannot withdraw 0");
_totalSupply -= amount;
balances[msg.sender] -= amount;
stakingToken.transfer(msg.sender, amount);
}
function getReward() external nonReentrant updateReward(msg.sender) {
uint256 reward = rewards[msg.sender];
if (reward > 0) {
rewards[msg.sender] = 0;
rewardToken.transfer(msg.sender, reward);
}
}
}
// Simple Automated Market Maker (like Uniswap)
contract SimpleAMM is ReentrancyGuard {
IERC20 public token0;
IERC20 public token1;
uint256 public reserve0;
uint256 public reserve1;
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
event Swap(address indexed user, address tokenIn, uint256 amountIn, uint256 amountOut);
event AddLiquidity(address indexed user, uint256 amount0, uint256 amount1);
event RemoveLiquidity(address indexed user, uint256 amount0, uint256 amount1);
constructor(address _token0, address _token1) {
token0 = IERC20(_token0);
token1 = IERC20(_token1);
}
function addLiquidity(uint256 amount0, uint256 amount1)
external
nonReentrant
returns (uint256 shares)
{
token0.transferFrom(msg.sender, address(this), amount0);
token1.transferFrom(msg.sender, address(this), amount1);
if (totalSupply == 0) {
shares = sqrt(amount0 * amount1);
} else {
shares = min(
(amount0 * totalSupply) / reserve0,
(amount1 * totalSupply) / reserve1
);
}
require(shares > 0, "Shares = 0");
_mint(msg.sender, shares);
_update(
token0.balanceOf(address(this)),
token1.balanceOf(address(this))
);
emit AddLiquidity(msg.sender, amount0, amount1);
}
function removeLiquidity(uint256 shares)
external
nonReentrant
returns (uint256 amount0, uint256 amount1)
{
uint256 balance0 = token0.balanceOf(address(this));
uint256 balance1 = token1.balanceOf(address(this));
amount0 = (shares * balance0) / totalSupply;
amount1 = (shares * balance1) / totalSupply;
require(amount0 > 0 && amount1 > 0, "Amount = 0");
_burn(msg.sender, shares);
_update(balance0 - amount0, balance1 - amount1);
token0.transfer(msg.sender, amount0);
token1.transfer(msg.sender, amount1);
emit RemoveLiquidity(msg.sender, amount0, amount1);
}
function swap(address tokenIn, uint256 amountIn)
external
nonReentrant
returns (uint256 amountOut)
{
require(tokenIn == address(token0) || tokenIn == address(token1), "Invalid token");
bool isToken0 = tokenIn == address(token0);
(IERC20 tokenIn_, IERC20 tokenOut, uint256 reserveIn, uint256 reserveOut) =
isToken0
? (token0, token1, reserve0, reserve1)
: (token1, token0, reserve1, reserve0);
tokenIn_.transferFrom(msg.sender, address(this), amountIn);
// 0.3% fee
uint256 amountInWithFee = (amountIn * 997) / 1000;
// x * y = k formula
amountOut = (reserveOut * amountInWithFee) / (reserveIn + amountInWithFee);
tokenOut.transfer(msg.sender, amountOut);
_update(
token0.balanceOf(address(this)),
token1.balanceOf(address(this))
);
emit Swap(msg.sender, tokenIn, amountIn, amountOut);
}
function _mint(address to, uint256 amount) private {
balanceOf[to] += amount;
totalSupply += amount;
}
function _burn(address from, uint256 amount) private {
balanceOf[from] -= amount;
totalSupply -= amount;
}
function _update(uint256 _reserve0, uint256 _reserve1) private {
reserve0 = _reserve0;
reserve1 = _reserve1;
}
function sqrt(uint256 y) private pure returns (uint256 z) {
if (y > 3) {
z = y;
uint256 x = y / 2 + 1;
while (x < z) {
z = x;
x = (y / x + x) / 2;
}
} else if (y != 0) {
z = 1;
}
}
function min(uint256 x, uint256 y) private pure returns (uint256) {
return x <= y ? x : y;
}
}
import { ethers } from 'ethers';
import { Contract, Provider, Signer } from 'ethers';
class Web3Client {
private provider: Provider;
private signer?: Signer;
constructor(rpcUrl: string) {
this.provider = new ethers.JsonRpcProvider(rpcUrl);
}
async connectWallet(): Promise<string> {
// Connect to MetaMask
if (typeof window.ethereum !== 'undefined') {
const provider = new ethers.BrowserProvider(window.ethereum);
await provider.send("eth_requestAccounts", []);
this.signer = await provider.getSigner();
return await this.signer.getAddress();
}
throw new Error('No wallet found');
}
async getBalance(address: string): Promise<string> {
const balance = await this.provider.getBalance(address);
return ethers.formatEther(balance);
}
async sendTransaction(to: string, amount: string): Promise<string> {
if (!this.signer) throw new Error('Wallet not connected');
const tx = await this.signer.sendTransaction({
to,
value: ethers.parseEther(amount)
});
const receipt = await tx.wait();
return receipt?.hash || '';
}
getContract(address: string, abi: any[]): Contract {
return new ethers.Contract(
address,
abi,
this.signer || this.provider
);
}
async callContract(
contractAddress: string,
abi: any[],
method: string,
args: any[]
): Promise<any> {
const contract = this.getContract(contractAddress, abi);
return await contract[method](...args);
}
async estimateGas(
contractAddress: string,
abi: any[],
method: string,
args: any[]
): Promise<bigint> {
const contract = this.getContract(contractAddress, abi);
return await contract[method].estimateGas(...args);
}
}
uint256 over smaller typescalldata for function parameters❌ No reentrancy protection ❌ Unchecked external calls ❌ Using tx.origin for authorization ❌ Floating pragma versions ❌ No access control ❌ Storing sensitive data on-chain ❌ No gas limit considerations
Weekly Installs
102
Repository
GitHub Stars
11
First Seen
Jan 24, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykWarn
Installed on
opencode73
codex71
gemini-cli66
cursor61
github-copilot61
claude-code58
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
116,600 周安装
SpecStory 历史文件整理工具 - 按时间戳自动归档会话文件,保持项目目录整洁
101 周安装
OMC Doctor:Claude代码助手安装诊断与修复工具 - 解决OMC插件问题
101 周安装
微信文章转Markdown工具 - 高效抓取公众号文章并转换为Markdown格式,支持存档与AI处理
101 周安装
Go语言技术文档编写指南 - 专业API设计与文档生成技能
101 周安装
Mermaid图表专家技能 - 专业流程图、序列图、甘特图代码生成与可视化指南
101 周安装
销售自动化工具 - 冷邮件序列、跟进计划、话术模板与A/B测试完整指南
101 周安装