Implement DeFi protocols with production-ready templates

Defi protocol templates

by wshobson · MIT license · ★ 39,857 on GitHub · updated Sep 21

Defi protocol templates cover

Implement DeFi protocols with production-ready templates for staking, AMMs, governance, and flash loans. Use when building decentralized finance applications or smart contract protocols.

---
name: defi-protocol-templates
description: Implement DeFi protocols with production-ready templates for staking, AMMs, governance, and flash loans. Use when building decentralized finance applications or smart contract protocols.
---

# DeFi Protocol Templates

Production-ready templates for common DeFi protocols including staking, AMMs, governance, and flash loans.

## When to Use This Skill

- Building staking platforms with reward distribution
- Implementing AMM (Automated Market Maker) protocols
- Creating governance token systems
- Integrating flash loan functionality

## Staking Contract

Overview

Production-ready templates for common DeFi protocols including staking, AMMs, governance, and flash loans.

Manual install (npx, ZIP)
Claude Codenpx skills add wshobson/agents --skill defi-protocol-templates -g -a claude-code
Claude Code (manual)mkdir -p ~/.claude/skills && curl -sL https://codeload.github.com/wshobson/agents/tar.gz/4236bb91f839 \ | tar -xz -C ~/.claude/skills --strip-components=4 agents-4236bb91f839/plugins/blockchain-web3/skills/defi-protocol-templates
Windows (PowerShell)New-Item -ItemType Directory -Force "$HOME\.claude\skills" | Out-Null; Invoke-WebRequest "https://m.agentalley.io/zip/0bd30c283a75c6f012de/defi-protocol-templates.zip" -OutFile "$env:TEMP\defi-protocol-templates.zip"; Expand-Archive "$env:TEMP\defi-protocol-templates.zip" -DestinationPath "$HOME\.claude\skills" -Force
Claude.ai / desktopDownload the ZIP and upload it under Settings → Capabilities → Skills.
Codex, Cursor, other agentsPoint them at SKILL.md. The other files are plain text.

Connects with Agent Alley MCP · agentalley.io/mcp

Files included

  • SKILL.md7.3 KB
  • references/1 file · 5.5 KB
Read the files here
wshobson/4236bb92 files
SKILL.md
Show the full text237 lines

DeFi Protocol Templates

Production-ready templates for common DeFi protocols including staking, AMMs, governance, and flash loans.

When to Use This Skill

  • Building staking platforms with reward distribution
  • Implementing AMM (Automated Market Maker) protocols
  • Creating governance token systems
  • Integrating flash loan functionality

Staking Contract

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract StakingRewards is ReentrancyGuard, Ownable {
    IERC20 public stakingToken;
    IERC20 public rewardsToken;

    uint256 public rewardRate = 100; // Rewards 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;

    event Staked(address indexed user, uint256 amount);
    event Withdrawn(address indexed user, uint256 amount);
    event RewardPaid(address indexed user, uint256 reward);

    constructor(address _stakingToken, address _rewardsToken) {
        stakingToken = IERC20(_stakingToken);
        rewardsToken = IERC20(_rewardsToken);
    }

    modifier updateReward(address account) {
        rewardPerTokenStored = rewardPerToken();
        lastUpdateTime = block.timestamp;

        if (account != address(0)) {
            rewards[account] = earned(account);
            userRewardPerTokenPaid[account] = rewardPerTokenStored;
        }
        _;
    }

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

    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);
        emit Staked(msg.sender, amount);
    }

    function withdraw(uint256 amount) public nonReentrant updateReward(msg.sender) {
        require(amount > 0, "Cannot withdraw 0");
        _totalSupply -= amount;
        balances[msg.sender] -= amount;
        stakingToken.transfer(msg.sender, amount);
        emit Withdrawn(msg.sender, amount);
    }

    function getReward() public nonReentrant updateReward(msg.sender) {
        uint256 reward = rewards[msg.sender];
        if (reward > 0) {
            rewards[msg.sender] = 0;
            rewardsToken.transfer(msg.sender, reward);
            emit RewardPaid(msg.sender, reward);
        }
    }

    function exit() external {
        withdraw(balances[msg.sender]);
        getReward();
    }
}

AMM (Automated Market Maker)

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

contract SimpleAMM {
    IERC20 public token0;
    IERC20 public token1;

    uint256 public reserve0;
    uint256 public reserve1;

    uint256 public totalSupply;
    mapping(address => uint256) public balanceOf;

    event Mint(address indexed to, uint256 amount);
    event Burn(address indexed from, uint256 amount);
    event Swap(address indexed trader, uint256 amount0In, uint256 amount1In, uint256 amount0Out, uint256 amount1Out);

    constructor(address _token0, address _token1) {
        token0 = IERC20(_token0);
        token1 = IERC20(_token1);
    }

    function addLiquidity(uint256 amount0, uint256 amount1) external 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 Mint(msg.sender, shares);
    }

    function removeLiquidity(uint256 shares) external returns (uint256 amount0, uint256 amount1) {
        uint256 bal0 = token0.balanceOf(address(this));
        uint256 bal1 = token1.balanceOf(address(this));

        amount0 = (shares * bal0) / totalSupply;
        amount1 = (shares * bal1) / totalSupply;

        require(amount0 > 0 && amount1 > 0, "Amount0 or amount1 = 0");

        _burn(msg.sender, shares);
        _update(bal0 - amount0, bal1 - amount1);

        token0.transfer(msg.sender, amount0);
        token1.transfer(msg.sender, amount1);

        emit Burn(msg.sender, shares);
    }

    function swap(address tokenIn, uint256 amountIn) external returns (uint256 amountOut) {
        require(tokenIn == address(token0) || tokenIn == address(token1), "Invalid token");

        bool isToken0 = tokenIn == address(token0);
        (IERC20 tokenIn_, IERC20 tokenOut, uint256 resIn, uint256 resOut) = isToken0
            ? (token0, token1, reserve0, reserve1)
            : (token1, token0, reserve1, reserve0);

        tokenIn_.transferFrom(msg.sender, address(this), amountIn);

        // 0.3% fee
        uint256 amountInWithFee = (amountIn * 997) / 1000;
        amountOut = (resOut * amountInWithFee) / (resIn + amountInWithFee);

        tokenOut.transfer(msg.sender, amountOut);

        _update(
            token0.balanceOf(address(this)),
            token1.balanceOf(address(this))
        );

        emit Swap(msg.sender, isToken0 ? amountIn : 0, isToken0 ? 0 : amountIn, isToken0 ? 0 : amountOut, isToken0 ? amountOut : 0);
    }

    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 res0, uint256 res1) private {
        reserve0 = res0;
        reserve1 = res1;
    }

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

Additional patterns and templates

More detailed templates and worked examples live in references/details.md. Read that file for the full pattern library.

1---
2name: defi-protocol-templates
3description: Implement DeFi protocols with production-ready templates for staking, AMMs, governance, and flash loans. Use when building decentralized finance applications or smart contract protocols.
4---
5 
6# DeFi Protocol Templates
7 
8Production-ready templates for common DeFi protocols including staking, AMMs, governance, and flash loans.
9 
10## When to Use This Skill
11 
12- Building staking platforms with reward distribution
13- Implementing AMM (Automated Market Maker) protocols
14- Creating governance token systems
15- Integrating flash loan functionality
16 
17## Staking Contract
18 
19```solidity
20// SPDX-License-Identifier: MIT
21pragma solidity ^0.8.0;
22 
23import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
24import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
25import "@openzeppelin/contracts/access/Ownable.sol";
26 
27contract StakingRewards is ReentrancyGuard, Ownable {
28 IERC20 public stakingToken;
29 IERC20 public rewardsToken;
30 
31 uint256 public rewardRate = 100; // Rewards per second
32 uint256 public lastUpdateTime;
33 uint256 public rewardPerTokenStored;
34 
35 mapping(address => uint256) public userRewardPerTokenPaid;
36 mapping(address => uint256) public rewards;
37 mapping(address => uint256) public balances;
38 
39 uint256 private _totalSupply;
40 
41 event Staked(address indexed user, uint256 amount);
42 event Withdrawn(address indexed user, uint256 amount);
43 event RewardPaid(address indexed user, uint256 reward);
44 
45 constructor(address _stakingToken, address _rewardsToken) {
46 stakingToken = IERC20(_stakingToken);
47 rewardsToken = IERC20(_rewardsToken);
48 }
49 
50 modifier updateReward(address account) {
51 rewardPerTokenStored = rewardPerToken();
52 lastUpdateTime = block.timestamp;
53 
54 if (account != address(0)) {
55 rewards[account] = earned(account);
56 userRewardPerTokenPaid[account] = rewardPerTokenStored;
57 }
58 _;
59 }
60 
61 function rewardPerToken() public view returns (uint256) {
62 if (_totalSupply == 0) {
63 return rewardPerTokenStored;
64 }
65 return rewardPerTokenStored +
66 ((block.timestamp - lastUpdateTime) * rewardRate * 1e18) / _totalSupply;
67 }
68 
69 function earned(address account) public view returns (uint256) {
70 return (balances[account] *
71 (rewardPerToken() - userRewardPerTokenPaid[account])) / 1e18 +
72 rewards[account];
73 }
74 
75 function stake(uint256 amount) external nonReentrant updateReward(msg.sender) {
76 require(amount > 0, "Cannot stake 0");
77 _totalSupply += amount;
78 balances[msg.sender] += amount;
79 stakingToken.transferFrom(msg.sender, address(this), amount);
80 emit Staked(msg.sender, amount);
81 }
82 
83 function withdraw(uint256 amount) public nonReentrant updateReward(msg.sender) {
84 require(amount > 0, "Cannot withdraw 0");
85 _totalSupply -= amount;
86 balances[msg.sender] -= amount;
87 stakingToken.transfer(msg.sender, amount);
88 emit Withdrawn(msg.sender, amount);
89 }
90 
91 function getReward() public nonReentrant updateReward(msg.sender) {
92 uint256 reward = rewards[msg.sender];
93 if (reward > 0) {
94 rewards[msg.sender] = 0;
95 rewardsToken.transfer(msg.sender, reward);
96 emit RewardPaid(msg.sender, reward);
97 }
98 }
99 
100 function exit() external {
101 withdraw(balances[msg.sender]);
102 getReward();
103 }
104}
105```
106 
107## AMM (Automated Market Maker)
108 
109```solidity
110// SPDX-License-Identifier: MIT
111pragma solidity ^0.8.0;
112 
113import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
114 
115contract SimpleAMM {
116 IERC20 public token0;
117 IERC20 public token1;
118 
119 uint256 public reserve0;
120 uint256 public reserve1;
121 
122 uint256 public totalSupply;
123 mapping(address => uint256) public balanceOf;
124 
125 event Mint(address indexed to, uint256 amount);
126 event Burn(address indexed from, uint256 amount);
127 event Swap(address indexed trader, uint256 amount0In, uint256 amount1In, uint256 amount0Out, uint256 amount1Out);
128 
129 constructor(address _token0, address _token1) {
130 token0 = IERC20(_token0);
131 token1 = IERC20(_token1);
132 }
133 
134 function addLiquidity(uint256 amount0, uint256 amount1) external returns (uint256 shares) {
135 token0.transferFrom(msg.sender, address(this), amount0);
136 token1.transferFrom(msg.sender, address(this), amount1);
137 
138 if (totalSupply == 0) {
139 shares = sqrt(amount0 * amount1);
140 } else {
141 shares = min(
142 (amount0 * totalSupply) / reserve0,
143 (amount1 * totalSupply) / reserve1
144 );
145 }
146 
147 require(shares > 0, "Shares = 0");
148 _mint(msg.sender, shares);
149 _update(
150 token0.balanceOf(address(this)),
151 token1.balanceOf(address(this))
152 );
153 
154 emit Mint(msg.sender, shares);
155 }
156 
157 function removeLiquidity(uint256 shares) external returns (uint256 amount0, uint256 amount1) {
158 uint256 bal0 = token0.balanceOf(address(this));
159 uint256 bal1 = token1.balanceOf(address(this));
160 
161 amount0 = (shares * bal0) / totalSupply;
162 amount1 = (shares * bal1) / totalSupply;
163 
164 require(amount0 > 0 && amount1 > 0, "Amount0 or amount1 = 0");
165 
166 _burn(msg.sender, shares);
167 _update(bal0 - amount0, bal1 - amount1);
168 
169 token0.transfer(msg.sender, amount0);
170 token1.transfer(msg.sender, amount1);
171 
172 emit Burn(msg.sender, shares);
173 }
174 
175 function swap(address tokenIn, uint256 amountIn) external returns (uint256 amountOut) {
176 require(tokenIn == address(token0) || tokenIn == address(token1), "Invalid token");
177 
178 bool isToken0 = tokenIn == address(token0);
179 (IERC20 tokenIn_, IERC20 tokenOut, uint256 resIn, uint256 resOut) = isToken0
180 ? (token0, token1, reserve0, reserve1)
181 : (token1, token0, reserve1, reserve0);
182 
183 tokenIn_.transferFrom(msg.sender, address(this), amountIn);
184 
185 // 0.3% fee
186 uint256 amountInWithFee = (amountIn * 997) / 1000;
187 amountOut = (resOut * amountInWithFee) / (resIn + amountInWithFee);
188 
189 tokenOut.transfer(msg.sender, amountOut);
190 
191 _update(
192 token0.balanceOf(address(this)),
193 token1.balanceOf(address(this))
194 );
195 
196 emit Swap(msg.sender, isToken0 ? amountIn : 0, isToken0 ? 0 : amountIn, isToken0 ? 0 : amountOut, isToken0 ? amountOut : 0);
197 }
198 
199 function _mint(address to, uint256 amount) private {
200 balanceOf[to] += amount;
201 totalSupply += amount;
202 }
203 
204 function _burn(address from, uint256 amount) private {
205 balanceOf[from] -= amount;
206 totalSupply -= amount;
207 }
208 
209 function _update(uint256 res0, uint256 res1) private {
210 reserve0 = res0;
211 reserve1 = res1;
212 }
213 
214 function sqrt(uint256 y) private pure returns (uint256 z) {
215 if (y > 3) {
216 z = y;
217 uint256 x = y / 2 + 1;
218 while (x < z) {
219 z = x;
220 x = (y / x + x) / 2;
221 }
222 } else if (y != 0) {
223 z = 1;
224 }
225 }
226 
227 function min(uint256 x, uint256 y) private pure returns (uint256) {
228 return x <= y ? x : y;
229 }
230}
231```
232 
233## Additional patterns and templates
234 
235More detailed templates and worked examples live in `references/details.md`. Read that file for the full pattern library.
236 
237 
View all files on GitHub →

Details

Updated
Sep 21, 2026
License
MIT
Stars on the repo
★ 39,857
Checked
Source
wshobson/agents ↗
Creator
wshobson · 179 listings
View creator

Similar skills

See all →
MCPAgent-native x402 pay-per-call data & security APIs on BaseX402 data APIrezearcher/x402-data-api · by rezearcherAgent-native x402 pay-per-call data & security APIs on Base (crypto, DeFi, on-chain, Polymarket, MCP security scan)New listingSkillImplement NFT standards with proper metadata handlingwshobson/agents · by wshobsonImplement NFT standards (ERC-721, ERC-1155) with proper metadata handling, minting strategies, and marketplace integration. Use when creating NFT contracts, building NFT marketplaces, or implementing digital asset systems.★ 39.9k GitHub starsSkillMaster smart contract security best practices to preventSolidity securitywshobson/agents · by wshobsonMaster smart contract security best practices to prevent common vulnerabilities and implement secure Solidity patterns. Use when writing smart contracts, auditing existing contracts, or implementing security measures for blockchain applications.★ 39.9k GitHub starsSkillTest smart contracts comprehensively using HardhatWeb3 Smart Contract Testingwshobson/agents · by wshobsonTest smart contracts comprehensively using Hardhat and Foundry with unit tests, integration tests, and mainnet forking. Use when testing Solidity contracts, setting up blockchain test suites, or validating DeFi protocols.★ 39.9k GitHub starsMCPBuilding smart contracts, DAppsBlockchain developerVoltAgent/awesome-claude-code-subagents · by VoltAgentUse this agent when building smart contracts, DApps, and blockchain protocols that require expertise in Solidity, gas optimization, security auditing, and Web3 integration.★ 25.2k GitHub starsSkillRequires technical rigor and verificationCode Review Receptionobra/superpowers · by obraUse when receiving code review feedback, before implementing suggestions, especially if feedback seems unclear or technically questionable - requires technical rigor and verification, not performative agreement or blind implementation★ 290k GitHub stars

More from wshobson

SkillMaster C/.NET backend development patterns for buildingwshobson/agents · by wshobsonMaster C#/.NET backend development patterns for building robust APIs, MCP servers, and enterprise applications. Covers async/await, dependency injection, Entity Framework Core, Dapper, configuration, caching, and testing with xUnit. Use when developing .NET backends, reviewing C# code, or designing API architectures.★ 39.9k GitHub starsSkillImplement WCAG 2.2 compliant interfaces with mobileAccessibility compliancewshobson/agents · by wshobsonImplement WCAG 2.2 compliant interfaces with mobile accessibility, inclusive design patterns, and assistive technology support. Use when auditing accessibility, implementing ARIA patterns, building for screen readers, or ensuring inclusive user experiences.★ 39.9k GitHub starsSkillMaster Material Design 3 and Jetpack Compose patternsAndroid Mobile Designwshobson/agents · by wshobsonMaster Material Design 3 and Jetpack Compose patterns for building native Android apps. Use when designing Android interfaces, implementing Compose UI, or following Google's Material Design guidelines.★ 39.9k GitHub starsSkillMigrate from AngularJS to Angular using hybrid modeAngular migrationwshobson/agents · by wshobsonMigrate from AngularJS to Angular using hybrid mode, incremental component rewriting, and dependency injection updates. Use when upgrading AngularJS applications, planning framework migrations, or modernizing legacy Angular code.★ 39.9k GitHub starsSkillUnderstand anti-reversing, obfuscationAnti reversing techniqueswshobson/agents · by wshobsonUnderstand anti-reversing, obfuscation, and protection techniques encountered during software analysis. Use this skill when analyzing malware evasion techniques, when implementing anti-debugging protections for CTF challenges, when reverse engineering packed binaries, or when building security research tools that need to detect virtualized environments.★ 39.9k GitHub starsSkillBuild production Apache Airflow DAGs with best practicesApache Airflow DAG Patternswshobson/agents · by wshobsonBuild production Apache Airflow DAGs with best practices for operators, sensors, testing, and deployment. Use when creating data pipelines, orchestrating workflows, or scheduling batch jobs.★ 39.9k GitHub stars