
Defi Protocol Templates
Bootstrap Solidity patterns for DeFi primitives such as governance tokens and on-chain governors instead of writing ERC20Votes and proposal flows from scratch.
Install
npx skills add https://github.com/wshobson/agents --skill defi-protocol-templatesWhat is this skill?
- GovernanceToken example using OpenZeppelin ERC20Votes, ERC20Permit, and Ownable with mint supply pattern
- Governor contract sketch with proposals, for/against votes, voting period, and proposal threshold
- SPDX and pragma ^0.8.0 patterns aligned with modern Solidity tooling
- Additional DeFi protocol templates beyond governance in the full skill readme
- Copy-paste starting points for agent-assisted Solidity iteration and audits
Adoption & trust: 6.8k installs on skills.sh; 36.5k GitHub stars; 2/3 security scanners passed (skills.sh audits).
Recommended Skills
Solana Devsolana-foundation/solana-dev-skill
Solidity Securitywshobson/agents
Emblem Ai Agent Walletemblemcompany/emblemai-agentwallet
Emblem Portfolio Trackeremblemcompany/agent-skills
Emblem Defi Yieldemblemcompany/agent-skills
Emblem Memecoin Scoutemblemcompany/agent-skills
Journey fit
Primary fit
Smart-contract templates are implementation work in the Build phase once you have scoped a protocol or tokenized product. Backend subphase is the canonical shelf for contract logic, voting modules, and protocol scaffolding rather than wallet UI.
Common Questions / FAQ
Is Defi Protocol Templates safe to install?
skills.sh reports 2 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.
SKILL.md
READMESKILL.md - Defi Protocol Templates
# defi-protocol-templates — additional patterns and templates ## Governance Token ```solidity // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; contract GovernanceToken is ERC20Votes, Ownable { constructor() ERC20("Governance Token", "GOV") ERC20Permit("Governance Token") { _mint(msg.sender, 1000000 * 10**decimals()); } function _afterTokenTransfer( address from, address to, uint256 amount ) internal override(ERC20Votes) { super._afterTokenTransfer(from, to, amount); } function _mint(address to, uint256 amount) internal override(ERC20Votes) { super._mint(to, amount); } function _burn(address account, uint256 amount) internal override(ERC20Votes) { super._burn(account, amount); } } contract Governor is Ownable { GovernanceToken public governanceToken; struct Proposal { uint256 id; address proposer; string description; uint256 forVotes; uint256 againstVotes; uint256 startBlock; uint256 endBlock; bool executed; mapping(address => bool) hasVoted; } uint256 public proposalCount; mapping(uint256 => Proposal) public proposals; uint256 public votingPeriod = 17280; // ~3 days in blocks uint256 public proposalThreshold = 100000 * 10**18; event ProposalCreated(uint256 indexed proposalId, address proposer, string description); event VoteCast(address indexed voter, uint256 indexed proposalId, bool support, uint256 weight); event ProposalExecuted(uint256 indexed proposalId); constructor(address _governanceToken) { governanceToken = GovernanceToken(_governanceToken); } function propose(string memory description) external returns (uint256) { require( governanceToken.getPastVotes(msg.sender, block.number - 1) >= proposalThreshold, "Proposer votes below threshold" ); proposalCount++; Proposal storage newProposal = proposals[proposalCount]; newProposal.id = proposalCount; newProposal.proposer = msg.sender; newProposal.description = description; newProposal.startBlock = block.number; newProposal.endBlock = block.number + votingPeriod; emit ProposalCreated(proposalCount, msg.sender, description); return proposalCount; } function vote(uint256 proposalId, bool support) external { Proposal storage proposal = proposals[proposalId]; require(block.number >= proposal.startBlock, "Voting not started"); require(block.number <= proposal.endBlock, "Voting ended"); require(!proposal.hasVoted[msg.sender], "Already voted"); uint256 weight = governanceToken.getPastVotes(msg.sender, proposal.startBlock); require(weight > 0, "No voting power"); proposal.hasVoted[msg.sender] = true; if (support) { proposal.forVotes += weight; } else { proposal.againstVotes += weight; } emit VoteCast(msg.sender, proposalId, support, weight); } function execute(uint256 proposalId) external { Proposal storage proposal = proposals[proposalId]; require(block.number > proposal.endBlock, "Voting not ended"); require(!proposal.executed, "Already executed"); require(proposal.forVotes > proposal.againstVotes, "Proposal failed"); proposal.executed = true; // Execute proposal logic here emit ProposalExecuted(proposalId); } } ``` ## Flash Loan ```solidity // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; interface IFlashLoanReceiver { function executeOperation( address asset, uint256 amount, uint256 fee, bytes calldata params