smart-contract-generator

Smart Contract Template Generator

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "smart-contract-generator" with this command: npx skills add microck/ordinary-claude-skills/microck-ordinary-claude-skills-smart-contract-generator

Smart Contract Template Generator

Generates secure Solidity smart contracts following OpenZeppelin standards and best practices.

When to Use

  • "Create an ERC-20 token"

  • "Generate NFT contract"

  • "Smart contract template"

  • "Solidity contract with security"

  • "Create DAO contract"

Instructions

  1. Determine Contract Type

Ask user which type:

  • ERC-20 (Fungible Token)

  • ERC-721 (NFT - Non-Fungible Token)

  • ERC-1155 (Multi-Token)

  • ERC-4626 (Tokenized Vault)

  • Custom contract

  1. Generate Contracts

ERC-20 Token

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

import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";

contract MyToken is ERC20, ERC20Burnable, ERC20Pausable, Ownable, ERC20Permit { constructor(address initialOwner) ERC20("MyToken", "MTK") Ownable(initialOwner) ERC20Permit("MyToken") { _mint(msg.sender, 1000000 * 10 ** decimals()); }

function pause() public onlyOwner {
    _pause();
}

function unpause() public onlyOwner {
    _unpause();
}

function mint(address to, uint256 amount) public onlyOwner {
    _mint(to, amount);
}

// Required override
function _update(address from, address to, uint256 value)
    internal
    override(ERC20, ERC20Pausable)
{
    super._update(from, to, value);
}

}

ERC-721 NFT

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

import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol"; import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol"; import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Pausable.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol";

contract MyNFT is ERC721, ERC721Enumerable, ERC721URIStorage, ERC721Pausable, Ownable, ERC721Burnable { uint256 private _nextTokenId; uint256 public constant MAX_SUPPLY = 10000; uint256 public constant MINT_PRICE = 0.05 ether;

constructor(address initialOwner)
    ERC721("MyNFT", "MNFT")
    Ownable(initialOwner)
{}

function pause() public onlyOwner {
    _pause();
}

function unpause() public onlyOwner {
    _unpause();
}

function safeMint(address to, string memory uri) public payable {
    require(_nextTokenId < MAX_SUPPLY, "Max supply reached");
    require(msg.value >= MINT_PRICE, "Insufficient payment");

    uint256 tokenId = _nextTokenId++;
    _safeMint(to, tokenId);
    _setTokenURI(tokenId, uri);
}

function withdraw() public onlyOwner {
    uint256 balance = address(this).balance;
    payable(owner()).transfer(balance);
}

// Required overrides
function _update(address to, uint256 tokenId, address auth)
    internal
    override(ERC721, ERC721Enumerable, ERC721Pausable)
    returns (address)
{
    return super._update(to, tokenId, auth);
}

function _increaseBalance(address account, uint128 value)
    internal
    override(ERC721, ERC721Enumerable)
{
    super._increaseBalance(account, value);
}

function tokenURI(uint256 tokenId)
    public
    view
    override(ERC721, ERC721URIStorage)
    returns (string memory)
{
    return super.tokenURI(tokenId);
}

function supportsInterface(bytes4 interfaceId)
    public
    view
    override(ERC721, ERC721Enumerable, ERC721URIStorage)
    returns (bool)
{
    return super.supportsInterface(interfaceId);
}

}

ERC-1155 Multi-Token

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

import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Pausable.sol"; import "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Supply.sol";

contract MyMultiToken is ERC1155, Ownable, ERC1155Pausable, ERC1155Supply { constructor(address initialOwner) ERC1155("https://api.example.com/token/{id}.json") Ownable(initialOwner) {}

function setURI(string memory newuri) public onlyOwner {
    _setURI(newuri);
}

function pause() public onlyOwner {
    _pause();
}

function unpause() public onlyOwner {
    _unpause();
}

function mint(address account, uint256 id, uint256 amount, bytes memory data)
    public
    onlyOwner
{
    _mint(account, id, amount, data);
}

function mintBatch(address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data)
    public
    onlyOwner
{
    _mintBatch(to, ids, amounts, data);
}

// Required overrides
function _update(address from, address to, uint256[] memory ids, uint256[] memory values)
    internal
    override(ERC1155, ERC1155Pausable, ERC1155Supply)
{
    super._update(from, to, ids, values);
}

}

  1. Security Patterns

Reentrancy Protection:

import "@openzeppelin/contracts/security/ReentrancyGuard.sol";

contract SecureContract is ReentrancyGuard { function withdraw() public nonReentrant { uint amount = balances[msg.sender]; balances[msg.sender] = 0; (bool success, ) = msg.sender.call{value: amount}(""); require(success, "Transfer failed"); } }

Access Control:

import "@openzeppelin/contracts/access/AccessControl.sol";

contract MyContract is AccessControl { bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");

constructor() {
    _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
    _grantRole(MINTER_ROLE, msg.sender);
}

function mint(address to) public onlyRole(MINTER_ROLE) {
    // Minting logic
}

}

Pull Over Push:

// ❌ BAD: Push pattern (vulnerable) function distribute() public { for (uint i = 0; i < recipients.length; i++) { recipients[i].transfer(amounts[i]); } }

// ✅ GOOD: Pull pattern (secure) mapping(address => uint) public pendingWithdrawals;

function withdraw() public { uint amount = pendingWithdrawals[msg.sender]; pendingWithdrawals[msg.sender] = 0; payable(msg.sender).transfer(amount); }

  1. Gas Optimization

// Use uint256 instead of smaller uints (saves gas) uint256 public count; // ✅

// Cache array length for (uint256 i = 0; i < array.length; i++) // ❌ uint256 length = array.length; for (uint256 i = 0; i < length; i++) // ✅

// Use unchecked for gas savings (when safe) unchecked { counter++; }

// Immutable for constants uint256 public immutable MAX_SUPPLY;

  1. Testing Setup

Hardhat:

// test/MyToken.test.js const { expect } = require("chai"); const { ethers } = require("hardhat");

describe("MyToken", function () { let token; let owner; let addr1;

beforeEach(async function () { [owner, addr1] = await ethers.getSigners();

const MyToken = await ethers.getContractFactory("MyToken");
token = await MyToken.deploy(owner.address);

});

it("Should assign total supply to owner", async function () { const ownerBalance = await token.balanceOf(owner.address); expect(await token.totalSupply()).to.equal(ownerBalance); });

it("Should transfer tokens", async function () { await token.transfer(addr1.address, 50); expect(await token.balanceOf(addr1.address)).to.equal(50); }); });

  1. Deployment Script

// scripts/deploy.js const hre = require("hardhat");

async function main() { const [deployer] = await hre.ethers.getSigners();

console.log("Deploying with account:", deployer.address);

const MyToken = await hre.ethers.getContractFactory("MyToken"); const token = await MyToken.deploy(deployer.address);

await token.waitForDeployment();

console.log("Token deployed to:", await token.getAddress());

// Verify on Etherscan if (network.name !== "hardhat") { await hre.run("verify:verify", { address: await token.getAddress(), constructorArguments: [deployer.address], }); } }

main().catch((error) => { console.error(error); process.exitCode = 1; });

  1. Configuration Files

hardhat.config.js:

require("@nomicfoundation/hardhat-toolbox"); require("dotenv").config();

module.exports = { solidity: { version: "0.8.20", settings: { optimizer: { enabled: true, runs: 200, }, }, }, networks: { sepolia: { url: process.env.SEPOLIA_RPC_URL, accounts: [process.env.PRIVATE_KEY], }, mainnet: { url: process.env.MAINNET_RPC_URL, accounts: [process.env.PRIVATE_KEY], }, }, etherscan: { apiKey: process.env.ETHERSCAN_API_KEY, }, };

  1. Best Practices
  • Use latest Solidity version

  • Import from OpenZeppelin

  • Add comprehensive tests (>90% coverage)

  • Use Slither for static analysis

  • Get audited before mainnet

  • Use multi-sig for ownership

  • Implement pause mechanism

  • Follow checks-effects-interactions pattern

  • Document all functions with NatSpec

  • Version control and CI/CD

  1. Audit Checklist
  • Reentrancy protection

  • Integer overflow/underflow (use 0.8.0+)

  • Access control properly implemented

  • No unchecked external calls

  • Gas limits considered

  • Front-running mitigation

  • Timestamp dependence avoided

  • Randomness source secure

  • Upgrade mechanism (if proxy)

  • Emergency pause function

  1. Documentation Template

/**

  • @title MyToken
  • @dev Implementation of ERC-20 token with additional features
  • @custom:security-contact security@example.com */

/**

  • @notice Mints new tokens
  • @dev Only callable by owner
  • @param to Address to receive tokens
  • @param amount Amount of tokens to mint */ function mint(address to, uint256 amount) public onlyOwner { _mint(to, amount); }

Installation

Initialize project

npm init -y npm install --save-dev hardhat @openzeppelin/contracts

Initialize Hardhat

npx hardhat init

Install dependencies

npm install --save-dev @nomicfoundation/hardhat-toolbox

Run tests

npx hardhat test

Deploy

npx hardhat run scripts/deploy.js --network sepolia

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

alex-hormozi-pitch

No summary provided by upstream source.

Repository SourceNeeds Review
General

dnd5e-srd

No summary provided by upstream source.

Repository SourceNeeds Review
General

shopify-api

No summary provided by upstream source.

Repository SourceNeeds Review
General

analyzing-financial-statements

No summary provided by upstream source.

Repository SourceNeeds Review