Loading skill
Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Expert usage of OpenZeppelin Contracts library for secure smart contract development. Covers access control, token standards, governance, upgrades, and security utilities.
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 44% | 0% |
| case-02 | ✗→✗ | = Same ✗ | 266% | 0% |
| case-03 | ✗→✗ | = Same ✗ | 132% | 0% |
| case-04 | ✗→✗ | = Same ✗ | 129% | 0% |
| case-05 | ✗→✗ | = Same ✗ | 66% | 0% |
Expert usage of OpenZeppelin Contracts, the standard library for secure smart contract development.
bash# Standard contracts npm install @openzeppelin/contracts # Upgradeable contracts npm install @openzeppelin/contracts-upgradeable # Hardhat upgrades plugin npm install @openzeppelin/hardhat-upgrades
solidity// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "@openzeppelin/contracts/access/Ownable.sol"; contract MyContract is Ownable { constructor(address initialOwner) Ownable(initialOwner) {} function protectedFunction() external onlyOwner { // Only owner can call } }
solidityimport "@openzeppelin/contracts/access/AccessControl.sol"; contract MyContract is AccessControl { bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE"); bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE"); constructor() { _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); _grantRole(ADMIN_ROLE, msg.sender); } function mint(address to, uint256 amount) external onlyRole(MINTER_ROLE) { // Minting logic } function pause() external onlyRole(PAUSER_ROLE) { // Pausing logic } }
solidityimport "@openzeppelin/contracts/access/extensions/AccessControlEnumerable.sol"; contract MyContract is AccessControlEnumerable { function getAllAdmins() external view returns (address[] memory) { uint256 count = getRoleMemberCount(DEFAULT_ADMIN_ROLE); address[] memory admins = new address[](count); for (uint256 i = 0; i < count; i++) { admins[i] = getRoleMember(DEFAULT_ADMIN_ROLE, i); } return admins; } }
solidityimport "@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/token/ERC20/extensions/ERC20Permit.sol"; import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol"; import "@openzeppelin/contracts/access/AccessControl.sol"; contract MyToken is ERC20, ERC20Burnable, ERC20Pausable, ERC20Permit, ERC20Votes, AccessControl { bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE"); constructor() ERC20("MyToken", "MTK") ERC20Permit("MyToken") { _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); _grantRole(MINTER_ROLE, msg.sender); _grantRole(PAUSER_ROLE, msg.sender); } function mint(address to, uint256 amount) public onlyRole(MINTER_ROLE) { _mint(to, amount); } function pause() public onlyRole(PAUSER_ROLE) { _pause(); } function unpause() public onlyRole(PAUSER_ROLE) { _unpause(); } // Required overrides function _update(address from, address to, uint256 value) internal override(ERC20, ERC20Pausable, ERC20Votes) { super._update(from, to, value); } function nonces(address owner) public view override(ERC20Permit, Nonces) returns (uint256) { return super.nonces(owner); } }
solidityimport "@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/ERC721Royalty.sol"; contract MyNFT is ERC721, ERC721Enumerable, ERC721URIStorage, ERC721Royalty { uint256 private _tokenIdCounter; constructor() ERC721("MyNFT", "MNFT") { _setDefaultRoyalty(msg.sender, 500); // 5% royalty } function safeMint(address to, string memory uri) public { uint256 tokenId = _tokenIdCounter++; _safeMint(to, tokenId); _setTokenURI(tokenId, uri); } // Required overrides function _update(address to, uint256 tokenId, address auth) internal override(ERC721, ERC721Enumerable) 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, ERC721Royalty) returns (bool) { return super.supportsInterface(interfaceId); } }
solidityimport "@openzeppelin/contracts/governance/Governor.sol"; import "@openzeppelin/contracts/governance/extensions/GovernorSettings.sol"; import "@openzeppelin/contracts/governance/extensions/GovernorCountingSimple.sol"; import "@openzeppelin/contracts/governance/extensions/GovernorVotes.sol"; import "@openzeppelin/contracts/governance/extensions/GovernorVotesQuorumFraction.sol"; import "@openzeppelin/contracts/governance/extensions/GovernorTimelockControl.sol"; contract MyGovernor is Governor, GovernorSettings, GovernorCountingSimple, GovernorVotes, GovernorVotesQuorumFraction, GovernorTimelockControl { constructor( IVotes _token, TimelockController _timelock ) Governor("MyGovernor") GovernorSettings( 1 days, // Voting delay 1 weeks, // Voting period 100e18 // Proposal threshold ) GovernorVotes(_token) GovernorVotesQuorumFraction(4) // 4% quorum GovernorTimelockControl(_timelock) {} // Required overrides... }
solidityimport "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; contract MyContractV1 is Initializable, UUPSUpgradeable, OwnableUpgradeable { uint256 public value; /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); } function initialize() public initializer { __Ownable_init(msg.sender); __UUPSUpgradeable_init(); } function _authorizeUpgrade(address newImplementation) internal override onlyOwner {} }
javascriptconst { ethers, upgrades } = require("hardhat"); async function main() { // Deploy const MyContract = await ethers.getContractFactory("MyContractV1"); const proxy = await upgrades.deployProxy(MyContract, [], { initializer: "initialize", kind: "uups", }); await proxy.waitForDeployment(); console.log("Proxy:", await proxy.getAddress()); // Upgrade const MyContractV2 = await ethers.getContractFactory("MyContractV2"); await upgrades.upgradeProxy(await proxy.getAddress(), MyContractV2); }
solidityimport "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; contract MyContract { using SafeERC20 for IERC20; function deposit(IERC20 token, uint256 amount) external { token.safeTransferFrom(msg.sender, address(this), amount); } function withdraw(IERC20 token, uint256 amount) external { token.safeTransfer(msg.sender, amount); } }
solidityimport "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; contract MyContract is ReentrancyGuard { function withdraw() external nonReentrant { // Safe from reentrancy } }
solidityimport "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol"; contract Airdrop { bytes32 public merkleRoot; function claim(bytes32[] calldata proof, uint256 amount) external { bytes32 leaf = keccak256(abi.encodePacked(msg.sender, amount)); require(MerkleProof.verify(proof, merkleRoot, leaf), "Invalid proof"); // Process claim } }
| Process | Purpose | |---------|---------| | All token processes | Token development | | governance-system.js | Governance | | smart-contract-upgrade.js | Upgrades | | staking-contract.js | Staking |
skills/solidity-dev/SKILL.md - Solidity developmentOther measured skills in the registry, with their headline benchmark lift.