Secure Smart Contract library for Solidity with upgradeable implementations of standards like ERC20 and ERC721, flexible role-based permissioning schemes, and reusable components for building custom contracts and complex decentralized systems.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Complete implementations of popular token standards including ERC-20 fungible tokens, ERC-721 NFTs, ERC-1155 multi-tokens, and the draft ERC-6909 standard. All token contracts follow the upgradeable pattern with initialization functions.
Standard implementation of the ERC-20 token interface for fungible tokens.
/**
* @dev Implementation of the ERC-20 token standard
*/
contract ERC20Upgradeable {
function __ERC20_init(string memory name_, string memory symbol_) internal onlyInitializing;
/**
* @dev Returns the name of the token
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the number of decimals used to get user representation
*/
function decimals() external view returns (uint8);
/**
* @dev Returns the total token supply
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the balance of account
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves value tokens from the caller's account to to
*/
function transfer(address to, uint256 value) external returns (bool);
/**
* @dev Returns the remaining number of tokens that spender can spend on behalf of owner
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets value as the allowance of spender over the caller's tokens
*/
function approve(address spender, uint256 value) external returns (bool);
/**
* @dev Moves value tokens from from to to using the allowance mechanism
*/
function transferFrom(address from, address to, uint256 value) external returns (bool);
}
// Events
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);/**
* @dev Extension that allows token holders to destroy tokens
*/
abstract contract ERC20BurnableUpgradeable {
/**
* @dev Destroys value tokens from the caller
*/
function burn(uint256 value) external;
/**
* @dev Destroys value tokens from account, deducting from the caller's allowance
*/
function burnFrom(address account, uint256 value) external;
}/**
* @dev Extension that adds a cap to the supply of tokens
*/
abstract contract ERC20CappedUpgradeable {
function __ERC20Capped_init(uint256 cap_) internal onlyInitializing;
/**
* @dev Returns the cap on the token's total supply
*/
function cap() external view returns (uint256);
}/**
* @dev ERC-20 token with pausable token transfers, minting and burning
*/
abstract contract ERC20PausableUpgradeable {
function __ERC20Pausable_init() internal onlyInitializing;
// Inherits pause functionality, automatically pauses transfers when contract is paused
}/**
* @dev Implementation of EIP-2612 permit functionality
*/
abstract contract ERC20PermitUpgradeable {
function __ERC20Permit_init(string memory name) internal onlyInitializing;
/**
* @dev Sets value as the allowance of spender over owner's tokens via signature
*/
function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;
/**
* @dev Returns the current nonce for owner
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator for the current chain
*/
function DOMAIN_SEPARATOR() external view returns (bytes32);
}/**
* @dev Extension of ERC-20 to support Compound-like voting and delegation
*/
abstract contract ERC20VotesUpgradeable {
function __ERC20Votes_init() internal onlyInitializing;
/**
* @dev Returns the current amount of votes that account has
*/
function getVotes(address account) external view returns (uint256);
/**
* @dev Returns the amount of votes that account had at the end of the last completed checkpoint
*/
function getPastVotes(address account, uint256 timepoint) external view returns (uint256);
/**
* @dev Delegates votes from the sender to delegatee
*/
function delegate(address delegatee) external;
/**
* @dev Delegates votes from signer to delegatee
*/
function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;
}/**
* @dev Extension that allows wrapping of an underlying ERC-20 token
*/
abstract contract ERC20WrapperUpgradeable {
function __ERC20Wrapper_init(IERC20 underlyingToken) internal onlyInitializing;
/**
* @dev Returns the underlying token
*/
function underlying() external view returns (IERC20);
/**
* @dev Allow a user to deposit underlying tokens and mint the corresponding wrapper tokens
*/
function depositFor(address account, uint256 value) external returns (bool);
/**
* @dev Allow a user to burn wrapper tokens and withdraw the corresponding underlying tokens
*/
function withdrawTo(address account, uint256 value) external returns (bool);
}/**
* @dev Implementation of the ERC-4626 "Tokenized Vault Standard"
*/
contract ERC4626Upgradeable {
function __ERC4626_init(IERC20 asset_) internal onlyInitializing;
/**
* @dev Returns the address of the underlying token used for the Vault
*/
function asset() external view returns (address);
/**
* @dev Returns the total amount of the underlying asset managed by the Vault
*/
function totalAssets() external view returns (uint256);
/**
* @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided
*/
function convertToShares(uint256 assets) external view returns (uint256);
/**
* @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided
*/
function convertToAssets(uint256 shares) external view returns (uint256);
/**
* @dev Returns the maximum amount of the underlying asset that can be deposited
*/
function maxDeposit(address receiver) external view returns (uint256);
/**
* @dev Returns the amount of shares that would be minted for a deposit
*/
function previewDeposit(uint256 assets) external view returns (uint256);
/**
* @dev Mints shares to receiver by depositing exactly assets of underlying tokens
*/
function deposit(uint256 assets, address receiver) external returns (uint256 shares);
/**
* @dev Mints exactly shares to receiver by depositing assets of underlying tokens
*/
function mint(uint256 shares, address receiver) external returns (uint256 assets);
/**
* @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver
*/
function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);
/**
* @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver
*/
function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);
}
// Events
event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares);
event Withdraw(address indexed sender, address indexed receiver, address indexed owner, uint256 assets, uint256 shares);/**
* @dev Extension that adds flash loan functionality to ERC-20 tokens
*/
abstract contract ERC20FlashMintUpgradeable {
function __ERC20FlashMint_init() internal onlyInitializing;
/**
* @dev Returns the maximum amount of tokens available for loan
*/
function maxFlashLoan(address token) external view returns (uint256);
/**
* @dev Returns the fee for a flash loan
*/
function flashFee(address token, uint256 amount) external view returns (uint256);
/**
* @dev Initiates a flash loan
*/
function flashLoan(
IERC3156FlashBorrower receiver,
address token,
uint256 amount,
bytes calldata data
) external returns (bool);
}
// Custom errors
error ERC3156UnsupportedToken(address token);
error ERC3156ExceededMaxLoan(uint256 maxLoan);
error ERC3156InvalidReceiver(address receiver);/**
* @dev Extension that wraps an existing ERC-20 token
*/
abstract contract ERC20WrapperUpgradeable {
function __ERC20Wrapper_init(IERC20 underlyingToken) internal onlyInitializing;
/**
* @dev Returns the underlying token being wrapped
*/
function underlying() external view returns (IERC20);
/**
* @dev Deposits underlying tokens and mints wrapper tokens
*/
function depositFor(address account, uint256 amount) external returns (bool);
/**
* @dev Withdraws underlying tokens by burning wrapper tokens
*/
function withdrawTo(address account, uint256 amount) external returns (bool);
/**
* @dev Recovers any ERC-20 token sent by mistake to the contract
*/
function _recover(address account) internal returns (uint256);
}/**
* @dev Draft extension for temporary token approvals with expiration
*/
abstract contract ERC20TemporaryApprovalUpgradeable {
function __ERC20TemporaryApproval_init() internal onlyInitializing;
/**
* @dev Sets a temporary approval that expires at a specific timestamp
*/
function temporaryApprove(address spender, uint256 amount, uint256 validUntil) external returns (bool);
/**
* @dev Returns the temporary allowance details including expiration
*/
function temporaryAllowance(address owner, address spender) external view returns (uint256 amount, uint256 validUntil);
}/**
* @dev Draft extension for cross-chain bridging functionality
*/
abstract contract ERC20BridgeableUpgradeable {
function __ERC20Bridgeable_init() internal onlyInitializing;
/**
* @dev Burns tokens for bridging to another chain
*/
function burnForBridge(address account, uint256 amount, bytes calldata bridgeData) external;
/**
* @dev Mints tokens from a bridge operation
*/
function mintFromBridge(address account, uint256 amount, bytes calldata bridgeData) external;
}Standard implementation of the ERC-721 token interface for non-fungible tokens (NFTs).
/**
* @dev Implementation of the ERC-721 Non-Fungible Token Standard
*/
contract ERC721Upgradeable {
function __ERC721_init(string memory name_, string memory symbol_) internal onlyInitializing;
/**
* @dev Returns true if this contract implements the interface defined by interfaceId
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
/**
* @dev Returns the number of tokens in owner's account
*/
function balanceOf(address owner) external view returns (uint256);
/**
* @dev Returns the owner of the tokenId token
*/
function ownerOf(uint256 tokenId) external view returns (address);
/**
* @dev Returns the token collection name
*/
function name() external view returns (string memory);
/**
* @dev Returns the token collection symbol
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the Uniform Resource Identifier (URI) for tokenId token
*/
function tokenURI(uint256 tokenId) external view returns (string memory);
/**
* @dev Gives permission to to to transfer tokenId token to another account
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Returns the account approved for tokenId token
*/
function getApproved(uint256 tokenId) external view returns (address);
/**
* @dev Approve or remove operator as an operator for the caller
*/
function setApprovalForAll(address operator, bool approved) external;
/**
* @dev Returns if the operator is allowed to manage all of the assets of owner
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
/**
* @dev Transfers tokenId token from from to to
*/
function transferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Safely transfers tokenId token from from to to
*/
function safeTransferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Safely transfers tokenId token from from to to with additional data
*/
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
}
// Events
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);/**
* @dev Extension of ERC-721 that adds enumerability of all the token ids in the contract
*/
abstract contract ERC721EnumerableUpgradeable {
function __ERC721Enumerable_init() internal onlyInitializing;
/**
* @dev Returns a token ID owned by owner at a given index of its token list
*/
function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);
/**
* @dev Returns the total amount of tokens stored by the contract
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns a token ID at a given index of all the tokens stored by the contract
*/
function tokenByIndex(uint256 index) external view returns (uint256);
}/**
* @dev Extension that allows setting individual token URIs
*/
abstract contract ERC721URIStorageUpgradeable {
function __ERC721URIStorage_init() internal onlyInitializing;
/**
* @dev Returns the URI for a given token ID
*/
function tokenURI(uint256 tokenId) external view override returns (string memory);
/**
* @dev Sets tokenURI as the tokenURI of tokenId
*/
function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal;
}/**
* @dev Extension of ERC-721 that adds ERC-2981 royalty support
*/
abstract contract ERC721RoyaltyUpgradeable {
function __ERC721Royalty_init() internal onlyInitializing;
/**
* @dev Returns how much royalty is owed and to whom for tokenId sold at salePrice
*/
function royaltyInfo(uint256 tokenId, uint256 salePrice) external view returns (address, uint256);
}/**
* @dev Extension that allows efficient batch minting of consecutive token IDs
*/
abstract contract ERC721ConsecutiveUpgradeable {
function __ERC721Consecutive_init() internal onlyInitializing;
/**
* @dev Returns the first token ID in a consecutive batch
*/
function _firstConsecutiveId() internal view returns (uint96);
/**
* @dev Returns the next consecutive token ID to be minted
*/
function _nextConsecutiveId() internal view returns (uint96);
/**
* @dev Mints consecutive token IDs in a batch
*/
function _mintConsecutive(address to, uint96 batchSize) internal returns (uint256 first);
/**
* @dev Maximum batch size for consecutive minting (default: 5000)
*/
function _maxBatchSize() internal view virtual returns (uint256);
}
// Events (ERC-2309)
event ConsecutiveTransfer(uint256 indexed fromTokenId, uint256 toTokenId, address indexed from, address indexed to);/**
* @dev Extension that wraps existing ERC-721 tokens into new tokens
*/
abstract contract ERC721WrapperUpgradeable {
function __ERC721Wrapper_init(IERC721 underlyingToken) internal onlyInitializing;
/**
* @dev Returns the underlying token contract being wrapped
*/
function underlying() external view returns (IERC721);
/**
* @dev Deposits an underlying token and mints a wrapped token
*/
function depositFor(address account, uint256[] calldata tokenIds) external returns (bool);
/**
* @dev Withdraws underlying tokens by burning wrapped tokens
*/
function withdrawTo(address account, uint256[] calldata tokenIds) external returns (bool);
}/**
* @dev Extension that allows token holders to destroy their tokens
*/
abstract contract ERC721BurnableUpgradeable {
function __ERC721Burnable_init() internal onlyInitializing;
/**
* @dev Burns tokenId
*/
function burn(uint256 tokenId) external;
}/**
* @dev Extension that adds pausable functionality to transfers
*/
abstract contract ERC721PausableUpgradeable {
function __ERC721Pausable_init() internal onlyInitializing;
// Inherits pause functionality, automatically pauses transfers when contract is paused
}/**
* @dev Extension that adds vote delegation functionality
*/
abstract contract ERC721VotesUpgradeable {
function __ERC721Votes_init() internal onlyInitializing;
/**
* @dev Returns the current amount of votes that account has
*/
function getVotes(address account) external view returns (uint256);
/**
* @dev Returns the amount of votes that account had at a specific timepoint
*/
function getPastVotes(address account, uint256 timepoint) external view returns (uint256);
/**
* @dev Delegates votes from the sender to delegatee
*/
function delegate(address delegatee) external;
/**
* @dev Delegates votes from signer to delegatee using signature
*/
function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;
}Implementation of the ERC-1155 Multi Token Standard that supports both fungible and non-fungible tokens.
/**
* @dev Implementation of the basic standard multi-token
*/
contract ERC1155Upgradeable {
function __ERC1155_init(string memory uri_) internal onlyInitializing;
/**
* @dev Returns true if this contract implements the interface defined by interfaceId
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
/**
* @dev Returns the URI for token type id
*/
function uri(uint256 id) external view returns (string memory);
/**
* @dev Returns the balance of account's tokens of token type id
*/
function balanceOf(address account, uint256 id) external view returns (uint256);
/**
* @dev Returns the balance of multiple account/token pairs
*/
function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory);
/**
* @dev Grants or revokes permission to operator to transfer the caller's tokens
*/
function setApprovalForAll(address operator, bool approved) external;
/**
* @dev Returns true if operator is approved to transfer account's tokens
*/
function isApprovedForAll(address account, address operator) external view returns (bool);
/**
* @dev Transfers value tokens of token type id from from to to
*/
function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external;
/**
* @dev Batch version of safeTransferFrom
*/
function safeBatchTransferFrom(address from, address to, uint256[] calldata ids, uint256[] calldata values, bytes calldata data) external;
}
// Events
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);/**
* @dev Extension that adds tracking of total supply per token id
*/
abstract contract ERC1155SupplyUpgradeable {
function __ERC1155Supply_init() internal onlyInitializing;
/**
* @dev Total value of tokens with a given id
*/
function totalSupply(uint256 id) external view returns (uint256);
/**
* @dev Total value of tokens
*/
function totalSupply() external view returns (uint256);
/**
* @dev Indicates whether any token exist with a given id, or not
*/
function exists(uint256 id) external view returns (bool);
}/**
* @dev Implementation of the NFT Royalty Standard
*/
abstract contract ERC2981Upgradeable {
function __ERC2981_init() internal onlyInitializing;
/**
* @dev Returns how much royalty is owed and to whom for tokenId sold at salePrice
*/
function royaltyInfo(uint256 tokenId, uint256 salePrice) external view returns (address, uint256);
/**
* @dev Sets the royalty information that all ids in this contract will default to
*/
function _setDefaultRoyalty(address receiver, uint96 feeNumerator) internal;
/**
* @dev Sets the royalty information for a specific token id
*/
function _setTokenRoyalty(uint256 tokenId, address receiver, uint96 feeNumerator) internal;
/**
* @dev Removes default royalty information
*/
function _deleteDefaultRoyalty() internal;
/**
* @dev Resets royalty information for the token id
*/
function _resetTokenRoyalty(uint256 tokenId) internal;
}import {ERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
contract MyToken is ERC20Upgradeable, OwnableUpgradeable {
function initialize(address initialOwner) initializer public {
__ERC20_init("MyToken", "MTK");
__Ownable_init(initialOwner);
}
function mint(address to, uint256 amount) public onlyOwner {
_mint(to, amount);
}
}import {ERC721Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol";
import {ERC721RoyaltyUpgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721RoyaltyUpgradeable.sol";
contract MyNFT is ERC721Upgradeable, ERC721RoyaltyUpgradeable {
function initialize() initializer public {
__ERC721_init("MyNFT", "MNFT");
__ERC721Royalty_init();
_setDefaultRoyalty(msg.sender, 250); // 2.5% royalty
}
function mint(address to, uint256 tokenId) public {
_mint(to, tokenId);
}
}import {ERC4626Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC4626Upgradeable.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
contract MyVault is ERC4626Upgradeable {
function initialize(IERC20 asset) initializer public {
__ERC4626_init(asset);
__ERC20_init("My Vault Token", "MVT");
}
function _totalAssets() internal view override returns (uint256) {
return IERC20(asset()).balanceOf(address(this));
}
}Install with Tessl CLI
npx tessl i tessl/npm-openzeppelin--contracts-upgradeable