Secure Smart Contract library for Solidity with battle-tested implementations of token standards, access control, governance, and essential utilities for building decentralized applications.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Comprehensive implementations of Ethereum token standards including ERC20 (fungible tokens), ERC721 (NFTs), and ERC1155 (multi-tokens) with extensive extensions and utilities.
Implementation of the ERC20 standard for fungible tokens with full compliance and security features.
/**
* @dev Implementation of the {IERC20} interface.
* Abstract contract requiring supply mechanism in derived contracts.
*/
abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {
/**
* @dev Sets the values for {name} and {symbol}
* Both values are immutable: they can only be set once during construction
*/
constructor(string memory name_, string memory symbol_);
/**
* @dev Returns the name of the token
*/
function name() public view virtual returns (string memory);
/**
* @dev Returns the symbol of the token
*/
function symbol() public view virtual returns (string memory);
/**
* @dev Returns the number of decimals used to get its user representation
*/
function decimals() public view virtual returns (uint8);
/**
* @dev Returns the value of tokens in existence
*/
function totalSupply() public view virtual returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`
*/
function balanceOf(address account) public view virtual returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`
*/
function transfer(address to, uint256 value) public virtual returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be allowed to spend on behalf of `owner`
*/
function allowance(address owner, address spender) public view virtual returns (uint256);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the caller's tokens
*/
function approve(address spender, uint256 value) public virtual returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
*/
function transferFrom(address from, address to, uint256 value) public virtual returns (bool);
/**
* @dev Creates a `value` amount of tokens and assigns them to `account`
* Internal function that can be called by derived contracts
*/
function _mint(address account, uint256 value) internal;
/**
* @dev Destroys a `value` amount of tokens from `account`
* Internal function that can be called by derived contracts
*/
function _burn(address account, uint256 value) internal;
/**
* @dev Sets `value` as the allowance of `spender` over `owner`'s tokens
* Internal function that can be called by derived contracts
*/
function _approve(address owner, address spender, uint256 value) internal;
}Usage Example:
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract MyToken is ERC20, Ownable {
constructor(address initialOwner)
ERC20("MyToken", "MTK")
Ownable(initialOwner)
{}
function mint(address to, uint256 amount) public onlyOwner {
_mint(to, amount);
}
function burn(uint256 amount) public {
_burn(msg.sender, amount);
}
}Extended functionality for ERC20 tokens including permits, pausability, burning, and more.
// ERC20 Permit - Gasless approvals via signatures
abstract contract ERC20Permit is ERC20, IERC20Permit, EIP712, Nonces {
function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public virtual;
function nonces(address owner) public view virtual returns (uint256);
function DOMAIN_SEPARATOR() external view virtual returns (bytes32);
}
// ERC20 Pausable - Emergency pause functionality
abstract contract ERC20Pausable is ERC20, Pausable {
function _update(address from, address to, uint256 value) internal virtual override whenNotPaused;
}
// ERC20 Burnable - Token burning functionality
abstract contract ERC20Burnable is Context, ERC20 {
function burn(uint256 value) public virtual;
function burnFrom(address account, uint256 value) public virtual;
}
// ERC20 Capped - Supply cap functionality
abstract contract ERC20Capped is ERC20 {
constructor(uint256 cap_);
function cap() public view virtual returns (uint256);
function _update(address from, address to, uint256 value) internal virtual override;
}
// ERC20 FlashMint - Flash loan functionality
abstract contract ERC20FlashMint is ERC20, IERC3156FlashLender {
function maxFlashLoan(address token) public view virtual returns (uint256);
function flashFee(address token, uint256 value) public view virtual returns (uint256);
function flashLoan(IERC3156FlashBorrower receiver, address token, uint256 value, bytes calldata data) public virtual returns (bool);
}
// ERC20 Votes - Voting weight tracking for governance
abstract contract ERC20Votes is ERC20, Votes {
function _update(address from, address to, uint256 value) internal virtual override;
function getVotes(address account) public view virtual returns (uint256);
function getPastVotes(address account, uint256 timepoint) public view virtual returns (uint256);
}
// ERC4626 Tokenized Vaults - Vault standard for yield-bearing tokens
abstract contract ERC4626 is ERC20, IERC4626 {
constructor(IERC20 asset_, string memory name_, string memory symbol_);
function asset() public view virtual returns (address);
function totalAssets() public view virtual returns (uint256);
function convertToShares(uint256 assets) public view virtual returns (uint256);
function convertToAssets(uint256 shares) public view virtual returns (uint256);
function maxDeposit(address) public view virtual returns (uint256);
function maxMint(address) public view virtual returns (uint256);
function maxWithdraw(address owner) public view virtual returns (uint256);
function maxRedeem(address owner) public view virtual returns (uint256);
function previewDeposit(uint256 assets) public view virtual returns (uint256);
function previewMint(uint256 shares) public view virtual returns (uint256);
function previewWithdraw(uint256 assets) public view virtual returns (uint256);
function previewRedeem(uint256 shares) public view virtual returns (uint256);
function deposit(uint256 assets, address receiver) public virtual returns (uint256);
function mint(uint256 shares, address receiver) public virtual returns (uint256);
function withdraw(uint256 assets, address receiver, address owner) public virtual returns (uint256);
function redeem(uint256 shares, address receiver, address owner) public virtual returns (uint256);
}
// ERC1363 Payable Token - Callbacks after transfers and approvals
abstract contract ERC1363 is ERC20, ERC165, IERC1363 {
function transferAndCall(address to, uint256 value) public returns (bool);
function transferAndCall(address to, uint256 value, bytes memory data) public virtual returns (bool);
function transferFromAndCall(address from, address to, uint256 value) public returns (bool);
function transferFromAndCall(address from, address to, uint256 value, bytes memory data) public virtual returns (bool);
function approveAndCall(address spender, uint256 value) public returns (bool);
function approveAndCall(address spender, uint256 value, bytes memory data) public virtual returns (bool);
}
// ERC20Wrapper - Wrap existing ERC20 tokens
abstract contract ERC20Wrapper is ERC20 {
constructor(IERC20 underlyingToken, string memory name_, string memory symbol_);
function underlying() public view returns (IERC20);
function depositFor(address account, uint256 value) public virtual returns (bool);
function withdrawTo(address account, uint256 value) public virtual returns (bool);
function recover(address account) public virtual returns (uint256);
}Implementation of the ERC721 standard for non-fungible tokens (NFTs) with metadata support.
/**
* @dev Implementation of the {IERC721} Non-Fungible Token Standard
*/
abstract contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Errors {
/**
* @dev Sets the values for {name} and {symbol}
*/
constructor(string memory name_, string memory symbol_);
/**
* @dev Returns the token collection name
*/
function name() public view virtual returns (string memory);
/**
* @dev Returns the token collection symbol
*/
function symbol() public view virtual returns (string memory);
/**
* @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token
*/
function tokenURI(uint256 tokenId) public view virtual returns (string memory);
/**
* @dev Returns the number of tokens in `owner`'s account
*/
function balanceOf(address owner) public view virtual returns (uint256);
/**
* @dev Returns the owner of the `tokenId` token
*/
function ownerOf(uint256 tokenId) public view virtual returns (address);
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account
*/
function approve(address to, uint256 tokenId) public virtual;
/**
* @dev Returns the account approved for `tokenId` token
*/
function getApproved(uint256 tokenId) public view virtual returns (address);
/**
* @dev Approve or remove `operator` as an operator for the caller
*/
function setApprovalForAll(address operator, bool approved) public virtual;
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`
*/
function isApprovedForAll(address owner, address operator) public view virtual returns (bool);
/**
* @dev Transfers `tokenId` token from `from` to `to`
*/
function transferFrom(address from, address to, uint256 tokenId) public virtual;
/**
* @dev Safely transfers `tokenId` token from `from` to `to`
*/
function safeTransferFrom(address from, address to, uint256 tokenId) public virtual;
/**
* @dev Safely transfers `tokenId` token from `from` to `to` with additional data
*/
function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual;
/**
* @dev Mints `tokenId` and transfers it to `to`
* Internal function that can be called by derived contracts
*/
function _mint(address to, uint256 tokenId) internal;
/**
* @dev Destroys `tokenId` token
* Internal function that can be called by derived contracts
*/
function _burn(uint256 tokenId) internal;
}Usage Example:
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract MyNFT is ERC721, Ownable {
uint256 private _tokenIdCounter;
constructor(address initialOwner)
ERC721("MyNFT", "MNFT")
Ownable(initialOwner)
{}
function safeMint(address to) public onlyOwner {
uint256 tokenId = _tokenIdCounter++;
_safeMint(to, tokenId);
}
function tokenURI(uint256 tokenId) public view override returns (string memory) {
_requireOwned(tokenId);
return string(abi.encodePacked("https://api.example.com/token/", tokenId));
}
}Extended functionality for ERC721 tokens including enumeration, URI storage, and more.
// ERC721 Enumerable - Token enumeration functionality
abstract contract ERC721Enumerable is ERC721, IERC721Enumerable {
function totalSupply() public view virtual returns (uint256);
function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual returns (uint256);
function tokenByIndex(uint256 index) public view virtual returns (uint256);
}
// ERC721 URI Storage - Per-token URI storage
abstract contract ERC721URIStorage is IERC4906, ERC721 {
function tokenURI(uint256 tokenId) public view virtual override returns (string memory);
function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual;
}
// ERC721 Burnable - Token burning functionality
abstract contract ERC721Burnable is Context, ERC721 {
function burn(uint256 tokenId) public virtual;
}
// ERC721 Pausable - Emergency pause functionality
abstract contract ERC721Pausable is ERC721, Pausable {
function _update(address to, uint256 tokenId, address auth) internal virtual override whenNotPaused returns (address);
}
// ERC721 Royalty - EIP-2981 royalty functionality
abstract contract ERC721Royalty is ERC721, ERC2981 {
function _burn(uint256 tokenId) internal virtual override;
}Implementation of the ERC1155 standard supporting multiple token types in a single contract.
/**
* @dev Implementation of the {IERC1155} Multi Token Standard
*/
abstract contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI, IERC1155Errors {
/**
* @dev Sets the URI for all token types
*/
constructor(string memory uri_);
/**
* @dev Returns the URI for token type `id`
*/
function uri(uint256 id) public view virtual returns (string memory);
/**
* @dev Returns the value of tokens of token type `id` owned by `account`
*/
function balanceOf(address account, uint256 id) public view virtual returns (uint256);
/**
* @dev Batched version of {balanceOf}
*/
function balanceOfBatch(address[] memory accounts, uint256[] memory ids) public view virtual returns (uint256[] memory);
/**
* @dev Grants or revokes permission to `operator` to transfer the caller's tokens
*/
function setApprovalForAll(address operator, bool approved) public virtual;
/**
* @dev Returns true if `operator` is approved to transfer `account`'s tokens
*/
function isApprovedForAll(address account, address operator) public view virtual returns (bool);
/**
* @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`
*/
function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes memory data) public virtual;
/**
* @dev Batched version of {safeTransferFrom}
*/
function safeBatchTransferFrom(address from, address to, uint256[] memory ids, uint256[] memory values, bytes memory data) public virtual;
/**
* @dev Creates a `value` amount of tokens of type `id`, and assigns them to `to`
* Internal function that can be called by derived contracts
*/
function _mint(address to, uint256 id, uint256 value, bytes memory data) internal;
/**
* @dev Batched version of {_mint}
*/
function _mintBatch(address to, uint256[] memory ids, uint256[] memory values, bytes memory data) internal;
/**
* @dev Destroys a `value` amount of tokens of type `id` from `from`
* Internal function that can be called by derived contracts
*/
function _burn(address from, uint256 id, uint256 value) internal;
/**
* @dev Batched version of {_burn}
*/
function _burnBatch(address from, uint256[] memory ids, uint256[] memory values) internal;
}Usage Example:
import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract MyMultiToken is ERC1155, Ownable {
constructor(address initialOwner)
ERC1155("https://api.example.com/token/{id}.json")
Ownable(initialOwner)
{}
function mint(address to, uint256 id, uint256 amount, bytes memory data) public onlyOwner {
_mint(to, id, amount, data);
}
function mintBatch(address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data) public onlyOwner {
_mintBatch(to, ids, amounts, data);
}
}Draft implementation of ERC6909 standard providing multi-token functionality with per-token allowances.
/**
* @dev Implementation of ERC6909 multi-token standard with per-token-type allowances
* Combines benefits of ERC20 (per-token allowances) with ERC1155 (multi-token support)
*/
abstract contract ERC6909 is Context, ERC165, IERC6909 {
/**
* @dev Returns the balance of `owner` for token `id`
*/
function balanceOf(address owner, uint256 id) public view virtual returns (uint256);
/**
* @dev Returns the allowance `owner` has given `spender` for token `id`
*/
function allowance(address owner, address spender, uint256 id) public view virtual returns (uint256);
/**
* @dev Returns true if `spender` is approved as an operator for `owner`
*/
function isOperator(address owner, address spender) public view virtual returns (bool);
/**
* @dev Approve `spender` to spend `amount` of token `id` on behalf of caller
*/
function approve(address spender, uint256 id, uint256 amount) public virtual returns (bool);
/**
* @dev Set `spender` as operator for all tokens owned by caller
*/
function setOperator(address spender, bool approved) public virtual returns (bool);
/**
* @dev Transfer `amount` of token `id` to `receiver`
*/
function transfer(address receiver, uint256 id, uint256 amount) public virtual returns (bool);
/**
* @dev Transfer `amount` of token `id` from `sender` to `receiver`
*/
function transferFrom(address sender, address receiver, uint256 id, uint256 amount) public virtual returns (bool);
/**
* @dev Internal function to update balances during transfers
*/
function _update(address from, address to, uint256 id, uint256 amount) internal virtual;
/**
* @dev Internal function to mint tokens
*/
function _mint(address to, uint256 id, uint256 amount) internal;
/**
* @dev Internal function to burn tokens
*/
function _burn(address from, uint256 id, uint256 amount) internal;
}Usage Example:
import "@openzeppelin/contracts/token/ERC6909/draft-ERC6909.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract MyERC6909Token is ERC6909, Ownable {
constructor(address initialOwner) Ownable(initialOwner) {}
function mint(address to, uint256 id, uint256 amount) public onlyOwner {
_mint(to, id, amount);
}
function burn(address from, uint256 id, uint256 amount) public {
require(from == msg.sender || isOperator(from, msg.sender) || allowance(from, msg.sender, id) >= amount, "Insufficient permission");
_burn(from, id, amount);
}
}ERC6909ContentURI - Provides URI functionality for tokens:
abstract contract ERC6909ContentURI is ERC6909 {
function contractURI() public view virtual returns (string memory);
function tokenURI(uint256 id) public view virtual returns (string memory);
}ERC6909Metadata - Adds name and symbol metadata:
abstract contract ERC6909Metadata is ERC6909 {
function name(uint256 id) public view virtual returns (string memory);
function symbol(uint256 id) public view virtual returns (string memory);
function decimals(uint256 id) public view virtual returns (uint8);
}ERC6909TokenSupply - Tracks total supply per token:
abstract contract ERC6909TokenSupply is ERC6909 {
function totalSupply(uint256 id) public view virtual returns (uint256);
function exists(uint256 id) public view virtual returns (bool);
}Utility contracts and libraries for safe token interactions and common patterns.
// Safe ERC20 Operations
library SafeERC20 {
function safeTransfer(IERC20 token, address to, uint256 value) internal;
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal;
function safeApprove(IERC20 token, address spender, uint256 value) internal;
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal;
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal;
}
// ERC721 Holder - Safe NFT recipient
contract ERC721Holder is IERC721Receiver {
function onERC721Received(address, address, uint256, bytes memory) public virtual returns (bytes4);
}
// ERC1155 Holder - Safe multi-token recipient
contract ERC1155Holder is ERC1155Receiver {
function onERC1155Received(address, address, uint256, uint256, bytes memory) public virtual returns (bytes4);
function onERC1155BatchReceived(address, address, uint256[] memory, uint256[] memory, bytes memory) public virtual returns (bytes4);
}
// ERC2981 Royalty Standard
abstract contract ERC2981 is IERC2981, ERC165 {
function royaltyInfo(uint256 tokenId, uint256 salePrice) public view virtual returns (address, uint256);
function _setDefaultRoyalty(address receiver, uint96 feeNumerator) internal;
function _setTokenRoyalty(uint256 tokenId, address receiver, uint96 feeNumerator) internal;
function _deleteDefaultRoyalty() internal;
function _deleteTokenRoyalty(uint256 tokenId) internal;
}// ERC20 Interface
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 value) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 value) external returns (bool);
function transferFrom(address from, address to, uint256 value) external returns (bool);
}
// ERC721 Interface
interface IERC721 {
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
function balanceOf(address owner) external view returns (uint256 balance);
function ownerOf(uint256 tokenId) external view returns (address owner);
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
function safeTransferFrom(address from, address to, uint256 tokenId) external;
function transferFrom(address from, address to, uint256 tokenId) external;
function approve(address to, uint256 tokenId) external;
function setApprovalForAll(address operator, bool approved) external;
function getApproved(uint256 tokenId) external view returns (address operator);
function isApprovedForAll(address owner, address operator) external view returns (bool);
}
// ERC1155 Interface
interface IERC1155 {
event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);
event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values);
event ApprovalForAll(address indexed account, address indexed operator, bool approved);
event URI(string value, uint256 indexed id);
function balanceOf(address account, uint256 id) external view returns (uint256);
function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory);
function setApprovalForAll(address operator, bool approved) external;
function isApprovedForAll(address account, address operator) external view returns (bool);
function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external;
function safeBatchTransferFrom(address from, address to, uint256[] calldata ids, uint256[] calldata values, bytes calldata data) external;
}Install with Tessl CLI
npx tessl i tessl/npm-openzeppelin--contracts