NYC
skills/personamanagmentlayer/pcl/blockchain-expert

blockchain-expert

SKILL.md

Blockchain Expert

Expert guidance for blockchain development, smart contracts, Web3 applications, DeFi protocols, and cryptocurrency systems.

Core Concepts

Blockchain Fundamentals

  • Distributed ledger technology
  • Consensus mechanisms (PoW, PoS, PoA)
  • Cryptographic hashing
  • Public/private key cryptography
  • Transaction validation
  • Block structure and chain

Smart Contracts

  • Solidity programming
  • Gas optimization
  • Security patterns
  • Upgradeable contracts
  • Testing and auditing
  • Contract interactions

Web3 & DeFi

  • Decentralized applications (dApps)
  • DeFi protocols (AMM, lending, staking)
  • NFTs and token standards
  • Layer 2 solutions
  • Cross-chain bridges
  • Wallet integration

Smart Contract Development

// 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);
        }
    }
}

DeFi: AMM Implementation

// 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;
    }
}

Web3 Integration

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);
    }
}

Best Practices

Smart Contract Security

  • Use OpenZeppelin contracts for standards
  • Implement reentrancy guards
  • Check for integer overflow/underflow (use Solidity 0.8+)
  • Validate all inputs
  • Use pull over push for payments
  • Implement circuit breakers for emergencies
  • Comprehensive testing and auditing

Gas Optimization

  • Use uint256 over smaller types
  • Pack storage variables
  • Use calldata for function parameters
  • Minimize storage operations
  • Use events for data that doesn't need on-chain storage
  • Batch operations when possible

Development

  • Use Hardhat/Foundry for development
  • Write comprehensive tests
  • Use test networks before mainnet
  • Implement upgrade patterns carefully
  • Monitor contract events
  • Document all functions

Anti-Patterns

❌ 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

Resources

Weekly Installs
45
First Seen
Jan 24, 2026
Installed on
claude-code31
opencode26
codex22
gemini-cli19
github-copilot15
antigravity14