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.
.claude/skills/a5c-ai-openzeppelin/SKILL.md| 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 development| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→pass | 14,562 | 9,768 | -33% | 1 | 1 | 0% | 3,377 | 4,877 | +44% | 0 | 0 | — |
case-02 | fail→fail | 5,377 | 5,711 | +6% | 1 | 1 | 0% | 1,042 | 3,811 | +266% | 0 | 0 | — |
case-03 | fail→fail | 7,667 | 4,902 | -36% | 1 | 1 | 0% | 1,599 | 3,710 | +132% | 0 | 0 | — |
case-04 | fail→fail | 7,621 | 5,261 | -31% | 1 | 1 | 0% | 1,650 | 3,776 | +129% | 0 | 0 | — |
case-05 | fail→fail | 13,364 | 10,952 | -18% | 1 | 1 | 0% | 3,050 | 5,060 | +66% | 0 | 0 | — |
case-06 | fail→fail | 12,075 | 7,536 | -38% | 1 | 1 | 0% | 2,523 | 4,260 | +69% | 0 | 0 | — |
case-07 | fail→fail | 10,299 | 6,990 | -32% | 1 | 1 | 0% | 2,017 | 4,182 | +107% | 0 | 0 | — |
case-08 | fail→fail | 6,841 | 4,859 | -29% | 1 | 1 | 0% | 1,404 | 3,717 | +165% | 0 | 0 | — |
case-09 | fail→fail | 10,582 | 5,190 | -51% | 1 | 1 | 0% | 1,727 | 3,818 | +121% | 0 | 0 | — |
case-10 | fail→fail | 15,693 | 12,825 | -18% | 1 | 1 | 0% | 3,769 | 5,919 | +57% | 0 | 0 | — |
case-11 | fail→fail | 9,786 | 7,624 | -22% | 1 | 1 | 0% | 1,943 | 4,241 | +118% | 0 | 0 | — |
case-12 | fail→fail | 11,087 | 10,911 | -2% | 1 | 1 | 0% | 2,222 | 5,025 | +126% | 0 | 0 | — |
case-13 | fail→fail | 8,574 | 5,765 | -33% | 1 | 1 | 0% | 1,574 | 3,562 | +126% | 0 | 0 | — |
case-14 | fail→fail | 11,233 | 5,944 | -47% | 1 | 1 | 0% | 2,413 | 3,818 | +58% | 0 | 0 | — |
case-15 | fail→fail | 12,348 | 10,686 | -13% | 1 | 1 | 0% | 2,915 | 4,943 | +70% | 0 | 0 | — |
case-16 | fail→fail | 11,412 | 7,523 | -34% | 1 | 1 | 0% | 2,232 | 4,108 | +84% | 0 | 0 | — |
case-17 | fail→fail | 14,195 | 10,161 | -28% | 1 | 1 | 0% | 3,055 | 5,017 | +64% | 0 | 0 | — |
case-18 | fail→fail | 11,998 | 17,136 | +43% | 1 | 1 | 0% | 2,455 | 5,625 | +129% | 0 | 0 | — |
case-19 | fail→fail | 9,529 | 8,713 | -9% | 1 | 1 | 0% | 1,941 | 4,508 | +132% | 0 | 0 | — |
case-20 | fail→fail | 21,081 | 14,638 | -31% | 1 | 1 | 0% | 4,192 | 5,664 | +35% | 0 | 0 | — |
case-21 | fail→fail | 12,944 | 14,809 | +14% | 1 | 1 | 0% | 3,131 | 6,121 | +95% | 0 | 0 | — |
case-22 | fail→fail | 12,092 | 11,999 | -1% | 1 | 1 | 0% | 2,339 | 4,676 | +100% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +5 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.