[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-7fa94747-ba1e-4a54-ad6b-fa354cdf5831":3,"$f0JdZzBP7ukX9H5BbbU6RY5x9RxX5Q1DHpDfsspwkY7Q":43},{"id":4,"title":5,"description":6,"categoryId":7,"moduleId":8,"tags":9,"prompt":10,"icon":11,"source":12,"sourceUrl":13,"authorId":14,"authorName":15,"isPublic":16,"stars":17,"runs":18,"createdAt":19,"updatedAt":19,"module":20,"category":27,"packages":34},"7fa94747-ba1e-4a54-ad6b-fa354cdf5831","defi-protocol-templates","实现适用于质押、AMM、治理和借贷系统的生产级模板的DeFi协议。用于构建去中心化金融应用或智能合约协议。","cat_life_career","mod_other","sickn33,other","---\nname: defi-protocol-templates\ndescription: \"Implement DeFi protocols with production-ready templates for staking, AMMs, governance, and lending systems. Use when building decentralized finance applications or smart contract protocols.\"\nrisk: unknown\nsource: community\ndate_added: \"2026-02-27\"\n---\n\n# DeFi Protocol Templates\n\nProduction-ready templates for common DeFi protocols including staking, AMMs, governance, lending, and flash loans.\n\n## Do not use this skill when\n\n- The task is unrelated to defi protocol templates\n- You need a different domain or tool outside this scope\n\n## Instructions\n\n- Clarify goals, constraints, and required inputs.\n- Apply relevant best practices and validate outcomes.\n- Provide actionable steps and verification.\n- If detailed examples are required, open `resources\u002Fimplementation-playbook.md`.\n\n## Use this skill when\n\n- Building staking platforms with reward distribution\n- Implementing AMM (Automated Market Maker) protocols\n- Creating governance token systems\n- Developing lending\u002Fborrowing protocols\n- Integrating flash loan functionality\n- Launching yield farming platforms\n\n## Staking Contract\n\n```solidity\n\u002F\u002F SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin\u002Fcontracts\u002Ftoken\u002FERC20\u002FIERC20.sol\";\nimport \"@openzeppelin\u002Fcontracts\u002Fsecurity\u002FReentrancyGuard.sol\";\nimport \"@openzeppelin\u002Fcontracts\u002Faccess\u002FOwnable.sol\";\n\ncontract StakingRewards is ReentrancyGuard, Ownable {\n    IERC20 public stakingToken;\n    IERC20 public rewardsToken;\n\n    uint256 public rewardRate = 100; \u002F\u002F Rewards per second\n    uint256 public lastUpdateTime;\n    uint256 public rewardPerTokenStored;\n\n    mapping(address => uint256) public userRewardPerTokenPaid;\n    mapping(address => uint256) public rewards;\n    mapping(address => uint256) public balances;\n\n    uint256 private _totalSupply;\n\n    event Staked(address indexed user, uint256 amount);\n    event Withdrawn(address indexed user, uint256 amount);\n    event RewardPaid(address indexed user, uint256 reward);\n\n    constructor(address _stakingToken, address _rewardsToken) {\n        stakingToken = IERC20(_stakingToken);\n        rewardsToken = IERC20(_rewardsToken);\n    }\n\n    modifier updateReward(address account) {\n        rewardPerTokenStored = rewardPerToken();\n        lastUpdateTime = block.timestamp;\n\n        if (account != address(0)) {\n            rewards[account] = earned(account);\n            userRewardPerTokenPaid[account] = rewardPerTokenStored;\n        }\n        _;\n    }\n\n    function rewardPerToken() public view returns (uint256) {\n        if (_totalSupply == 0) {\n            return rewardPerTokenStored;\n        }\n        return rewardPerTokenStored +\n            ((block.timestamp - lastUpdateTime) * rewardRate * 1e18) \u002F _totalSupply;\n    }\n\n    function earned(address account) public view returns (uint256) {\n        return (balances[account] *\n            (rewardPerToken() - userRewardPerTokenPaid[account])) \u002F 1e18 +\n            rewards[account];\n    }\n\n    function stake(uint256 amount) external nonReentrant updateReward(msg.sender) {\n        require(amount > 0, \"Cannot stake 0\");\n        _totalSupply += amount;\n        balances[msg.sender] += amount;\n        stakingToken.transferFrom(msg.sender, address(this), amount);\n        emit Staked(msg.sender, amount);\n    }\n\n    function withdraw(uint256 amount) public nonReentrant updateReward(msg.sender) {\n        require(amount > 0, \"Cannot withdraw 0\");\n        _totalSupply -= amount;\n        balances[msg.sender] -= amount;\n        stakingToken.transfer(msg.sender, amount);\n        emit Withdrawn(msg.sender, amount);\n    }\n\n    function getReward() public nonReentrant updateReward(msg.sender) {\n        uint256 reward = rewards[msg.sender];\n        if (reward > 0) {\n            rewards[msg.sender] = 0;\n            rewardsToken.transfer(msg.sender, reward);\n            emit RewardPaid(msg.sender, reward);\n        }\n    }\n\n    function exit() external {\n        withdraw(balances[msg.sender]);\n        getReward();\n    }\n}\n```\n\n## AMM (Automated Market Maker)\n\n```solidity\n\u002F\u002F SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin\u002Fcontracts\u002Ftoken\u002FERC20\u002FIERC20.sol\";\n\ncontract SimpleAMM {\n    IERC20 public token0;\n    IERC20 public token1;\n\n    uint256 public reserve0;\n    uint256 public reserve1;\n\n    uint256 public totalSupply;\n    mapping(address => uint256) public balanceOf;\n\n    event Mint(address indexed to, uint256 amount);\n    event Burn(address indexed from, uint256 amount);\n    event Swap(address indexed trader, uint256 amount0In, uint256 amount1In, uint256 amount0Out, uint256 amount1Out);\n\n    constructor(address _token0, address _token1) {\n        token0 = IERC20(_token0);\n        token1 = IERC20(_token1);\n    }\n\n    function addLiquidity(uint256 amount0, uint256 amount1) external returns (uint256 shares) {\n        token0.transferFrom(msg.sender, address(this), amount0);\n        token1.transferFrom(msg.sender, address(this), amount1);\n\n        if (totalSupply == 0) {\n            shares = sqrt(amount0 * amount1);\n        } else {\n            shares = min(\n                (amount0 * totalSupply) \u002F reserve0,\n                (amount1 * totalSupply) \u002F reserve1\n            );\n        }\n\n        require(shares > 0, \"Shares = 0\");\n        _mint(msg.sender, shares);\n        _update(\n            token0.balanceOf(address(this)),\n            token1.balanceOf(address(this))\n        );\n\n        emit Mint(msg.sender, shares);\n    }\n\n    function removeLiquidity(uint256 shares) external returns (uint256 amount0, uint256 amount1) {\n        uint256 bal0 = token0.balanceOf(address(this));\n        uint256 bal1 = token1.balanceOf(address(this));\n\n        amount0 = (shares * bal0) \u002F totalSupply;\n        amount1 = (shares * bal1) \u002F totalSupply;\n\n        require(amount0 > 0 && amount1 > 0, \"Amount0 or amount1 = 0\");\n\n        _burn(msg.sender, shares);\n        _update(bal0 - amount0, bal1 - amount1);\n\n        token0.transfer(msg.sender, amount0);\n        token1.transfer(msg.sender, amount1);\n\n        emit Burn(msg.sender, shares);\n    }\n\n    function swap(address tokenIn, uint256 amountIn) external returns (uint256 amountOut) {\n        require(tokenIn == address(token0) || tokenIn == address(token1), \"Invalid token\");\n\n        bool isToken0 = tokenIn == address(token0);\n        (IERC20 tokenIn_, IERC20 tokenOut, uint256 resIn, uint256 resOut) = isToken0\n            ? (token0, token1, reserve0, reserve1)\n            : (token1, token0, reserve1, reserve0);\n\n        tokenIn_.transferFrom(msg.sender, address(this), amountIn);\n\n        \u002F\u002F 0.3% fee\n        uint256 amountInWithFee = (amountIn * 997) \u002F 1000;\n        amountOut = (resOut * amountInWithFee) \u002F (resIn + amountInWithFee);\n\n        tokenOut.transfer(msg.sender, amountOut);\n\n        _update(\n            token0.balanceOf(address(this)),\n            token1.balanceOf(address(this))\n        );\n\n        emit Swap(msg.sender, isToken0 ? amountIn : 0, isToken0 ? 0 : amountIn, isToken0 ? 0 : amountOut, isToken0 ? amountOut : 0);\n    }\n\n    function _mint(address to, uint256 amount) private {\n        balanceOf[to] += amount;\n        totalSupply += amount;\n    }\n\n    function _burn(address from, uint256 amount) private {\n        balanceOf[from] -= amount;\n        totalSupply -= amount;\n    }\n\n    function _update(uint256 res0, uint256 res1) private {\n        reserve0 = res0;\n        reserve1 = res1;\n    }\n\n    function sqrt(uint256 y) private pure returns (uint256 z) {\n        if (y > 3) {\n            z = y;\n            uint256 x = y \u002F 2 + 1;\n            while (x \u003C z) {\n                z = x;\n                x = (y \u002F x + x) \u002F 2;\n            }\n        } else if (y != 0) {\n            z = 1;\n        }\n    }\n\n    function min(uint256 x, uint256 y) private pure returns (uint256) {\n        return x \u003C= y ? x : y;\n    }\n}\n```\n\n## Governance Token\n\n```solidity\n\u002F\u002F SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin\u002Fcontracts\u002Ftoken\u002FERC20\u002Fextensions\u002FERC20Votes.sol\";\nimport \"@openzeppelin\u002Fcontracts\u002Faccess\u002FOwnable.sol\";\n\ncontract GovernanceToken is ERC20Votes, Ownable {\n    constructor() ERC20(\"Governance Token\", \"GOV\") ERC20Permit(\"Governance Token\") {\n        _mint(msg.sender, 1000000 * 10**decimals());\n    }\n\n    function _afterTokenTransfer(\n        address from,\n        address to,\n        uint256 amount\n    ) internal override(ERC20Votes) {\n        super._afterTokenTransfer(from, to, amount);\n    }\n\n    function _mint(address to, uint256 amount) internal override(ERC20Votes) {\n        super._mint(to, amount);\n    }\n\n    function _burn(address account, uint256 amount) internal override(ERC20Votes) {\n        super._burn(account, amount);\n    }\n}\n\ncontract Governor is Ownable {\n    GovernanceToken public governanceToken;\n\n    struct Proposal {\n        uint256 id;\n        address proposer;\n        string description;\n        uint256 forVotes;\n        uint256 againstVotes;\n        uint256 startBlock;\n        uint256 endBlock;\n        bool executed;\n        mapping(address => bool) hasVoted;\n    }\n\n    uint256 public proposalCount;\n    mapping(uint256 => Proposal) public proposals;\n\n    uint256 public votingPeriod = 17280; \u002F\u002F ~3 days in blocks\n    uint256 public proposalThreshold = 100000 * 10**18;\n\n    event ProposalCreated(uint256 indexed proposalId, address proposer, string description);\n    event VoteCast(address indexed voter, uint256 indexed proposalId, bool support, uint256 weight);\n    event ProposalExecuted(uint256 indexed proposalId);\n\n    constructor(address _governanceToken) {\n        governanceToken = GovernanceToken(_governanceToken);\n    }\n\n    function propose(string memory description) external returns (uint256) {\n        require(\n            governanceToken.getPastVotes(msg.sender, block.number - 1) >= proposalThreshold,\n            \"Proposer votes below threshold\"\n        );\n\n        proposalCount++;\n        Proposal storage newProposal = proposals[proposalCount];\n        newProposal.id = proposalCount;\n        newProposal.proposer = msg.sender;\n        newProposal.description = description;\n        newProposal.startBlock = block.number;\n        newProposal.endBlock = block.number + votingPeriod;\n\n        emit ProposalCreated(proposalCount, msg.sender, description);\n        return proposalCount;\n    }\n\n    function vote(uint256 proposalId, bool support) external {\n        Proposal storage proposal = proposals[proposalId];\n        require(block.number >= proposal.startBlock, \"Voting not started\");\n        require(block.number \u003C= proposal.endBlock, \"Voting ended\");\n        require(!proposal.hasVoted[msg.sender], \"Already voted\");\n\n        uint256 weight = governanceToken.getPastVotes(msg.sender, proposal.startBlock);\n        require(weight > 0, \"No voting power\");\n\n        proposal.hasVoted[msg.sender] = true;\n\n        if (support) {\n            proposal.forVotes += weight;\n        } else {\n            proposal.againstVotes += weight;\n        }\n\n        emit VoteCast(msg.sender, proposalId, support, weight);\n    }\n\n    function execute(uint256 proposalId) external {\n        Proposal storage proposal = proposals[proposalId];\n        require(block.number > proposal.endBlock, \"Voting not ended\");\n        require(!proposal.executed, \"Already executed\");\n        require(proposal.forVotes > proposal.againstVotes, \"Proposal failed\");\n\n        proposal.executed = true;\n\n        \u002F\u002F Execute proposal logic here\n\n        emit ProposalExecuted(proposalId);\n    }\n}\n```\n\n## Flash Loan\n\n```solidity\n\u002F\u002F SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin\u002Fcontracts\u002Ftoken\u002FERC20\u002FIERC20.sol\";\n\ninterface IFlashLoanReceiver {\n    function executeOperation(\n        address asset,\n        uint256 amount,\n        uint256 fee,\n        bytes calldata params\n    ) external returns (bool);\n}\n\ncontract FlashLoanProvider {\n    IERC20 public token;\n    uint256 public feePercentage = 9; \u002F\u002F 0.09% fee\n\n    event FlashLoan(address indexed borrower, uint256 amount, uint256 fee);\n\n    constructor(address _token) {\n        token = IERC20(_token);\n    }\n\n    function flashLoan(\n        address receiver,\n        uint256 amount,\n        bytes calldata params\n    ) external {\n        uint256 balanceBefore = token.balanceOf(address(this));\n        require(balanceBefore >= amount, \"Insufficient liquidity\");\n\n        uint256 fee = (amount * feePercentage) \u002F 10000;\n\n        \u002F\u002F Send tokens to receiver\n        token.transfer(receiver, amount);\n\n        \u002F\u002F Execute callback\n        require(\n            IFlashLoanReceiver(receiver).executeOperation(\n                address(token),\n                amount,\n                fee,\n                params\n            ),\n            \"Flash loan failed\"\n        );\n\n        \u002F\u002F Verify repayment\n        uint256 balanceAfter = token.balanceOf(address(this));\n        require(balanceAfter >= balanceBefore + fee, \"Flash loan not repaid\");\n\n        emit FlashLoan(receiver, amount, fee);\n    }\n}\n\n\u002F\u002F Example flash loan receiver\ncontract FlashLoanReceiver is IFlashLoanReceiver {\n    function executeOperation(\n        address asset,\n        uint256 amount,\n        uint256 fee,\n        bytes calldata params\n    ) external override returns (bool) {\n        \u002F\u002F Decode params and execute arbitrage, liquidation, etc.\n        \u002F\u002F ...\n\n        \u002F\u002F Approve repayment\n        IERC20(asset).approve(msg.sender, amount + fee);\n\n        return true;\n    }\n}\n```\n\n## Resources\n\n- **references\u002Fstaking.md**: Staking mechanics and reward distribution\n- **references\u002Fliquidity-pools.md**: AMM mathematics and pricing\n- **references\u002Fgovernance-tokens.md**: Governance and voting systems\n- **references\u002Flending-protocols.md**: Lending\u002Fborrowing implementation\n- **references\u002Fflash-loans.md**: Flash loan security and use cases\n- **assets\u002Fstaking-contract.sol**: Production staking template\n- **assets\u002Famm-contract.sol**: Full AMM implementation\n- **assets\u002Fgovernance-token.sol**: Governance system\n- **assets\u002Flending-protocol.sol**: Lending platform template\n\n## Best Practices\n\n1. **Use Established Libraries**: OpenZeppelin, Solmate\n2. **Test Thoroughly**: Unit tests, integration tests, fuzzing\n3. **Audit Before Launch**: Professional security audits\n4. **Start Simple**: MVP first, add features incrementally\n5. **Monitor**: Track contract health and user activity\n6. **Upgradability**: Consider proxy patterns for upgrades\n7. **Emergency Controls**: Pause mechanisms for critical issues\n\n## Common DeFi Patterns\n\n- **Time-Weighted Average Price (TWAP)**: Price oracle resistance\n- **Liquidity Mining**: Incentivize liquidity provision\n- **Vesting**: Lock tokens with gradual release\n- **Multisig**: Require multiple signatures for critical operations\n- **Timelocks**: Delay execution of governance decisions\n\n## Limitations\n- Use this skill only when the task clearly matches the scope described above.\n- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.\n- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.\n","","imported","https:\u002F\u002Fgithub.com\u002Fsickn33\u002Fantigravity-awesome-skills","user_system_seed","SkillOPIC",true,94,303,"2026-05-16 13:14:48",{"id":8,"name":21,"slug":22,"icon":23,"description":24,"sort":25,"createdAt":26},"其他","other","mdi-page-next-outline","其他类型Skill",5,"2026-05-16 12:53:40",{"id":7,"name":28,"slug":29,"icon":30,"description":31,"moduleId":8,"sort":32,"skillCount":33,"createdAt":26},"职场发展","career","mdi-briefcase-outline","面试准备、简历优化、职业规划",4,575,[35],{"id":36,"skillId":4,"version":37,"fileName":38,"fileSize":39,"filePath":40,"fileHash":41,"manifest":42,"createdAt":19},"43815ca0-0424-4203-b20e-c72650689849","1.0.0","defi-protocol-templates.zip",4216,"uploads\u002Fskills\u002F7fa94747-ba1e-4a54-ad6b-fa354cdf5831\u002Fdefi-protocol-templates.zip","c31e28603ee54fb81dd15767a398ae6e4737508578b1836f588fcb6e3bd93dcb","[{\"path\":\"SKILL.md\",\"isDirectory\":false,\"size\":15061}]",{"code":44,"message":45,"data":46},200,"success",{"items":47,"stats":48,"page":51},[],{"averageRating":49,"totalRatings":49,"ratingCounts":50},0,[49,49,49,49,49],{"limit":52,"offset":49,"hasMore":53,"nextOffset":52,"ratedOnly":16},15,false]