Skills · Coding

Defi Protocol Templates

Unverified31/40

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

Originally by wshobson · MIT

Claude CodePartialHas SKILL.md but declares no allowed-tools — Claude Code will ask for permission each time
CursorPartialPlain prose you can paste in — but no Cursor rules file
CodexPartialPlain prose you can paste in — but no AGENTS.md
Gemini CLIPartialPlain prose you can paste in
CopilotPartialPlain prose you can paste in — but no Copilot instructions file
npx agentalley add defi-protocol-templates

This command does not work yet — the CLI is still being built. Until then, use Raw in the reader below to take the file.

Who is stuck, and on what

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

The whole source

No sign-in, no blur, nothing truncated
defi-protocol-templates/SKILL.md237 lines7.3 KBRawView on GitHub
Frontmatter — 2 properties
namedefi-protocol-templates
descriptionImplement DeFi protocols with production-ready templates for staking, AMMs, governance, and flash loans. Use when building decentralized finance applications or smart contract protocols.
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---A5No allowed-tools declared — no way to tell what this skill may touch
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 

Reviews

Installed this one?Write the first review and take the Trailblazer badge.

Reviews only open after a real install, so this is empty — and we leave it empty rather than invent one.

Alternatives

Also in Coding